diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore new file mode 100644 index 00000000..3898a1cf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore @@ -0,0 +1,2 @@ +linux-3.2* +kernel-3.2* diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/Makefile b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/Makefile new file mode 100644 index 00000000..06577e25 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/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-lts/configs/arm-iproc-all/arm-iproc-all.config b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config new file mode 100644 index 00000000..8aa366c4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config @@ -0,0 +1,2432 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.2.84 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_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 + +# +# 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_HAVE_BPF_JIT=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 + +# +# 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=y +CONFIG_EDA_DEF_SIZE=0x04000000 +CONFIG_EDA_DEF_ALIGN=0x00100000 +# 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_EEPROM_ACCTON_AS4610_SFP=y +# 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_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_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=y +# 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_SENSORS_ACCTON_I2C_CPLD=y +CONFIG_SENSORS_ACCTON_AS4610_FAN=y +CONFIG_SENSORS_ACCTON_AS4610_PSU=y +CONFIG_SENSORS_YM2651Y=y +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_UNSAFE_RESUME=y +# 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_SDIO_UART=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_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=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +CONFIG_LEDS_ACCTON_AS4610=y +# CONFIG_LEDS_TRIGGERS is not set + +# +# LED Triggers +# +# 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 +# CONFIG_PM_DEVFREQ 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_INOTIFY_STACKFS=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_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_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set diff --git a/packages/base/any/kernels/3.2-lts/kconfig.mk b/packages/base/any/kernels/3.2-lts/kconfig.mk new file mode 100644 index 00000000..bbaa91cb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/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 := 84 +K_SUFFIX := +K_PATCH_DIR := $(THIS_DIR)/patches diff --git a/packages/base/any/kernels/3.2-lts/patches/Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/Makefile.patch new file mode 100644 index 00000000..fb3eefaf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/Makefile.patch @@ -0,0 +1,131 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch new file mode 100644 index 00000000..47cb8e3e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch @@ -0,0 +1,85 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch new file mode 100644 index 00000000..937a0d51 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch @@ -0,0 +1,28 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch new file mode 100644 index 00000000..f09f0cb3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch @@ -0,0 +1,13 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch new file mode 100644 index 00000000..7737f9ef --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch @@ -0,0 +1,256 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch new file mode 100644 index 00000000..61a1af5f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch @@ -0,0 +1,172 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch new file mode 100644 index 00000000..0d5d3e20 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch @@ -0,0 +1,65 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch new file mode 100644 index 00000000..5e544e90 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch @@ -0,0 +1,44 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch new file mode 100644 index 00000000..7757265a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch @@ -0,0 +1,2430 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch new file mode 100644 index 00000000..b4db0dac --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch new file mode 100644 index 00000000..bc5fd627 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch new file mode 100644 index 00000000..e308b092 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch @@ -0,0 +1,39 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch new file mode 100644 index 00000000..ecf5bf4c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch @@ -0,0 +1,13 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch new file mode 100644 index 00000000..6d188842 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch @@ -0,0 +1,39 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch new file mode 100644 index 00000000..b7f2c53d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch @@ -0,0 +1,15 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch new file mode 100644 index 00000000..d9d3312b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch @@ -0,0 +1,32 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch new file mode 100644 index 00000000..4c6c765c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch @@ -0,0 +1,74 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch new file mode 100644 index 00000000..48c61653 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch @@ -0,0 +1,27 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch new file mode 100644 index 00000000..1a88d2a2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch @@ -0,0 +1,49 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch new file mode 100644 index 00000000..1634a4d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch @@ -0,0 +1,70 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch new file mode 100644 index 00000000..d7548b4c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch @@ -0,0 +1,113 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch new file mode 100644 index 00000000..21af44ed --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch @@ -0,0 +1,8 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch new file mode 100644 index 00000000..60f3a4a0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch @@ -0,0 +1,21 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch new file mode 100644 index 00000000..126a2d42 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch @@ -0,0 +1,1103 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch new file mode 100644 index 00000000..2fa4f8f0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch @@ -0,0 +1,353 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch new file mode 100644 index 00000000..42454e17 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch @@ -0,0 +1,34 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch new file mode 100644 index 00000000..0f84f3b9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch @@ -0,0 +1,381 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch new file mode 100644 index 00000000..d6aa9c6c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch @@ -0,0 +1,729 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch new file mode 100644 index 00000000..ea279572 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch @@ -0,0 +1,92 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch new file mode 100644 index 00000000..d3f9f688 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch @@ -0,0 +1,830 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch new file mode 100644 index 00000000..90d7b97d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch @@ -0,0 +1,43 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch new file mode 100644 index 00000000..d52845fd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch @@ -0,0 +1,33 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch new file mode 100644 index 00000000..bf6dea5c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch @@ -0,0 +1,166 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch new file mode 100644 index 00000000..95057dd1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch @@ -0,0 +1,781 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch new file mode 100644 index 00000000..f694a373 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch @@ -0,0 +1,87 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch new file mode 100644 index 00000000..a0d18cd2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch @@ -0,0 +1,404 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch new file mode 100644 index 00000000..4a9e13f3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch @@ -0,0 +1,267 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch new file mode 100644 index 00000000..94925e96 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch @@ -0,0 +1,30 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch new file mode 100644 index 00000000..8a1283a1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch @@ -0,0 +1,63 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch new file mode 100644 index 00000000..5294b538 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch @@ -0,0 +1,33 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch new file mode 100644 index 00000000..9ed0bde4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch @@ -0,0 +1,172 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch new file mode 100644 index 00000000..eb6fa038 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch @@ -0,0 +1,33 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch new file mode 100644 index 00000000..02de3943 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch @@ -0,0 +1,808 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch new file mode 100644 index 00000000..8c902f15 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch @@ -0,0 +1,45 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch new file mode 100644 index 00000000..d29ac419 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch new file mode 100644 index 00000000..0be49e07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch @@ -0,0 +1,13 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch new file mode 100644 index 00000000..c3e4590f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch @@ -0,0 +1,131 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch new file mode 100644 index 00000000..df2243fa --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch @@ -0,0 +1,25 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch new file mode 100644 index 00000000..dbb38afa --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch @@ -0,0 +1,204 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch new file mode 100644 index 00000000..fe6390cd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch @@ -0,0 +1,110 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch new file mode 100644 index 00000000..0c54ffdd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch new file mode 100644 index 00000000..655fb068 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch new file mode 100644 index 00000000..8b475d7f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch @@ -0,0 +1,921 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch new file mode 100644 index 00000000..eaadc907 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch @@ -0,0 +1,196 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch new file mode 100644 index 00000000..f72b82cb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch @@ -0,0 +1,102 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch new file mode 100644 index 00000000..3d8ae55f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch @@ -0,0 +1,23 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch new file mode 100644 index 00000000..c17f2d9c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch @@ -0,0 +1,90 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch new file mode 100644 index 00000000..de6a28ae --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch @@ -0,0 +1,171 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch new file mode 100644 index 00000000..fb9d8c07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch @@ -0,0 +1,112 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch new file mode 100644 index 00000000..775242dd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch @@ -0,0 +1,153 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch new file mode 100644 index 00000000..38227ca9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch @@ -0,0 +1,70 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch new file mode 100644 index 00000000..7b6375ab --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch @@ -0,0 +1,74 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch new file mode 100644 index 00000000..6ea65748 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch @@ -0,0 +1,49 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch new file mode 100644 index 00000000..5018d5fc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch @@ -0,0 +1,41 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch new file mode 100644 index 00000000..0a644892 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch @@ -0,0 +1,57 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch new file mode 100644 index 00000000..dbb5963a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch @@ -0,0 +1,41 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch new file mode 100644 index 00000000..e16ade85 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch @@ -0,0 +1,105 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch new file mode 100644 index 00000000..811aa9ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch @@ -0,0 +1,36 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch new file mode 100644 index 00000000..9baa1080 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch @@ -0,0 +1,49 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch new file mode 100644 index 00000000..51ae7c3f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch @@ -0,0 +1,41 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch new file mode 100644 index 00000000..1d561ecd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch @@ -0,0 +1,32 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch new file mode 100644 index 00000000..609e8db9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch @@ -0,0 +1,154 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch new file mode 100644 index 00000000..6b781664 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch @@ -0,0 +1,255 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch new file mode 100644 index 00000000..5fe5c287 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch @@ -0,0 +1,54 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch new file mode 100644 index 00000000..eadc8b6b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch @@ -0,0 +1,84 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch new file mode 100644 index 00000000..c65d3a3e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch @@ -0,0 +1,73 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch new file mode 100644 index 00000000..16cfc53f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch @@ -0,0 +1,48 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch new file mode 100644 index 00000000..5e307d63 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch @@ -0,0 +1,42 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch new file mode 100644 index 00000000..d9cf6991 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch @@ -0,0 +1,55 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch new file mode 100644 index 00000000..62f00537 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch @@ -0,0 +1,31 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch new file mode 100644 index 00000000..957a06da --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch @@ -0,0 +1,60 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch new file mode 100644 index 00000000..b500b554 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch @@ -0,0 +1,109 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch new file mode 100644 index 00000000..b1db4e8d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch @@ -0,0 +1,609 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch new file mode 100644 index 00000000..03df92e2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch @@ -0,0 +1,82 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch new file mode 100644 index 00000000..0c8a55f3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch @@ -0,0 +1,66 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch new file mode 100644 index 00000000..04a1280f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch @@ -0,0 +1,50 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch new file mode 100644 index 00000000..8af39b07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch @@ -0,0 +1,33 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch new file mode 100644 index 00000000..58bb7484 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch @@ -0,0 +1,46 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch new file mode 100644 index 00000000..a3734f49 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch @@ -0,0 +1,24 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch new file mode 100644 index 00000000..a48d719f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch @@ -0,0 +1,26 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch new file mode 100644 index 00000000..01568c44 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch @@ -0,0 +1,126 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch new file mode 100644 index 00000000..184f887b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch @@ -0,0 +1,51 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch new file mode 100644 index 00000000..f42fd327 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch @@ -0,0 +1,144 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch new file mode 100644 index 00000000..cb9b2431 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch @@ -0,0 +1,42 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch new file mode 100644 index 00000000..a1535a7d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch @@ -0,0 +1,271 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch new file mode 100644 index 00000000..59f461ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch @@ -0,0 +1,177 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch new file mode 100644 index 00000000..2147e611 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch @@ -0,0 +1,181 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch new file mode 100644 index 00000000..83a19fa1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch @@ -0,0 +1,256 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch new file mode 100644 index 00000000..64772bed --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch @@ -0,0 +1,285 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch new file mode 100644 index 00000000..08fdfda7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch @@ -0,0 +1,9 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch new file mode 100644 index 00000000..7446d53f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch @@ -0,0 +1,11 @@ +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -136,4 +136,6 @@ source "drivers/hv/Kconfig" + + source "drivers/devfreq/Kconfig" + ++source "drivers/bcmdrivers/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 1b31421..9352f86 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch new file mode 100644 index 00000000..b8059ba5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch @@ -0,0 +1,9 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch new file mode 100644 index 00000000..e224dcf4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch @@ -0,0 +1,15 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch new file mode 100644 index 00000000..d419debd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch @@ -0,0 +1,22 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch new file mode 100644 index 00000000..a62f9068 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch @@ -0,0 +1,63 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch new file mode 100644 index 00000000..4f60648f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch @@ -0,0 +1,382 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch new file mode 100644 index 00000000..45591327 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch @@ -0,0 +1,53 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch new file mode 100644 index 00000000..7b22bd8d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch @@ -0,0 +1,166 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch new file mode 100644 index 00000000..acba66e3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch @@ -0,0 +1,363 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch new file mode 100644 index 00000000..8b5ed74e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch new file mode 100644 index 00000000..a3055586 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch @@ -0,0 +1,34 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch new file mode 100644 index 00000000..665e1f67 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch @@ -0,0 +1,28 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch new file mode 100644 index 00000000..a7fad20d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch @@ -0,0 +1,119 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch new file mode 100644 index 00000000..87dc9367 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch @@ -0,0 +1,20 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch new file mode 100644 index 00000000..1fb68a12 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch @@ -0,0 +1,90 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch new file mode 100644 index 00000000..690f6f13 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch @@ -0,0 +1,27 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch new file mode 100644 index 00000000..2342d0a7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch @@ -0,0 +1,10 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch new file mode 100644 index 00000000..1477e5ec --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch @@ -0,0 +1,21 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch new file mode 100644 index 00000000..fc4043ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch new file mode 100644 index 00000000..eca1fec7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch @@ -0,0 +1,109 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch new file mode 100644 index 00000000..2a1a11d8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch @@ -0,0 +1,892 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch new file mode 100644 index 00000000..30e54716 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch @@ -0,0 +1,608 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch new file mode 100644 index 00000000..ed8cb597 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch @@ -0,0 +1,42 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch new file mode 100644 index 00000000..a3c38ad0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch @@ -0,0 +1,12 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch new file mode 100644 index 00000000..1538385c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch @@ -0,0 +1,20 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch new file mode 100644 index 00000000..ac7108b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch @@ -0,0 +1,103 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch new file mode 100644 index 00000000..ffc9b767 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch @@ -0,0 +1,12 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch new file mode 100644 index 00000000..94c36635 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch @@ -0,0 +1,203 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch new file mode 100644 index 00000000..fca164c1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch @@ -0,0 +1,181 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch new file mode 100644 index 00000000..63a697c3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch @@ -0,0 +1,68 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch new file mode 100644 index 00000000..96f3dab2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch @@ -0,0 +1,36 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch new file mode 100644 index 00000000..f4d1f64e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch @@ -0,0 +1,12 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch new file mode 100644 index 00000000..9899ba6d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch @@ -0,0 +1,30 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch new file mode 100644 index 00000000..ea77478c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch @@ -0,0 +1,65 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch new file mode 100644 index 00000000..06210c14 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch @@ -0,0 +1,49 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch new file mode 100644 index 00000000..ab7eba0f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch @@ -0,0 +1,3902 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch new file mode 100644 index 00000000..a9a5e0ea --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch @@ -0,0 +1,74 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch new file mode 100644 index 00000000..7420f10a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch @@ -0,0 +1,905 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch new file mode 100644 index 00000000..ed0cafc6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch @@ -0,0 +1,323 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch new file mode 100644 index 00000000..3d5909de --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch @@ -0,0 +1,2573 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch new file mode 100644 index 00000000..394cd4be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch @@ -0,0 +1,74 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch new file mode 100644 index 00000000..100147fb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch @@ -0,0 +1,59 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch new file mode 100644 index 00000000..d236fb0a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch @@ -0,0 +1,389 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch new file mode 100644 index 00000000..4f5012df --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch @@ -0,0 +1,323 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch new file mode 100644 index 00000000..15007d3f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch @@ -0,0 +1,34 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch new file mode 100644 index 00000000..1bebaba8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch @@ -0,0 +1,361 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch new file mode 100644 index 00000000..ba71ec98 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch @@ -0,0 +1,128 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch new file mode 100644 index 00000000..b7bb9878 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch @@ -0,0 +1,342 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch new file mode 100644 index 00000000..c8295ce1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch @@ -0,0 +1,868 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch new file mode 100644 index 00000000..daeb4572 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch @@ -0,0 +1,330 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch new file mode 100644 index 00000000..adaa42e3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch @@ -0,0 +1,94 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch new file mode 100644 index 00000000..33bbb94e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch @@ -0,0 +1,93 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch new file mode 100644 index 00000000..9a2fd4d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch @@ -0,0 +1,56 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch new file mode 100644 index 00000000..ff31dd8b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch @@ -0,0 +1,123 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch new file mode 100644 index 00000000..09401730 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch @@ -0,0 +1,59 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch new file mode 100644 index 00000000..9ab89f01 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch @@ -0,0 +1,273 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch new file mode 100644 index 00000000..e93ef478 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch @@ -0,0 +1,51 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch new file mode 100644 index 00000000..41b215f9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch @@ -0,0 +1,52 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch new file mode 100644 index 00000000..794c4995 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch @@ -0,0 +1,84 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch new file mode 100644 index 00000000..64223745 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch @@ -0,0 +1,84 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch new file mode 100644 index 00000000..f6f227d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch @@ -0,0 +1,312 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch new file mode 100644 index 00000000..cf3bb855 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch @@ -0,0 +1,301 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch new file mode 100644 index 00000000..f1095b67 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch @@ -0,0 +1,87 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch new file mode 100644 index 00000000..bb7540b5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch @@ -0,0 +1,38 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch new file mode 100644 index 00000000..09d863ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch @@ -0,0 +1,46 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch new file mode 100644 index 00000000..39b3425b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch @@ -0,0 +1,209 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch new file mode 100644 index 00000000..21ea547c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch @@ -0,0 +1,232 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch new file mode 100644 index 00000000..05d7cfe0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch @@ -0,0 +1,274 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch new file mode 100644 index 00000000..24d77878 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch @@ -0,0 +1,61 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch new file mode 100644 index 00000000..b6ad28b8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch @@ -0,0 +1,555 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch new file mode 100644 index 00000000..2d6c06d6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch @@ -0,0 +1,884 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch new file mode 100644 index 00000000..a23cc894 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch @@ -0,0 +1,134 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch new file mode 100644 index 00000000..567c2854 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch @@ -0,0 +1,870 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch new file mode 100644 index 00000000..d7a1c5b8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch @@ -0,0 +1,462 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch new file mode 100644 index 00000000..c15e50f8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch @@ -0,0 +1,128 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch new file mode 100644 index 00000000..6e84f000 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch @@ -0,0 +1,82 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch new file mode 100644 index 00000000..a08289ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch @@ -0,0 +1,305 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch new file mode 100644 index 00000000..ecdecc3d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch @@ -0,0 +1,52 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch new file mode 100644 index 00000000..846b3b68 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch @@ -0,0 +1,51 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch new file mode 100644 index 00000000..56fbd0d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch @@ -0,0 +1,301 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch new file mode 100644 index 00000000..cac11272 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch @@ -0,0 +1,164 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch new file mode 100644 index 00000000..71abb6a9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch @@ -0,0 +1,566 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch new file mode 100644 index 00000000..b1d35542 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch @@ -0,0 +1,308 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch new file mode 100644 index 00000000..8a200152 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch @@ -0,0 +1,102 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch new file mode 100644 index 00000000..a97882b5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch @@ -0,0 +1,44 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch new file mode 100644 index 00000000..8c43025d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch @@ -0,0 +1,46 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch new file mode 100644 index 00000000..ba57efee --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch @@ -0,0 +1,323 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch new file mode 100644 index 00000000..a731d86b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch @@ -0,0 +1,142 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch new file mode 100644 index 00000000..7e1e5224 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch @@ -0,0 +1,275 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch new file mode 100644 index 00000000..085aa791 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch @@ -0,0 +1,101 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch new file mode 100644 index 00000000..21565d1c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch @@ -0,0 +1,985 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch new file mode 100644 index 00000000..b31d6c27 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch @@ -0,0 +1,668 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch new file mode 100644 index 00000000..3b2fe58c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch @@ -0,0 +1,151 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch new file mode 100644 index 00000000..c5b9ea16 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch @@ -0,0 +1,77 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch new file mode 100644 index 00000000..70c4c44f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch @@ -0,0 +1,82 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch new file mode 100644 index 00000000..7fd8f492 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch @@ -0,0 +1,575 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch new file mode 100644 index 00000000..c4cab740 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch @@ -0,0 +1,2362 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch new file mode 100644 index 00000000..c6e4015b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch @@ -0,0 +1,50 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch new file mode 100644 index 00000000..f644b264 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch @@ -0,0 +1,10 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch new file mode 100644 index 00000000..c52212b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch @@ -0,0 +1,15 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch new file mode 100644 index 00000000..e5acb184 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch @@ -0,0 +1,112 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch new file mode 100644 index 00000000..74d02b31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch @@ -0,0 +1,319 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch new file mode 100644 index 00000000..91960fdb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch @@ -0,0 +1,211 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch new file mode 100644 index 00000000..a75d41a8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch @@ -0,0 +1,107 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch new file mode 100644 index 00000000..baa492ab --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch @@ -0,0 +1,208 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch new file mode 100644 index 00000000..31e5a251 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch @@ -0,0 +1,73 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch new file mode 100644 index 00000000..c979b7b4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch @@ -0,0 +1,175 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch new file mode 100644 index 00000000..2d57bad9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch @@ -0,0 +1,2523 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch new file mode 100644 index 00000000..8010ca8b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch @@ -0,0 +1,282 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch new file mode 100644 index 00000000..cecf2c96 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch @@ -0,0 +1,299 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch new file mode 100644 index 00000000..e49d6ea2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch @@ -0,0 +1,409 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch new file mode 100644 index 00000000..725e16a0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch @@ -0,0 +1,199 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch new file mode 100644 index 00000000..0c4ab04c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch @@ -0,0 +1,262 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch new file mode 100644 index 00000000..98448ab4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch @@ -0,0 +1,92 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch new file mode 100644 index 00000000..048141c0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch @@ -0,0 +1,458 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch new file mode 100644 index 00000000..9db6e3c3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch @@ -0,0 +1,4889 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch new file mode 100644 index 00000000..1449a31e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch @@ -0,0 +1,1269 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch new file mode 100644 index 00000000..b75529ac --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch @@ -0,0 +1,515 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch new file mode 100644 index 00000000..c937af31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch @@ -0,0 +1,740 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch new file mode 100644 index 00000000..81e750b4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch @@ -0,0 +1,434 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch new file mode 100644 index 00000000..49a3a6df --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch @@ -0,0 +1,487 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch new file mode 100644 index 00000000..1d506247 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch @@ -0,0 +1,3797 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch new file mode 100644 index 00000000..db8ff971 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch @@ -0,0 +1,1554 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch new file mode 100644 index 00000000..2469a414 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch @@ -0,0 +1,5115 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch new file mode 100644 index 00000000..4f055f3f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch @@ -0,0 +1,3259 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch new file mode 100644 index 00000000..3ec53d24 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch @@ -0,0 +1,3575 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch new file mode 100644 index 00000000..cbd0df8a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch @@ -0,0 +1,231 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch new file mode 100644 index 00000000..4cb1532e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch @@ -0,0 +1,70 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch new file mode 100644 index 00000000..eb643cc9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch @@ -0,0 +1,32 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch new file mode 100644 index 00000000..a8c6066e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch @@ -0,0 +1,71 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch new file mode 100644 index 00000000..e13f5896 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch @@ -0,0 +1,32 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch new file mode 100644 index 00000000..890fab3b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch @@ -0,0 +1,71 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch new file mode 100644 index 00000000..81057fe7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch @@ -0,0 +1,32 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch new file mode 100644 index 00000000..58984b12 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch @@ -0,0 +1,1719 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch new file mode 100644 index 00000000..be506634 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch @@ -0,0 +1,73 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch new file mode 100644 index 00000000..0d6f74ca --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch @@ -0,0 +1,32 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch new file mode 100644 index 00000000..cbeb1ff7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch @@ -0,0 +1,371 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch new file mode 100644 index 00000000..80b67dbd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch @@ -0,0 +1,1542 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch new file mode 100644 index 00000000..15ce4216 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch @@ -0,0 +1,265 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch new file mode 100644 index 00000000..d97df5b0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch @@ -0,0 +1,32 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch new file mode 100644 index 00000000..cabe97c8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch @@ -0,0 +1,18 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch new file mode 100644 index 00000000..943286e0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch @@ -0,0 +1,17 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch new file mode 100644 index 00000000..af195cbb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch new file mode 100644 index 00000000..2fd2834a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch @@ -0,0 +1,750 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch new file mode 100644 index 00000000..63f451cd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch @@ -0,0 +1,107 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch new file mode 100644 index 00000000..d4d59972 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch @@ -0,0 +1,408 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch new file mode 100644 index 00000000..ba3066b5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch @@ -0,0 +1,113 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch new file mode 100644 index 00000000..1a8e21f5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch @@ -0,0 +1,265 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch new file mode 100644 index 00000000..9b622fc5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch @@ -0,0 +1,7 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch new file mode 100644 index 00000000..584088e1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch new file mode 100644 index 00000000..28f46181 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch new file mode 100644 index 00000000..0306d5be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch new file mode 100644 index 00000000..70a566e5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch @@ -0,0 +1,591 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch new file mode 100644 index 00000000..562b1c30 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch @@ -0,0 +1,88 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch new file mode 100644 index 00000000..a0397644 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch @@ -0,0 +1,50 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch new file mode 100644 index 00000000..04230fa1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch new file mode 100644 index 00000000..00293770 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch @@ -0,0 +1,30 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch new file mode 100644 index 00000000..f3def015 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch @@ -0,0 +1,8 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch new file mode 100644 index 00000000..d59b9a7b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch @@ -0,0 +1,1739 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch new file mode 100644 index 00000000..38ee39b6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch new file mode 100644 index 00000000..7febc0e0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch @@ -0,0 +1,15 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch new file mode 100644 index 00000000..dae1af6d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch new file mode 100644 index 00000000..a14e656d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch @@ -0,0 +1,67 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch new file mode 100644 index 00000000..48910901 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch new file mode 100644 index 00000000..8864744e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch new file mode 100644 index 00000000..cf9178bd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch new file mode 100644 index 00000000..edeab9b8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch @@ -0,0 +1,417 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch new file mode 100644 index 00000000..9ae130eb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch @@ -0,0 +1,581 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch new file mode 100644 index 00000000..d119602b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch new file mode 100644 index 00000000..f5204dc9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch @@ -0,0 +1,78 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch new file mode 100644 index 00000000..90266a9c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch new file mode 100644 index 00000000..dfa76075 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch @@ -0,0 +1,1813 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch new file mode 100644 index 00000000..1217b7b1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch new file mode 100644 index 00000000..754166ae --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch @@ -0,0 +1,14 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch new file mode 100644 index 00000000..bb58dce0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch @@ -0,0 +1,9 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch new file mode 100644 index 00000000..7c597837 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch @@ -0,0 +1,2049 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch new file mode 100644 index 00000000..d6f033eb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch @@ -0,0 +1,195 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch new file mode 100644 index 00000000..a6c8d2ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch @@ -0,0 +1,53 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch new file mode 100644 index 00000000..17eac90f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch @@ -0,0 +1,296 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch new file mode 100644 index 00000000..797dc6c0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch @@ -0,0 +1,10 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch new file mode 100644 index 00000000..51aa314a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch @@ -0,0 +1,12 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch new file mode 100644 index 00000000..45041229 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch @@ -0,0 +1,8 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch new file mode 100644 index 00000000..3d2f4445 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch @@ -0,0 +1,485 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch new file mode 100644 index 00000000..d11e8cab --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch @@ -0,0 +1,31 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch new file mode 100644 index 00000000..09f5fc32 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch @@ -0,0 +1,389 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch new file mode 100644 index 00000000..c47146dc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch @@ -0,0 +1,320 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch new file mode 100644 index 00000000..8aa7e9ee --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch @@ -0,0 +1,57 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch new file mode 100644 index 00000000..eccb0994 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch @@ -0,0 +1,10 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch new file mode 100644 index 00000000..cd1e4edb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch @@ -0,0 +1,13 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch new file mode 100644 index 00000000..43a19555 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch @@ -0,0 +1,8 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch new file mode 100644 index 00000000..11fe49be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch @@ -0,0 +1,496 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch new file mode 100644 index 00000000..18fdd68b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch @@ -0,0 +1,53 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch new file mode 100644 index 00000000..6f8f5282 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch @@ -0,0 +1,29 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch new file mode 100644 index 00000000..11aae084 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch @@ -0,0 +1,156 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch new file mode 100644 index 00000000..0a475e16 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch @@ -0,0 +1,32 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch new file mode 100644 index 00000000..050733ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch @@ -0,0 +1,42 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch new file mode 100644 index 00000000..dfd818e4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch @@ -0,0 +1,16 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch new file mode 100644 index 00000000..b2b34773 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch @@ -0,0 +1,16 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch new file mode 100644 index 00000000..8982f94b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch @@ -0,0 +1,49 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch new file mode 100644 index 00000000..375f0bdf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch new file mode 100644 index 00000000..a6d1b572 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch @@ -0,0 +1,837 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch new file mode 100644 index 00000000..28224943 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch @@ -0,0 +1,195 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch new file mode 100644 index 00000000..c6d04ba8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch @@ -0,0 +1,87 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch new file mode 100644 index 00000000..64dc1603 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch @@ -0,0 +1,28 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch new file mode 100644 index 00000000..d6b2b379 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch @@ -0,0 +1,35 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch new file mode 100644 index 00000000..35523d22 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch @@ -0,0 +1,26 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch new file mode 100644 index 00000000..e24eea5c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch @@ -0,0 +1,40 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch new file mode 100644 index 00000000..33486dc7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch @@ -0,0 +1,1087 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch new file mode 100644 index 00000000..a2de0980 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch @@ -0,0 +1,1090 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch new file mode 100644 index 00000000..061d7fe7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch @@ -0,0 +1,880 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch new file mode 100644 index 00000000..1febfc34 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch @@ -0,0 +1,189 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch new file mode 100644 index 00000000..d615fec6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch @@ -0,0 +1,666 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch new file mode 100644 index 00000000..00480ae1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch @@ -0,0 +1,456 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch new file mode 100644 index 00000000..3460088b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch @@ -0,0 +1,707 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch new file mode 100644 index 00000000..1aef0cb1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch @@ -0,0 +1,39 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch new file mode 100644 index 00000000..0e18bea0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch new file mode 100644 index 00000000..4e5730fb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch @@ -0,0 +1,89 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch new file mode 100644 index 00000000..76cb56ca --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch @@ -0,0 +1,106 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch new file mode 100644 index 00000000..ac9da2ad --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch @@ -0,0 +1,20 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch new file mode 100644 index 00000000..724ae420 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch @@ -0,0 +1,267 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch new file mode 100644 index 00000000..9de4b98d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch @@ -0,0 +1,94 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch new file mode 100644 index 00000000..4f887491 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch @@ -0,0 +1,38 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch new file mode 100644 index 00000000..ef889a76 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch @@ -0,0 +1,39 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch new file mode 100644 index 00000000..121c39bf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch @@ -0,0 +1,21 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch new file mode 100644 index 00000000..d34d15cc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch @@ -0,0 +1,112 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch new file mode 100644 index 00000000..e702e64f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch @@ -0,0 +1,21 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch new file mode 100644 index 00000000..192ab21a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch @@ -0,0 +1,13 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch new file mode 100644 index 00000000..c4eb589c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch new file mode 100644 index 00000000..ceeff4bf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch new file mode 100644 index 00000000..c36a8f06 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch @@ -0,0 +1,45 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch new file mode 100644 index 00000000..ca38ba7a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch @@ -0,0 +1,60 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch new file mode 100644 index 00000000..57927135 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch new file mode 100644 index 00000000..3e00c18f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch @@ -0,0 +1,332 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch new file mode 100644 index 00000000..570d67a3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch @@ -0,0 +1,228 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch new file mode 100644 index 00000000..f740b763 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch @@ -0,0 +1,38 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch new file mode 100644 index 00000000..fbd3a616 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch new file mode 100644 index 00000000..4065e220 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch @@ -0,0 +1,205 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch new file mode 100644 index 00000000..79e59f45 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch @@ -0,0 +1,200 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch new file mode 100644 index 00000000..51e87f65 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch @@ -0,0 +1,1231 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch new file mode 100644 index 00000000..1efb818c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch @@ -0,0 +1,18 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch new file mode 100644 index 00000000..03046ecf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch @@ -0,0 +1,165 @@ +--- /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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch new file mode 100644 index 00000000..4ddf4f33 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch @@ -0,0 +1,17 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch new file mode 100644 index 00000000..ec4efbeb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch @@ -0,0 +1,25 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch new file mode 100644 index 00000000..965a594f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch @@ -0,0 +1,15 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch new file mode 100644 index 00000000..ebd911b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch @@ -0,0 +1,20 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch new file mode 100644 index 00000000..cfa4bbba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch @@ -0,0 +1,143 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch new file mode 100644 index 00000000..e8466966 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch @@ -0,0 +1,31 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch new file mode 100644 index 00000000..650f9777 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch new file mode 100644 index 00000000..a32b7f2c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch @@ -0,0 +1,13 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch new file mode 100644 index 00000000..6f4218e7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch @@ -0,0 +1,27 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch new file mode 100644 index 00000000..9cefb7ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch @@ -0,0 +1,18 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch new file mode 100644 index 00000000..e0a0f3a1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch @@ -0,0 +1,65 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch new file mode 100644 index 00000000..38493852 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch @@ -0,0 +1,98 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch new file mode 100644 index 00000000..1be9c137 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch @@ -0,0 +1,21 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch new file mode 100644 index 00000000..1619909a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch @@ -0,0 +1,17 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch new file mode 100644 index 00000000..042f01a3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch @@ -0,0 +1,50 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch new file mode 100644 index 00000000..5fefddcb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch @@ -0,0 +1,77 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch new file mode 100644 index 00000000..e24a668f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch @@ -0,0 +1,51 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch new file mode 100644 index 00000000..01b0808b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch @@ -0,0 +1,342 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch new file mode 100644 index 00000000..9be126bd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch @@ -0,0 +1,48 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch new file mode 100644 index 00000000..9ea2800d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch @@ -0,0 +1,41 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch new file mode 100644 index 00000000..690c2f55 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch @@ -0,0 +1,210 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch new file mode 100644 index 00000000..97701622 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch @@ -0,0 +1,190 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch new file mode 100644 index 00000000..57b12feb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch @@ -0,0 +1,23 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch new file mode 100644 index 00000000..3616dd54 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch @@ -0,0 +1,30 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch new file mode 100644 index 00000000..f8b91a59 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch @@ -0,0 +1,14 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch new file mode 100644 index 00000000..b0534ef9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch @@ -0,0 +1,63 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch new file mode 100644 index 00000000..5b3fa398 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch @@ -0,0 +1,17 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch new file mode 100644 index 00000000..893450ee --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch @@ -0,0 +1,86 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch new file mode 100644 index 00000000..711e6b90 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch @@ -0,0 +1,170 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch new file mode 100644 index 00000000..56c2829d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch @@ -0,0 +1,32 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch new file mode 100644 index 00000000..a29872bd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch @@ -0,0 +1,161 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch new file mode 100644 index 00000000..6bdc0448 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch @@ -0,0 +1,16 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch new file mode 100644 index 00000000..f3c44456 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch @@ -0,0 +1,19 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch new file mode 100644 index 00000000..c78a7d1e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch @@ -0,0 +1,28 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch new file mode 100644 index 00000000..0b3b093e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch @@ -0,0 +1,16 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch new file mode 100644 index 00000000..6296779d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch @@ -0,0 +1,63 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch new file mode 100644 index 00000000..e38f7682 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch @@ -0,0 +1,91 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch new file mode 100644 index 00000000..89df7fc5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch @@ -0,0 +1,17 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch new file mode 100644 index 00000000..0755eee1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch @@ -0,0 +1,29 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch new file mode 100644 index 00000000..8721ee88 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch @@ -0,0 +1,27 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch new file mode 100644 index 00000000..4e4c1da0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch @@ -0,0 +1,17 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch new file mode 100644 index 00000000..7b347562 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch @@ -0,0 +1,22 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch new file mode 100644 index 00000000..8e87edf2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch @@ -0,0 +1,16 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch new file mode 100644 index 00000000..8f3583e8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch @@ -0,0 +1,17 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch new file mode 100644 index 00000000..220a3c31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch @@ -0,0 +1,16 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch new file mode 100644 index 00000000..d71095df --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch @@ -0,0 +1,25 @@ +--- 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 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch new file mode 100644 index 00000000..26e702b4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch @@ -0,0 +1,24 @@ +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -545,6 +545,19 @@ config I6300ESB_WDT + To compile this driver as a module, choose M here: the + module will be called i6300esb. + ++config IE6XX_WDT ++ tristate "Intel Atom E6xx Watchdog" ++ depends on X86 && PCI ++ select WATCHDOG_CORE ++ select MFD_CORE ++ select LPC_SCH ++ ---help--- ++ Hardware driver for the watchdog timer built into the Intel ++ Atom E6XX (TunnelCreek) processor. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ie6xx_wdt. ++ + config INTEL_SCU_WATCHDOG + bool "Intel SCU Watchdog for Mobile Platforms" + depends on X86_MRST +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +index fe893e9..8f591c5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch new file mode 100644 index 00000000..4ec330d2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch @@ -0,0 +1,12 @@ +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -81,6 +81,7 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o + obj-$(CONFIG_IBMASR) += ibmasr.o + obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o + obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o ++obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o + obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o + ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) + obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o +diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c +index 337265b..2af9c3a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch new file mode 100644 index 00000000..d34fcb65 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch @@ -0,0 +1,314 @@ +--- a/drivers/watchdog/booke_wdt.c ++++ b/drivers/watchdog/booke_wdt.c +@@ -12,16 +12,13 @@ + * option) any later version. + */ + ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ + #include +-#include + #include +-#include +-#include + #include +-#include + + #include +-#include + #include + #include + +@@ -33,10 +30,8 @@ + * occur, and the final time the board will reset. + */ + +-u32 booke_wdt_enabled; +-u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; + +-#ifdef CONFIG_FSL_BOOKE ++#ifdef CONFIG_PPC_FSL_BOOK3E + #define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) + #define WDTP_MASK (WDTP(0x3f)) + #else +@@ -44,7 +39,12 @@ u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; + #define WDTP_MASK (TCR_WP_MASK) + #endif + +-static DEFINE_SPINLOCK(booke_wdt_lock); ++static bool booke_wdt_enabled; ++module_param(booke_wdt_enabled, bool, 0); ++static int booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; ++module_param(booke_wdt_period, int, 0); ++ ++#ifdef CONFIG_PPC_FSL_BOOK3E + + /* For the specified period, determine the number of seconds + * corresponding to the reset time. There will be a watchdog +@@ -85,20 +85,39 @@ static unsigned int sec_to_period(unsigned int secs) + return 0; + } + ++#define MAX_WDT_TIMEOUT period_to_sec(1) ++ ++#else /* CONFIG_PPC_FSL_BOOK3E */ ++ ++static unsigned long long period_to_sec(unsigned int period) ++{ ++ return period; ++} ++ ++static unsigned int sec_to_period(unsigned int secs) ++{ ++ return secs; ++} ++ ++#define MAX_WDT_TIMEOUT 3 /* from Kconfig */ ++ ++#endif /* !CONFIG_PPC_FSL_BOOK3E */ ++ + static void __booke_wdt_set(void *data) + { + u32 val; ++ struct watchdog_device *wdog = data; + + val = mfspr(SPRN_TCR); + val &= ~WDTP_MASK; +- val |= WDTP(booke_wdt_period); ++ val |= WDTP(sec_to_period(wdog->timeout)); + + mtspr(SPRN_TCR, val); + } + +-static void booke_wdt_set(void) ++static void booke_wdt_set(void *data) + { +- on_each_cpu(__booke_wdt_set, NULL, 0); ++ on_each_cpu(__booke_wdt_set, data, 0); + } + + static void __booke_wdt_ping(void *data) +@@ -106,20 +125,23 @@ static void __booke_wdt_ping(void *data) + mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); + } + +-static void booke_wdt_ping(void) ++static int booke_wdt_ping(struct watchdog_device *wdog) + { + on_each_cpu(__booke_wdt_ping, NULL, 0); ++ ++ return 0; + } + + static void __booke_wdt_enable(void *data) + { + u32 val; ++ struct watchdog_device *wdog = data; + + /* clear status before enabling watchdog */ + __booke_wdt_ping(NULL); + val = mfspr(SPRN_TCR); + val &= ~WDTP_MASK; +- val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); ++ val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(sec_to_period(wdog->timeout))); + + mtspr(SPRN_TCR, val); + } +@@ -145,149 +167,73 @@ static void __booke_wdt_disable(void *data) + + } + +-static ssize_t booke_wdt_write(struct file *file, const char __user *buf, +- size_t count, loff_t *ppos) ++static int booke_wdt_start(struct watchdog_device *wdog) + { +- booke_wdt_ping(); +- return count; +-} +- +-static struct watchdog_info ident = { +- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +- .identity = "PowerPC Book-E Watchdog", +-}; +- +-static long booke_wdt_ioctl(struct file *file, +- unsigned int cmd, unsigned long arg) +-{ +- u32 tmp = 0; +- u32 __user *p = (u32 __user *)arg; +- +- switch (cmd) { +- case WDIOC_GETSUPPORT: +- if (copy_to_user((void *)arg, &ident, sizeof(ident))) +- return -EFAULT; +- case WDIOC_GETSTATUS: +- return put_user(0, p); +- case WDIOC_GETBOOTSTATUS: +- /* XXX: something is clearing TSR */ +- tmp = mfspr(SPRN_TSR) & TSR_WRS(3); +- /* returns CARDRESET if last reset was caused by the WDT */ +- return (tmp ? WDIOF_CARDRESET : 0); +- case WDIOC_SETOPTIONS: +- if (get_user(tmp, p)) +- return -EINVAL; +- if (tmp == WDIOS_ENABLECARD) { +- booke_wdt_ping(); +- break; +- } else +- return -EINVAL; +- return 0; +- case WDIOC_KEEPALIVE: +- booke_wdt_ping(); +- return 0; +- case WDIOC_SETTIMEOUT: +- if (get_user(tmp, p)) +- return -EFAULT; +-#ifdef CONFIG_FSL_BOOKE +- /* period of 1 gives the largest possible timeout */ +- if (tmp > period_to_sec(1)) +- return -EINVAL; +- booke_wdt_period = sec_to_period(tmp); +-#else +- booke_wdt_period = tmp; +-#endif +- booke_wdt_set(); +- return 0; +- case WDIOC_GETTIMEOUT: +- return put_user(booke_wdt_period, p); +- default: +- return -ENOTTY; +- } ++ on_each_cpu(__booke_wdt_enable, wdog, 0); ++ pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout); + + return 0; + } + +-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */ +-static unsigned long wdt_is_active; +- +-static int booke_wdt_open(struct inode *inode, struct file *file) ++static int booke_wdt_stop(struct watchdog_device *wdog) + { +- /* /dev/watchdog can only be opened once */ +- if (test_and_set_bit(0, &wdt_is_active)) +- return -EBUSY; +- +- spin_lock(&booke_wdt_lock); +- if (booke_wdt_enabled == 0) { +- booke_wdt_enabled = 1; +- on_each_cpu(__booke_wdt_enable, NULL, 0); +- pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n", +- period_to_sec(booke_wdt_period)); +- } +- spin_unlock(&booke_wdt_lock); ++ on_each_cpu(__booke_wdt_disable, NULL, 0); ++ pr_debug("watchdog disabled\n"); + +- return nonseekable_open(inode, file); ++ return 0; + } + +-static int booke_wdt_release(struct inode *inode, struct file *file) ++static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, ++ unsigned int timeout) + { +-#ifndef CONFIG_WATCHDOG_NOWAYOUT +- /* Normally, the watchdog is disabled when /dev/watchdog is closed, but +- * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the +- * watchdog should remain enabled. So we disable it only if +- * CONFIG_WATCHDOG_NOWAYOUT is not defined. +- */ +- on_each_cpu(__booke_wdt_disable, NULL, 0); +- booke_wdt_enabled = 0; +- pr_debug("booke_wdt: watchdog disabled\n"); +-#endif +- +- clear_bit(0, &wdt_is_active); ++ if (timeout > MAX_WDT_TIMEOUT) ++ return -EINVAL; ++ wdt_dev->timeout = timeout; ++ booke_wdt_set(wdt_dev); + + return 0; + } + +-static const struct file_operations booke_wdt_fops = { ++static struct watchdog_info booke_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++ .identity = "PowerPC Book-E Watchdog", ++}; ++ ++static struct watchdog_ops booke_wdt_ops = { + .owner = THIS_MODULE, +- .llseek = no_llseek, +- .write = booke_wdt_write, +- .unlocked_ioctl = booke_wdt_ioctl, +- .open = booke_wdt_open, +- .release = booke_wdt_release, ++ .start = booke_wdt_start, ++ .stop = booke_wdt_stop, ++ .ping = booke_wdt_ping, ++ .set_timeout = booke_wdt_set_timeout, + }; + +-static struct miscdevice booke_wdt_miscdev = { +- .minor = WATCHDOG_MINOR, +- .name = "watchdog", +- .fops = &booke_wdt_fops, ++static struct watchdog_device booke_wdt_dev = { ++ .info = &booke_wdt_info, ++ .ops = &booke_wdt_ops, ++ .min_timeout = 1, ++ .max_timeout = 0xFFFFFFFF + }; + + static void __exit booke_wdt_exit(void) + { +- misc_deregister(&booke_wdt_miscdev); ++ watchdog_unregister_device(&booke_wdt_dev); + } + + static int __init booke_wdt_init(void) + { + int ret = 0; ++ bool nowayout = WATCHDOG_NOWAYOUT; + +- pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n"); +- ident.firmware_version = cur_cpu_spec->pvr_value; +- +- ret = misc_register(&booke_wdt_miscdev); +- if (ret) { +- pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n", +- WATCHDOG_MINOR, ret); +- return ret; +- } ++ pr_info("powerpc book-e watchdog driver loaded\n"); ++ booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value; ++ booke_wdt_set_timeout(&booke_wdt_dev, ++ period_to_sec(booke_wdt_period)); ++ booke_wdt_dev.timeout = period_to_sec(booke_wdt_period); ++ watchdog_set_nowayout(&booke_wdt_dev, nowayout); ++ if (booke_wdt_enabled) ++ booke_wdt_start(&booke_wdt_dev); + +- spin_lock(&booke_wdt_lock); +- if (booke_wdt_enabled == 1) { +- pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n", +- period_to_sec(booke_wdt_period)); +- on_each_cpu(__booke_wdt_enable, NULL, 0); +- } +- spin_unlock(&booke_wdt_lock); ++ ret = watchdog_register_device(&booke_wdt_dev); + + return ret; + } +@@ -295,5 +241,6 @@ static int __init booke_wdt_init(void) + module_init(booke_wdt_init); + module_exit(booke_wdt_exit); + ++MODULE_ALIAS("booke_wdt"); + MODULE_DESCRIPTION("PowerPC Book-E watchdog driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c +index bdf401b..590d62a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch new file mode 100644 index 00000000..9286a04d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch @@ -0,0 +1,283 @@ +--- a/drivers/watchdog/iTCO_wdt.c ++++ b/drivers/watchdog/iTCO_wdt.c +@@ -128,6 +128,7 @@ enum iTCO_chipsets { + TCO_DH89XXCC, /* DH89xxCC */ + TCO_PPT, /* Panther Point */ + TCO_LPT, /* Lynx Point */ ++ TCO_AVN, /* Avoton */ + }; + + static struct { +@@ -192,6 +193,7 @@ static struct { + {"DH89xxCC", 2}, + {"Panther Point", 2}, + {"Lynx Point", 2}, ++ {"Avoton", 3}, + {NULL, 0} + }; + +@@ -334,6 +336,10 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { + { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT}, ++ { PCI_VDEVICE(INTEL, 0x1f38), TCO_AVN}, ++ { PCI_VDEVICE(INTEL, 0x1f39), TCO_AVN}, ++ { PCI_VDEVICE(INTEL, 0x1f3a), TCO_AVN}, ++ { PCI_VDEVICE(INTEL, 0x1f3b), TCO_AVN}, + { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT}, +@@ -394,8 +400,12 @@ static struct { /* this is private data for the iTCO_wdt device */ + unsigned int iTCO_version; + /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ + unsigned long ACPIBASE; +- /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ +- unsigned long __iomem *gcs; ++ /* ++ * NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2), ++ * or memory-mapped PMC register bit 4 (TCO version 3). ++ */ ++ unsigned long __iomem *gcs_pmc; ++ + /* the lock for io operations */ + spinlock_t io_lock; + /* the PCI-device */ +@@ -428,11 +438,19 @@ MODULE_PARM_DESC(turn_SMI_watchdog_clear_off, + * Some TCO specific functions + */ + +-static inline unsigned int seconds_to_ticks(int seconds) ++/* ++ * The iTCO v1 and v2's internal timer is stored as ticks which decrement ++ * every 0.6 seconds. v3's internal timer is stored as seconds (some ++ * datasheets incorrectly state 0.6 seconds). ++ */ ++static inline unsigned int seconds_to_ticks(int secs) ++{ ++ return iTCO_wdt_private.iTCO_version == 3 ? secs : (secs * 10) / 6; ++} ++ ++static inline unsigned int ticks_to_seconds(int ticks) + { +- /* the internal timer is stored as ticks which decrement +- * every 0.6 seconds */ +- return (seconds * 10) / 6; ++ return iTCO_wdt_private.iTCO_version == 3 ? ticks : (ticks * 6) / 10; + } + + static void iTCO_wdt_set_NO_REBOOT_bit(void) +@@ -440,10 +458,14 @@ static void iTCO_wdt_set_NO_REBOOT_bit(void) + u32 val32; + + /* Set the NO_REBOOT bit: this disables reboots */ +- if (iTCO_wdt_private.iTCO_version == 2) { +- val32 = readl(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version == 3) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); ++ val32 |= 0x00000010; ++ writel(val32, iTCO_wdt_private.gcs_pmc); ++ } else if (iTCO_wdt_private.iTCO_version >= 2) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); + val32 |= 0x00000020; +- writel(val32, iTCO_wdt_private.gcs); ++ writel(val32, iTCO_wdt_private.gcs_pmc); + } else if (iTCO_wdt_private.iTCO_version == 1) { + pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32); + val32 |= 0x00000002; +@@ -457,12 +479,20 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void) + u32 val32; + + /* Unset the NO_REBOOT bit: this enables reboots */ +- if (iTCO_wdt_private.iTCO_version == 2) { +- val32 = readl(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version == 3) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); ++ val32 &= 0xffffffef; ++ writel(val32, iTCO_wdt_private.gcs_pmc); ++ ++ val32 = readl(iTCO_wdt_private.gcs_pmc); ++ if (val32 & 0x00000010) ++ ret = -EIO; ++ } else if (iTCO_wdt_private.iTCO_version == 2) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); + val32 &= 0xffffffdf; +- writel(val32, iTCO_wdt_private.gcs); ++ writel(val32, iTCO_wdt_private.gcs_pmc); + +- val32 = readl(iTCO_wdt_private.gcs); ++ val32 = readl(iTCO_wdt_private.gcs_pmc); + if (val32 & 0x00000020) + ret = -EIO; + } else if (iTCO_wdt_private.iTCO_version == 1) { +@@ -496,7 +526,7 @@ static int iTCO_wdt_start(void) + + /* Force the timer to its reload value by writing to the TCO_RLD + register */ +- if (iTCO_wdt_private.iTCO_version == 2) ++ if (iTCO_wdt_private.iTCO_version >= 2) + outw(0x01, TCO_RLD); + else if (iTCO_wdt_private.iTCO_version == 1) + outb(0x01, TCO_RLD); +@@ -544,9 +574,9 @@ static int iTCO_wdt_keepalive(void) + iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); + + /* Reload the timer by writing to the TCO Timer Counter register */ +- if (iTCO_wdt_private.iTCO_version == 2) ++ if (iTCO_wdt_private.iTCO_version >= 2) { + outw(0x01, TCO_RLD); +- else if (iTCO_wdt_private.iTCO_version == 1) { ++ } else if (iTCO_wdt_private.iTCO_version == 1) { + /* Reset the timeout status bit so that the timer + * needs to count down twice again before rebooting */ + outw(0x0008, TCO1_STS); /* write 1 to clear bit */ +@@ -574,14 +604,14 @@ static int iTCO_wdt_set_heartbeat(int t) + /* "Values of 0h-3h are ignored and should not be attempted" */ + if (tmrval < 0x04) + return -EINVAL; +- if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) || ++ if (((iTCO_wdt_private.iTCO_version >= 2) && (tmrval > 0x3ff)) || + ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f))) + return -EINVAL; + + iTCO_vendor_pre_set_heartbeat(tmrval); + + /* Write new heartbeat to watchdog */ +- if (iTCO_wdt_private.iTCO_version == 2) { ++ if (iTCO_wdt_private.iTCO_version >= 2) { + spin_lock(&iTCO_wdt_private.io_lock); + val16 = inw(TCOv2_TMR); + val16 &= 0xfc00; +@@ -615,13 +645,13 @@ static int iTCO_wdt_get_timeleft(int *time_left) + unsigned char val8; + + /* read the TCO Timer */ +- if (iTCO_wdt_private.iTCO_version == 2) { ++ if (iTCO_wdt_private.iTCO_version >= 2) { + spin_lock(&iTCO_wdt_private.io_lock); + val16 = inw(TCO_RLD); + val16 &= 0x3ff; + spin_unlock(&iTCO_wdt_private.io_lock); + +- *time_left = (val16 * 6) / 10; ++ *time_left = ticks_to_seconds(val16); + } else if (iTCO_wdt_private.iTCO_version == 1) { + spin_lock(&iTCO_wdt_private.io_lock); + val8 = inb(TCO_RLD); +@@ -630,7 +660,7 @@ static int iTCO_wdt_get_timeleft(int *time_left) + val8 += (inb(TCOv1_TMR) & 0x3f); + spin_unlock(&iTCO_wdt_private.io_lock); + +- *time_left = (val8 * 6) / 10; ++ *time_left = ticks_to_seconds(val8); + } else + return -EINVAL; + return 0; +@@ -784,6 +814,24 @@ static struct miscdevice iTCO_wdt_miscdev = { + }; + + /* ++ * From patch for Avoton/Rangeley, enable PMC space; here rather ++ * than where it is in newer kernels to avoid patch problems ++ * We don't need all the functionality related to newer kernels, ++ * so comment out a lot (keeping it for reference). ++ */ ++static void ++lpc_ich_enable_pmc_space (struct pci_dev *dev) ++{ ++ /* struct lpc_ich_priv *priv = pci_get_drvdata (dev); */ ++ u8 reg_save; ++ ++ pci_read_config_byte (dev, /* priv->actrl_pbase */0x44, ®_save); ++ pci_write_config_byte (dev, /* priv->actrl_pbase */0x44, reg_save | 0x2); ++ ++ /* priv->actrl_pbase_save = reg_save; */ ++} ++ ++/* + * Init & exit routines + */ + +@@ -810,13 +858,16 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, + } + iTCO_wdt_private.iTCO_version = + iTCO_chipset_info[ent->driver_data].iTCO_version; ++ if (iTCO_wdt_private.iTCO_version == 3) + iTCO_wdt_private.ACPIBASE = base_address; + iTCO_wdt_private.pdev = pdev; + +- /* Get the Memory-Mapped GCS register, we need it for the +- NO_REBOOT flag (TCO v2). To get access to it you have to +- read RCBA from PCI Config space 0xf0 and use it as base. +- GCS = RCBA + ICH6_GCS(0x3410). */ ++ /* ++ * Get the Memory-Mapped GCS or PMC register, we need it for the ++ * NO_REBOOT flag (TCO v2 and v3). ++ * v2: read RCBA from PCI Config space 0xf0 and use it as base. ++ * GCS = RCBA + ICH6_GCS(0x3410). ++ */ + if (iTCO_wdt_private.iTCO_version == 2) { + pci_read_config_dword(pdev, 0xf0, &base_address); + if ((base_address & 1) == 0) { +@@ -826,7 +877,19 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, + goto out; + } + RCBA = base_address & 0xffffc000; +- iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); ++ iTCO_wdt_private.gcs_pmc = ioremap((RCBA + 0x3410), 4); ++ } ++ else if (iTCO_wdt_private.iTCO_version == 3) { ++ /* ++ * comes from ACPI, in PMC space. driver resources ++ * changed a lot in this area from our 3.2 kernel to ++ * kernel where v3 support was added. 0x44 is ACPICTRL_PMBASE, ++ * 0x8 is ACPI_PMC_OFF. ++ */ ++ lpc_ich_enable_pmc_space (pdev); ++ pci_read_config_dword(pdev, 0x44, &base_address); ++ base_address &= 0xfffffe00; ++ iTCO_wdt_private.gcs_pmc = ioremap(base_address + 0x8, 4); + } + + /* Check chipset's NO_REBOOT bit */ +@@ -871,9 +934,13 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, + TCOBASE); + + /* Clear out the (probably old) status */ +- outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ +- outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ +- outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ ++ if (iTCO_wdt_private.iTCO_version == 3) { ++ outl(0x20008, TCO1_STS); ++ } else { ++ outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ ++ outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ ++ outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ ++ } + + /* Make sure the watchdog is not running */ + iTCO_wdt_stop(); +@@ -904,8 +971,8 @@ unreg_region: + unreg_smi_en: + release_region(SMI_EN, 4); + out_unmap: +- if (iTCO_wdt_private.iTCO_version == 2) +- iounmap(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version >= 2) ++ iounmap(iTCO_wdt_private.gcs_pmc); + out: + iTCO_wdt_private.ACPIBASE = 0; + return ret; +@@ -921,8 +988,8 @@ static void __devexit iTCO_wdt_cleanup(void) + misc_deregister(&iTCO_wdt_miscdev); + release_region(TCOBASE, 0x20); + release_region(SMI_EN, 4); +- if (iTCO_wdt_private.iTCO_version == 2) +- iounmap(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version >= 2) ++ iounmap(iTCO_wdt_private.gcs_pmc); + pci_dev_put(iTCO_wdt_private.pdev); + iTCO_wdt_private.ACPIBASE = 0; + } +diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c +new file mode 100644 +index 0000000..8f541b9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch new file mode 100644 index 00000000..dd78bd50 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch @@ -0,0 +1,353 @@ +--- /dev/null ++++ b/drivers/watchdog/ie6xx_wdt.c +@@ -0,0 +1,348 @@ ++/* ++ * Intel Atom E6xx Watchdog driver ++ * ++ * Copyright (C) 2011 Alexander Stein ++ * ++ * ++ * 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., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ * The full GNU General Public License is included in this ++ * distribution in the file called COPYING. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "ie6xx_wdt" ++ ++#define PV1 0x00 ++#define PV2 0x04 ++ ++#define RR0 0x0c ++#define RR1 0x0d ++#define WDT_RELOAD 0x01 ++#define WDT_TOUT 0x02 ++ ++#define WDTCR 0x10 ++#define WDT_PRE_SEL 0x04 ++#define WDT_RESET_SEL 0x08 ++#define WDT_RESET_EN 0x10 ++#define WDT_TOUT_EN 0x20 ++ ++#define DCR 0x14 ++ ++#define WDTLR 0x18 ++#define WDT_LOCK 0x01 ++#define WDT_ENABLE 0x02 ++#define WDT_TOUT_CNF 0x03 ++ ++#define MIN_TIME 1 ++#define MAX_TIME (10 * 60) /* 10 minutes */ ++#define DEFAULT_TIME 60 ++ ++static unsigned int timeout = DEFAULT_TIME; ++module_param(timeout, uint, 0); ++MODULE_PARM_DESC(timeout, ++ "Default Watchdog timer setting (" ++ __MODULE_STRING(DEFAULT_TIME) "s)." ++ "The range is from 1 to 600"); ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, bool, 0); ++MODULE_PARM_DESC(nowayout, ++ "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++static u8 resetmode = 0x10; ++module_param(resetmode, byte, 0); ++MODULE_PARM_DESC(resetmode, ++ "Resetmode bits: 0x08 warm reset (cold reset otherwise), " ++ "0x10 reset enable, 0x20 disable toggle GPIO[4] (default=0x10)"); ++ ++static struct { ++ unsigned short sch_wdtba; ++ struct spinlock unlock_sequence; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs; ++#endif ++} ie6xx_wdt_data; ++ ++/* ++ * This is needed to write to preload and reload registers ++ * struct ie6xx_wdt_data.unlock_sequence must be used ++ * to prevent sequence interrupts ++ */ ++static void ie6xx_wdt_unlock_registers(void) ++{ ++ outb(0x80, ie6xx_wdt_data.sch_wdtba + RR0); ++ outb(0x86, ie6xx_wdt_data.sch_wdtba + RR0); ++} ++ ++static int ie6xx_wdt_ping(struct watchdog_device *wdd) ++{ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ ie6xx_wdt_unlock_registers(); ++ outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1); ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ return 0; ++} ++ ++static int ie6xx_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) ++{ ++ u32 preload; ++ u64 clock; ++ u8 wdtcr; ++ ++ /* Watchdog clock is PCI Clock (33MHz) */ ++ clock = 33000000; ++ /* and the preload value is loaded into [34:15] of the down counter */ ++ preload = (t * clock) >> 15; ++ /* ++ * Manual states preload must be one less. ++ * Does not wrap as t is at least 1 ++ */ ++ preload -= 1; ++ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ ++ /* Set ResetMode & Enable prescaler for range 10ms to 10 min */ ++ wdtcr = resetmode & 0x38; ++ outb(wdtcr, ie6xx_wdt_data.sch_wdtba + WDTCR); ++ ++ ie6xx_wdt_unlock_registers(); ++ outl(0, ie6xx_wdt_data.sch_wdtba + PV1); ++ ++ ie6xx_wdt_unlock_registers(); ++ outl(preload, ie6xx_wdt_data.sch_wdtba + PV2); ++ ++ ie6xx_wdt_unlock_registers(); ++ outb(WDT_RELOAD | WDT_TOUT, ie6xx_wdt_data.sch_wdtba + RR1); ++ ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ ++ wdd->timeout = t; ++ return 0; ++} ++ ++static int ie6xx_wdt_start(struct watchdog_device *wdd) ++{ ++ ie6xx_wdt_set_timeout(wdd, wdd->timeout); ++ ++ /* Enable the watchdog timer */ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ outb(WDT_ENABLE, ie6xx_wdt_data.sch_wdtba + WDTLR); ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ ++ return 0; ++} ++ ++static int ie6xx_wdt_stop(struct watchdog_device *wdd) ++{ ++ if (inb(ie6xx_wdt_data.sch_wdtba + WDTLR) & WDT_LOCK) ++ return -1; ++ ++ /* Disable the watchdog timer */ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ outb(0, ie6xx_wdt_data.sch_wdtba + WDTLR); ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ ++ return 0; ++} ++ ++static const struct watchdog_info ie6xx_wdt_info = { ++ .identity = "Intel Atom E6xx Watchdog", ++ .options = WDIOF_SETTIMEOUT | ++ WDIOF_MAGICCLOSE | ++ WDIOF_KEEPALIVEPING, ++}; ++ ++static const struct watchdog_ops ie6xx_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = ie6xx_wdt_start, ++ .stop = ie6xx_wdt_stop, ++ .ping = ie6xx_wdt_ping, ++ .set_timeout = ie6xx_wdt_set_timeout, ++}; ++ ++static struct watchdog_device ie6xx_wdt_dev = { ++ .info = &ie6xx_wdt_info, ++ .ops = &ie6xx_wdt_ops, ++ .min_timeout = MIN_TIME, ++ .max_timeout = MAX_TIME, ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++ ++static int ie6xx_wdt_dbg_show(struct seq_file *s, void *unused) ++{ ++ seq_printf(s, "PV1 = 0x%08x\n", ++ inl(ie6xx_wdt_data.sch_wdtba + PV1)); ++ seq_printf(s, "PV2 = 0x%08x\n", ++ inl(ie6xx_wdt_data.sch_wdtba + PV2)); ++ seq_printf(s, "RR = 0x%08x\n", ++ inw(ie6xx_wdt_data.sch_wdtba + RR0)); ++ seq_printf(s, "WDTCR = 0x%08x\n", ++ inw(ie6xx_wdt_data.sch_wdtba + WDTCR)); ++ seq_printf(s, "DCR = 0x%08x\n", ++ inl(ie6xx_wdt_data.sch_wdtba + DCR)); ++ seq_printf(s, "WDTLR = 0x%08x\n", ++ inw(ie6xx_wdt_data.sch_wdtba + WDTLR)); ++ ++ seq_printf(s, "\n"); ++ return 0; ++} ++ ++static int ie6xx_wdt_dbg_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ie6xx_wdt_dbg_show, NULL); ++} ++ ++static const struct file_operations ie6xx_wdt_dbg_operations = { ++ .open = ie6xx_wdt_dbg_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void __devinit ie6xx_wdt_debugfs_init(void) ++{ ++ /* /sys/kernel/debug/ie6xx_wdt */ ++ ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt", ++ S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations); ++} ++ ++static void ie6xx_wdt_debugfs_exit(void) ++{ ++ debugfs_remove(ie6xx_wdt_data.debugfs); ++} ++ ++#else ++static void __devinit ie6xx_wdt_debugfs_init(void) ++{ ++} ++ ++static void ie6xx_wdt_debugfs_exit(void) ++{ ++} ++#endif ++ ++static int __devinit ie6xx_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ u8 wdtlr; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IO, 0); ++ if (!res) ++ return -ENODEV; ++ ++ if (!request_region(res->start, resource_size(res), pdev->name)) { ++ dev_err(&pdev->dev, "Watchdog region 0x%llx already in use!\n", ++ (u64)res->start); ++ return -EBUSY; ++ } ++ ++ ie6xx_wdt_data.sch_wdtba = res->start; ++ dev_dbg(&pdev->dev, "WDT = 0x%X\n", ie6xx_wdt_data.sch_wdtba); ++ ++ ie6xx_wdt_dev.timeout = timeout; ++ watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout); ++ ++ spin_lock_init(&ie6xx_wdt_data.unlock_sequence); ++ ++ wdtlr = inb(ie6xx_wdt_data.sch_wdtba + WDTLR); ++ if (wdtlr & WDT_LOCK) ++ dev_warn(&pdev->dev, ++ "Watchdog Timer is Locked (Reg=0x%x)\n", wdtlr); ++ ++ ie6xx_wdt_debugfs_init(); ++ ++ ret = watchdog_register_device(&ie6xx_wdt_dev); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "Watchdog timer: cannot register device (err =%d)\n", ++ ret); ++ goto misc_register_error; ++ } ++ ++ return 0; ++ ++misc_register_error: ++ ie6xx_wdt_debugfs_exit(); ++ release_region(res->start, resource_size(res)); ++ ie6xx_wdt_data.sch_wdtba = 0; ++ return ret; ++} ++ ++static int __devexit ie6xx_wdt_remove(struct platform_device *pdev) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IO, 0); ++ ie6xx_wdt_stop(NULL); ++ watchdog_unregister_device(&ie6xx_wdt_dev); ++ ie6xx_wdt_debugfs_exit(); ++ release_region(res->start, resource_size(res)); ++ ie6xx_wdt_data.sch_wdtba = 0; ++ ++ return 0; ++} ++ ++static struct platform_driver ie6xx_wdt_driver = { ++ .probe = ie6xx_wdt_probe, ++ .remove = __devexit_p(ie6xx_wdt_remove), ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ie6xx_wdt_init(void) ++{ ++ /* Check boot parameters to verify that their initial values */ ++ /* are in range. */ ++ if ((timeout < MIN_TIME) || ++ (timeout > MAX_TIME)) { ++ pr_err("Watchdog timer: value of timeout %d (dec) " ++ "is out of range from %d to %d (dec)\n", ++ timeout, MIN_TIME, MAX_TIME); ++ return -EINVAL; ++ } ++ ++ return platform_driver_register(&ie6xx_wdt_driver); ++} ++ ++static void __exit ie6xx_wdt_exit(void) ++{ ++ platform_driver_unregister(&ie6xx_wdt_driver); ++} ++ ++late_initcall(ie6xx_wdt_init); ++module_exit(ie6xx_wdt_exit); ++ ++MODULE_AUTHOR("Alexander Stein "); ++MODULE_DESCRIPTION("Intel Atom E6xx Watchdog Device Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c +index 87e0527..826f6bb 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch new file mode 100644 index 00000000..f5d4b2d6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch @@ -0,0 +1,15 @@ +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -287,6 +287,10 @@ static unsigned char __devinit sp5100_tco_setupdevice(void) + if (!sp5100_tco_pci) + return 0; + ++ /* Higher revisions are SB8x0 which have a different register set */ ++ if (sp5100_tco_pci->revision >= 0x40) ++ return 0; ++ + /* Request the IO ports used by this driver */ + pm_iobase = SP5100_IO_PM_INDEX_REG; + if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) { +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index 89588e7..f39d998 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/foopatch b/packages/base/any/kernels/3.2-lts/patches/foopatch new file mode 100644 index 00000000..11fda216 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/foopatch @@ -0,0 +1,74956 @@ +--- /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.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.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.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 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch new file mode 100644 index 00000000..06004175 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch @@ -0,0 +1,34 @@ +--- /dev/null ++++ b/include/asm-generic/io-64-nonatomic-hi-lo.h +@@ -0,0 +1,28 @@ ++#ifndef _ASM_IO_64_NONATOMIC_HI_LO_H_ ++#define _ASM_IO_64_NONATOMIC_HI_LO_H_ ++ ++#include ++#include ++ ++#ifndef readq ++static inline __u64 readq(const volatile void __iomem *addr) ++{ ++ const volatile u32 __iomem *p = addr; ++ u32 low, high; ++ ++ high = readl(p + 1); ++ low = readl(p); ++ ++ return low + ((u64)high << 32); ++} ++#endif ++ ++#ifndef writeq ++static inline void writeq(__u64 val, volatile void __iomem *addr) ++{ ++ writel(val >> 32, addr + 4); ++ writel(val, addr); ++} ++#endif ++ ++#endif /* _ASM_IO_64_NONATOMIC_HI_LO_H_ */ +diff --git a/include/asm-generic/io-64-nonatomic-lo-hi.h b/include/asm-generic/io-64-nonatomic-lo-hi.h +new file mode 100644 +index 0000000..ca546b1 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch new file mode 100644 index 00000000..28c861d3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/include/asm-generic/io-64-nonatomic-lo-hi.h +@@ -0,0 +1,28 @@ ++#ifndef _ASM_IO_64_NONATOMIC_LO_HI_H_ ++#define _ASM_IO_64_NONATOMIC_LO_HI_H_ ++ ++#include ++#include ++ ++#ifndef readq ++static inline __u64 readq(const volatile void __iomem *addr) ++{ ++ const volatile u32 __iomem *p = addr; ++ u32 low, high; ++ ++ low = readl(p); ++ high = readl(p + 1); ++ ++ return low + ((u64)high << 32); ++} ++#endif ++ ++#ifndef writeq ++static inline void writeq(__u64 val, volatile void __iomem *addr) ++{ ++ writel(val, addr); ++ writel(val >> 32, addr + 4); ++} ++#endif ++ ++#endif /* _ASM_IO_64_NONATOMIC_LO_HI_H_ */ +diff --git a/include/drm/Kbuild b/include/drm/Kbuild +index 3a60ac8..1e38a19 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch new file mode 100644 index 00000000..9e834fe1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch @@ -0,0 +1,42 @@ +--- a/include/linux/amba/bus.h ++++ b/include/linux/amba/bus.h +@@ -94,4 +94,37 @@ void amba_release_regions(struct amba_device *); + #define amba_manf(d) AMBA_MANF_BITS((d)->periphid) + #define amba_part(d) AMBA_PART_BITS((d)->periphid) + ++#define __AMBA_DEV(busid, data, mask) \ ++ { \ ++ .coherent_dma_mask = mask, \ ++ .init_name = busid, \ ++ .platform_data = data, \ ++ } ++ ++/* ++ * APB devices do not themselves have the ability to address memory, ++ * so DMA masks should be zero (much like USB peripheral devices.) ++ * The DMA controller DMA masks should be used instead (much like ++ * USB host controllers in conventional PCs.) ++ */ ++#define AMBA_APB_DEVICE(name, busid, id, base, irqs, data) \ ++struct amba_device name##_device = { \ ++ .dev = __AMBA_DEV(busid, data, 0), \ ++ .res = DEFINE_RES_MEM(base, SZ_4K), \ ++ .irq = irqs, \ ++ .periphid = id, \ ++} ++ ++/* ++ * AHB devices are DMA capable, so set their DMA masks ++ */ ++#define AMBA_AHB_DEVICE(name, busid, id, base, irqs, data) \ ++struct amba_device name##_device = { \ ++ .dev = __AMBA_DEV(busid, data, ~0ULL), \ ++ .res = DEFINE_RES_MEM(base, SZ_4K), \ ++ .dma_mask = ~0ULL, \ ++ .irq = irqs, \ ++ .periphid = id, \ ++} ++ + #endif +diff --git a/include/linux/ata_platform.h b/include/linux/ata_platform.h +index 9a26c83..b38ab9c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch new file mode 100644 index 00000000..bb9d33c9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch @@ -0,0 +1,30 @@ +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -129,6 +129,7 @@ + #define AUDIT_LAST_KERN_ANOM_MSG 1799 + #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ + #define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ ++#define AUDIT_ANOM_LINK 1702 /* Suspicious use of file links */ + #define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ + #define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ + #define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ +@@ -611,6 +612,8 @@ extern void audit_log_d_path(struct audit_buffer *ab, + struct path *path); + extern void audit_log_key(struct audit_buffer *ab, + char *key); ++extern void audit_log_link_denied(const char *operation, ++ struct path *link); + extern void audit_log_lost(const char *message); + #ifdef CONFIG_SECURITY + extern void audit_log_secctx(struct audit_buffer *ab, u32 secid); +@@ -640,6 +643,7 @@ extern int audit_enabled; + #define audit_log_untrustedstring(a,s) do { ; } while (0) + #define audit_log_d_path(b, p, d) do { ; } while (0) + #define audit_log_key(b, k) do { ; } while (0) ++#define audit_log_link_denied(o, l) do { ; } while (0) + #define audit_log_secctx(b,s) do { ; } while (0) + #define audit_enabled 0 + #endif +diff --git a/include/linux/aufs_type.h b/include/linux/aufs_type.h +new file mode 100644 +index 0000000..2e829a4 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch new file mode 100644 index 00000000..708fdc2c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch @@ -0,0 +1,28 @@ +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -26,6 +26,23 @@ extern unsigned long __sw_hweight64(__u64 w); + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + ++/* same as for_each_set_bit() but use bit as value to start with */ ++#define for_each_set_bit_from(bit, addr, size) \ ++ for ((bit) = find_next_bit((addr), (size), (bit)); \ ++ (bit) < (size); \ ++ (bit) = find_next_bit((addr), (size), (bit) + 1)) ++ ++#define for_each_clear_bit(bit, addr, size) \ ++ for ((bit) = find_first_zero_bit((addr), (size)); \ ++ (bit) < (size); \ ++ (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) ++ ++/* same as for_each_clear_bit() but use bit as value to start with */ ++#define for_each_clear_bit_from(bit, addr, size) \ ++ for ((bit) = find_next_zero_bit((addr), (size), (bit)); \ ++ (bit) < (size); \ ++ (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) ++ + static __inline__ int get_bitmask_order(unsigned int count) + { + int order; +diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h +index fed3f3a..43d5858 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch new file mode 100644 index 00000000..56088086 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/ceph/messenger.h ++++ b/include/linux/ceph/messenger.h +@@ -92,7 +92,11 @@ struct ceph_msg { + bool front_is_vmalloc; + bool more_to_follow; + bool needs_out_seq; ++#ifdef __GENKSYMS__ ++ int front_max; /* renamed */ ++#else + int front_alloc_len; ++#endif + unsigned long ack_stamp; /* tx: when we were acked */ + + struct ceph_msgpool *pool; +diff --git a/include/linux/connector.h b/include/linux/connector.h +index 3c9c54f..7638407 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch new file mode 100644 index 00000000..6302c284 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/connector.h ++++ b/include/linux/connector.h +@@ -43,6 +43,7 @@ + #define CN_IDX_DRBD 0x8 + #define CN_VAL_DRBD 0x1 + #define CN_KVP_IDX 0x9 /* HyperV KVP */ ++#define CN_KVP_VAL 0x1 /* queries from the kernel */ + + #define CN_NETLINK_USERS 10 /* Highest index + 1 */ + +diff --git a/include/linux/cpu.h b/include/linux/cpu.h +index 9c3e071..ea07082 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch new file mode 100644 index 00000000..921f0fed --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch @@ -0,0 +1,63 @@ +--- a/include/linux/cpu.h ++++ b/include/linux/cpu.h +@@ -14,7 +14,7 @@ + #ifndef _LINUX_CPU_H_ + #define _LINUX_CPU_H_ + +-#include ++#include + #include + #include + #include +@@ -22,19 +22,19 @@ + struct cpu { + int node_id; /* The node which contains the CPU */ + int hotpluggable; /* creates sysfs control file if hotpluggable */ +- struct sys_device sysdev; ++ struct device dev; + }; + + extern int register_cpu(struct cpu *cpu, int num); +-extern struct sys_device *get_cpu_sysdev(unsigned cpu); ++extern struct device *get_cpu_device(unsigned cpu); + +-extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr); +-extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr); ++extern int cpu_add_dev_attr(struct device_attribute *attr); ++extern void cpu_remove_dev_attr(struct device_attribute *attr); + +-extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs); +-extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs); ++extern int cpu_add_dev_attr_group(struct attribute_group *attrs); ++extern void cpu_remove_dev_attr_group(struct attribute_group *attrs); + +-extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls); ++extern int sched_create_sysfs_power_savings_entries(struct device *dev); + + #ifdef CONFIG_HOTPLUG_CPU + extern void unregister_cpu(struct cpu *cpu); +@@ -43,6 +43,13 @@ extern ssize_t arch_cpu_release(const char *, size_t); + #endif + struct notifier_block; + ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env); ++extern ssize_t arch_print_cpu_modalias(struct device *dev, ++ struct device_attribute *attr, ++ char *bufptr); ++#endif ++ + /* + * CPU notifier priorities. + */ +@@ -161,7 +168,7 @@ static inline void cpu_maps_update_done(void) + } + + #endif /* CONFIG_SMP */ +-extern struct sysdev_class cpu_sysdev_class; ++extern struct bus_type cpu_subsys; + + #ifdef CONFIG_HOTPLUG_CPU + /* Stop CPUs going up and down. */ +diff --git a/include/linux/dcache.h b/include/linux/dcache.h +index 99374de..2307a30 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch new file mode 100644 index 00000000..3ad3131c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch @@ -0,0 +1,36 @@ +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -133,15 +133,31 @@ struct dentry { + void *d_fsdata; /* fs-specific data */ + + struct list_head d_lru; /* LRU list */ ++#ifdef __GENKSYMS__ ++ /* ++ * bwh: The union changes here don't move anything other than ++ * d_rcu (which modules definitely should not touch). This is ++ * checked by dcache_abi_check(). ++ */ ++ union { ++#endif + struct list_head d_child; /* child of parent list */ ++#ifdef __GENKSYMS__ ++ struct rcu_head d_rcu; ++ } d_u; ++#endif + struct list_head d_subdirs; /* our children */ + /* + * d_alias and d_rcu can share memory + */ ++#ifndef __GENKSYMS__ + union { ++#endif + struct list_head d_alias; /* inode alias list */ ++#ifndef __GENKSYMS__ + struct rcu_head d_rcu; + } d_u; ++#endif + }; + + /* +diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h +index 6712ab6..fe51b99 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch new file mode 100644 index 00000000..3cdbc69f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch @@ -0,0 +1,15 @@ +--- a/include/linux/device-mapper.h ++++ b/include/linux/device-mapper.h +@@ -72,8 +72,8 @@ typedef void (*dm_postsuspend_fn) (struct dm_target *ti); + typedef int (*dm_preresume_fn) (struct dm_target *ti); + typedef void (*dm_resume_fn) (struct dm_target *ti); + +-typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, +- char *result, unsigned maxlen); ++typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, ++ char *result, unsigned int maxlen); + + typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); + +diff --git a/include/linux/device.h b/include/linux/device.h +index a31c5d0..34b5d6b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch new file mode 100644 index 00000000..4b4a171b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch @@ -0,0 +1,177 @@ +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -53,6 +53,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + * struct bus_type - The bus type of the device + * + * @name: The name of the bus. ++ * @dev_name: Used for subsystems to enumerate devices like ("foo%u", dev->id). ++ * @dev_root: Default device to use as the parent. + * @bus_attrs: Default attributes of the bus. + * @dev_attrs: Default attributes of the devices on the bus. + * @drv_attrs: Default attributes of the device drivers on the bus. +@@ -86,6 +88,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + */ + struct bus_type { + const char *name; ++ const char *dev_name; ++ struct device *dev_root; + struct bus_attribute *bus_attrs; + struct device_attribute *dev_attrs; + struct driver_attribute *drv_attrs; +@@ -106,12 +110,30 @@ struct bus_type { + struct subsys_private *p; + }; + +-extern int __must_check bus_register(struct bus_type *bus); ++/* This is a #define to keep the compiler from merging different ++ * instances of the __key variable */ ++#define bus_register(subsys) \ ++({ \ ++ static struct lock_class_key __key; \ ++ __bus_register(subsys, &__key); \ ++}) ++extern int __must_check __bus_register(struct bus_type *bus, ++ struct lock_class_key *key); + extern void bus_unregister(struct bus_type *bus); + + extern int __must_check bus_rescan_devices(struct bus_type *bus); + + /* iterator helpers for buses */ ++struct subsys_dev_iter { ++ struct klist_iter ki; ++ const struct device_type *type; ++}; ++void subsys_dev_iter_init(struct subsys_dev_iter *iter, ++ struct bus_type *subsys, ++ struct device *start, ++ const struct device_type *type); ++struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); ++void subsys_dev_iter_exit(struct subsys_dev_iter *iter); + + int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, + int (*fn)(struct device *dev, void *data)); +@@ -121,10 +143,10 @@ struct device *bus_find_device(struct bus_type *bus, struct device *start, + struct device *bus_find_device_by_name(struct bus_type *bus, + struct device *start, + const char *name); +- ++struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, ++ struct device *hint); + int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, + void *data, int (*fn)(struct device_driver *, void *)); +- + void bus_sort_breadthfirst(struct bus_type *bus, + int (*compare)(const struct device *a, + const struct device *b)); +@@ -256,6 +278,33 @@ struct device *driver_find_device(struct device_driver *drv, + int (*match)(struct device *dev, void *data)); + + /** ++ * struct subsys_interface - interfaces to device functions ++ * @name name of the device function ++ * @subsystem subsytem of the devices to attach to ++ * @node the list of functions registered at the subsystem ++ * @add device hookup to device function handler ++ * @remove device hookup to device function handler ++ * ++ * Simple interfaces attached to a subsystem. Multiple interfaces can ++ * attach to a subsystem and its devices. Unlike drivers, they do not ++ * exclusively claim or control devices. Interfaces usually represent ++ * a specific functionality of a subsystem/class of devices. ++ */ ++struct subsys_interface { ++ const char *name; ++ struct bus_type *subsys; ++ struct list_head node; ++ int (*add_dev)(struct device *dev, struct subsys_interface *sif); ++ int (*remove_dev)(struct device *dev, struct subsys_interface *sif); ++}; ++ ++int subsys_interface_register(struct subsys_interface *sif); ++void subsys_interface_unregister(struct subsys_interface *sif); ++ ++int subsys_system_register(struct bus_type *subsys, ++ const struct attribute_group **groups); ++ ++/** + * struct class - device classes + * @name: Name of the class. + * @owner: The module owner. +@@ -438,11 +487,37 @@ struct device_attribute { + const char *buf, size_t count); + }; + +-#define DEVICE_ATTR(_name, _mode, _show, _store) \ +-struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) ++struct dev_ext_attribute { ++ struct device_attribute attr; ++ void *var; ++}; ++ ++ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr, ++ char *buf); ++ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count); ++ssize_t device_show_int(struct device *dev, struct device_attribute *attr, ++ char *buf); ++ssize_t device_store_int(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count); + +-extern int __must_check device_create_file(struct device *device, +- const struct device_attribute *entry); ++#define DEVICE_ATTR(_name, _mode, _show, _store) \ ++ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) ++#define DEVICE_ATTR_RW(_name) \ ++ struct device_attribute dev_attr_##_name = __ATTR_RW(_name) ++#define DEVICE_ATTR_RO(_name) \ ++ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) ++#define DEVICE_ATTR_WO(_name) \ ++ struct device_attribute dev_attr_##_name = __ATTR_WO(_name) ++#define DEVICE_ULONG_ATTR(_name, _mode, _var) \ ++ struct dev_ext_attribute dev_attr_##_name = \ ++ { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } ++#define DEVICE_INT_ATTR(_name, _mode, _var) \ ++ struct dev_ext_attribute dev_attr_##_name = \ ++ { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } ++ ++extern int device_create_file(struct device *device, ++ const struct device_attribute *entry); + extern void device_remove_file(struct device *dev, + const struct device_attribute *attr); + extern int __must_check device_create_bin_file(struct device *dev, +@@ -600,6 +675,7 @@ struct device { + struct device_node *of_node; /* associated device tree node */ + + dev_t devt; /* dev_t, creates the sysfs "dev" */ ++ u32 id; /* device instance */ + + spinlock_t devres_lock; + struct list_head devres_head; +@@ -929,4 +1005,25 @@ extern long sysfs_deprecated; + #define sysfs_deprecated 0 + #endif + ++/** ++ * module_driver() - Helper macro for drivers that don't do anything ++ * special in module init/exit. This eliminates a lot of boilerplate. ++ * Each module may only use this macro once, and calling it replaces ++ * module_init() and module_exit(). ++ * ++ * Use this macro to construct bus specific macros for registering ++ * drivers, and do not use it on its own. ++ */ ++#define module_driver(__driver, __register, __unregister) \ ++static int __init __driver##_init(void) \ ++{ \ ++ return __register(&(__driver)); \ ++} \ ++module_init(__driver##_init); \ ++static void __exit __driver##_exit(void) \ ++{ \ ++ __unregister(&(__driver)); \ ++} \ ++module_exit(__driver##_exit); ++ + #endif /* _DEVICE_H_ */ +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index e13117c..a018887 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch new file mode 100644 index 00000000..88706b07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch @@ -0,0 +1,25 @@ +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -89,6 +89,20 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask) + } + #endif + ++/* ++ * Set both the DMA mask and the coherent DMA mask to the same thing. ++ * Note that we don't check the return value from dma_set_coherent_mask() ++ * as the DMA API guarantees that the coherent DMA mask can be set to ++ * the same or smaller than the streaming DMA mask. ++ */ ++static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) ++{ ++ int rc = dma_set_mask(dev, mask); ++ if (rc == 0) ++ dma_set_coherent_mask(dev, mask); ++ return rc; ++} ++ + extern u64 dma_get_required_mask(struct device *dev); + + static inline unsigned int dma_get_max_seg_size(struct device *dev) +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 75f53f8..2ee20c5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch new file mode 100644 index 00000000..50d9568e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -530,6 +530,22 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); + } + ++static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_data_direction dir, unsigned long flags) ++{ ++ return chan->device->device_prep_slave_sg(chan, sgl, sg_len, ++ dir, flags); ++} ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_data_direction dir) ++{ ++ return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, ++ period_len, dir); ++} ++ + static inline int dmaengine_terminate_all(struct dma_chan *chan) + { + return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); +diff --git a/include/linux/dmi.h b/include/linux/dmi.h +index f156cca..f6feb54 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch new file mode 100644 index 00000000..53d74b93 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch @@ -0,0 +1,20 @@ +--- a/include/linux/dmi.h ++++ b/include/linux/dmi.h +@@ -93,6 +93,14 @@ struct dmi_dev_onboard { + int devfn; + }; + ++/* ++ * bwh: These functions are renamed so that modules won't load on an ++ * older kernel version where setting the 'exact_match' flag would ++ * result in an array overrun. ++ */ ++#define dmi_check_system dmi_check_system_2 ++#define dmi_first_match dmi_first_match_2 ++ + extern int dmi_check_system(const struct dmi_system_id *list); + const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list); + extern const char * dmi_get_system_info(int field); +diff --git a/include/linux/dynamic_queue_limits.h b/include/linux/dynamic_queue_limits.h +new file mode 100644 +index 0000000..5621547 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch new file mode 100644 index 00000000..f2eab2c4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch @@ -0,0 +1,103 @@ +--- /dev/null ++++ b/include/linux/dynamic_queue_limits.h +@@ -0,0 +1,97 @@ ++/* ++ * Dynamic queue limits (dql) - Definitions ++ * ++ * Copyright (c) 2011, Tom Herbert ++ * ++ * This header file contains the definitions for dynamic queue limits (dql). ++ * dql would be used in conjunction with a producer/consumer type queue ++ * (possibly a HW queue). Such a queue would have these general properties: ++ * ++ * 1) Objects are queued up to some limit specified as number of objects. ++ * 2) Periodically a completion process executes which retires consumed ++ * objects. ++ * 3) Starvation occurs when limit has been reached, all queued data has ++ * actually been consumed, but completion processing has not yet run ++ * so queuing new data is blocked. ++ * 4) Minimizing the amount of queued data is desirable. ++ * ++ * The goal of dql is to calculate the limit as the minimum number of objects ++ * needed to prevent starvation. ++ * ++ * The primary functions of dql are: ++ * dql_queued - called when objects are enqueued to record number of objects ++ * dql_avail - returns how many objects are available to be queued based ++ * on the object limit and how many objects are already enqueued ++ * dql_completed - called at completion time to indicate how many objects ++ * were retired from the queue ++ * ++ * The dql implementation does not implement any locking for the dql data ++ * structures, the higher layer should provide this. dql_queued should ++ * be serialized to prevent concurrent execution of the function; this ++ * is also true for dql_completed. However, dql_queued and dlq_completed can ++ * be executed concurrently (i.e. they can be protected by different locks). ++ */ ++ ++#ifndef _LINUX_DQL_H ++#define _LINUX_DQL_H ++ ++#ifdef __KERNEL__ ++ ++struct dql { ++ /* Fields accessed in enqueue path (dql_queued) */ ++ unsigned int num_queued; /* Total ever queued */ ++ unsigned int adj_limit; /* limit + num_completed */ ++ unsigned int last_obj_cnt; /* Count at last queuing */ ++ ++ /* Fields accessed only by completion path (dql_completed) */ ++ ++ unsigned int limit ____cacheline_aligned_in_smp; /* Current limit */ ++ unsigned int num_completed; /* Total ever completed */ ++ ++ unsigned int prev_ovlimit; /* Previous over limit */ ++ unsigned int prev_num_queued; /* Previous queue total */ ++ unsigned int prev_last_obj_cnt; /* Previous queuing cnt */ ++ ++ unsigned int lowest_slack; /* Lowest slack found */ ++ unsigned long slack_start_time; /* Time slacks seen */ ++ ++ /* Configuration */ ++ unsigned int max_limit; /* Max limit */ ++ unsigned int min_limit; /* Minimum limit */ ++ unsigned int slack_hold_time; /* Time to measure slack */ ++}; ++ ++/* Set some static maximums */ ++#define DQL_MAX_OBJECT (UINT_MAX / 16) ++#define DQL_MAX_LIMIT ((UINT_MAX / 2) - DQL_MAX_OBJECT) ++ ++/* ++ * Record number of objects queued. Assumes that caller has already checked ++ * availability in the queue with dql_avail. ++ */ ++static inline void dql_queued(struct dql *dql, unsigned int count) ++{ ++ BUG_ON(count > DQL_MAX_OBJECT); ++ ++ dql->num_queued += count; ++ dql->last_obj_cnt = count; ++} ++ ++/* Returns how many objects can be queued, < 0 indicates over limit. */ ++static inline int dql_avail(const struct dql *dql) ++{ ++ return dql->adj_limit - dql->num_queued; ++} ++ ++/* Record number of completed objects and recalculate the limit. */ ++void dql_completed(struct dql *dql, unsigned int count); ++ ++/* Reset dql state */ ++void dql_reset(struct dql *dql); ++ ++/* Initialize dql state */ ++int dql_init(struct dql *dql, unsigned hold_time); ++ ++#endif /* _KERNEL_ */ ++ ++#endif /* _LINUX_DQL_H */ +diff --git a/include/linux/early_dma_alloc.h b/include/linux/early_dma_alloc.h +new file mode 100644 +index 0000000..a6d87ec diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch new file mode 100644 index 00000000..1278658f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch @@ -0,0 +1,42 @@ +--- /dev/null ++++ b/include/linux/early_dma_alloc.h +@@ -0,0 +1,36 @@ ++/* ++ * Early DMA Memory Allocator ++ * ++ * Copyright © 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#ifndef EARLY_DMA_ALLOC_H__ ++#define EARLY_DMA_ALLOC_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++extern int eda_init(void); ++extern int eda_dma_info_get(void** vaddr, uint32_t* paddr, uint32_t* size); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* EARLY_DMA_ALLOC_H__ */ +diff --git a/include/linux/eeprom_class.h b/include/linux/eeprom_class.h +new file mode 100644 +index 0000000..d21d350 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch new file mode 100644 index 00000000..f3968a44 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/include/linux/eeprom_class.h +@@ -0,0 +1,79 @@ ++/* ++ * eeprom_class.h ++ * ++ * This file exports interface functions for the sysfs class "eeprom", ++ * for use by EEPROM drivers. ++ * ++ * 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; 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. ++ * ++ */ ++ ++#ifndef EEPROM_CLASS_H__ ++#define EEPROM_CLASS_H__ ++ ++#include ++#include ++ ++/* ++ * Extra platform data used by the eeprom class ++ * ++ * An eeprom device can include this structure in its own platform ++ * data structure. ++ * ++ * A specific platform can set the values in this structure to values ++ * suitable for that platform. ++ * ++ */ ++struct eeprom_platform_data { ++ char *label; /* device label to use with the eeprom class */ ++}; ++ ++/* ++ * EEPROM device structure ++ * ++ * This structure is used by the eeprom_class driver to manage the ++ * state of the class device. ++ * ++ */ ++struct eeprom_device { ++ struct device *dev; ++ struct eeprom_platform_data *data; ++}; ++ ++#if defined(CONFIG_EEPROM_CLASS) || defined (CONFIG_EEPROM_CLASS_MODULE) ++ ++extern struct eeprom_device * ++eeprom_device_register(struct device *dev, struct eeprom_platform_data *data); ++extern void ++eeprom_device_unregister(struct eeprom_device *eeprom_dev); ++ ++#else ++ ++static inline struct eeprom_device * ++eeprom_device_register(struct device *dev, char *label) ++{ ++ return NULL; ++} ++ ++static inline void ++eeprom_device_unregister(struct eeprom_device *eeprom_dev) ++{ ++} ++ ++#endif ++ ++#endif /* EEPROM_CLASS_H__ */ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 88c953d..e3f80ba 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch new file mode 100644 index 00000000..09400652 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch @@ -0,0 +1,193 @@ +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -114,6 +114,14 @@ typedef struct { + u32 imagesize; + } efi_capsule_header_t; + ++/* ++ * Allocation types for calls to boottime->allocate_pages. ++ */ ++#define EFI_ALLOCATE_ANY_PAGES 0 ++#define EFI_ALLOCATE_MAX_ADDRESS 1 ++#define EFI_ALLOCATE_ADDRESS 2 ++#define EFI_MAX_ALLOCATE_TYPE 3 ++ + typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); + + /* +@@ -144,6 +152,57 @@ typedef struct { + } efi_time_cap_t; + + /* ++ * EFI Boot Services table ++ */ ++typedef struct { ++ efi_table_hdr_t hdr; ++ void *raise_tpl; ++ void *restore_tpl; ++ void *allocate_pages; ++ void *free_pages; ++ void *get_memory_map; ++ void *allocate_pool; ++ void *free_pool; ++ void *create_event; ++ void *set_timer; ++ void *wait_for_event; ++ void *signal_event; ++ void *close_event; ++ void *check_event; ++ void *install_protocol_interface; ++ void *reinstall_protocol_interface; ++ void *uninstall_protocol_interface; ++ void *handle_protocol; ++ void *__reserved; ++ void *register_protocol_notify; ++ void *locate_handle; ++ void *locate_device_path; ++ void *install_configuration_table; ++ void *load_image; ++ void *start_image; ++ void *exit; ++ void *unload_image; ++ void *exit_boot_services; ++ void *get_next_monotonic_count; ++ void *stall; ++ void *set_watchdog_timer; ++ void *connect_controller; ++ void *disconnect_controller; ++ void *open_protocol; ++ void *close_protocol; ++ void *open_protocol_information; ++ void *protocols_per_handle; ++ void *locate_handle_buffer; ++ void *locate_protocol; ++ void *install_multiple_protocol_interfaces; ++ void *uninstall_multiple_protocol_interfaces; ++ void *calculate_crc32; ++ void *copy_mem; ++ void *set_mem; ++ void *create_event_ex; ++} efi_boot_services_t; ++ ++/* + * Types and defines for EFI ResetSystem + */ + #define EFI_RESET_COLD 0 +@@ -242,6 +301,24 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si + #define LINUX_EFI_CRASH_GUID \ + EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 ) + ++#define LOADED_IMAGE_PROTOCOL_GUID \ ++ EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) ++ ++#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ ++ EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a ) ++ ++#define EFI_UGA_PROTOCOL_GUID \ ++ EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 ) ++ ++#define EFI_PCI_IO_PROTOCOL_GUID \ ++ EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a ) ++ ++#define EFI_FILE_INFO_ID \ ++ EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) ++ ++#define EFI_FILE_SYSTEM_GUID \ ++ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) ++ + typedef struct { + efi_guid_t guid; + unsigned long table; +@@ -267,7 +344,7 @@ typedef struct { + unsigned long stderr_handle; + unsigned long stderr; + efi_runtime_services_t *runtime; +- unsigned long boottime; ++ efi_boot_services_t *boottime; + unsigned long nr_tables; + unsigned long tables; + } efi_system_table_t; +@@ -281,6 +358,56 @@ struct efi_memory_map { + unsigned long desc_size; + }; + ++typedef struct { ++ u32 revision; ++ void *parent_handle; ++ efi_system_table_t *system_table; ++ void *device_handle; ++ void *file_path; ++ void *reserved; ++ u32 load_options_size; ++ void *load_options; ++ void *image_base; ++ __aligned_u64 image_size; ++ unsigned int image_code_type; ++ unsigned int image_data_type; ++ unsigned long unload; ++} efi_loaded_image_t; ++ ++typedef struct { ++ u64 revision; ++ void *open_volume; ++} efi_file_io_interface_t; ++ ++typedef struct { ++ u64 size; ++ u64 file_size; ++ u64 phys_size; ++ efi_time_t create_time; ++ efi_time_t last_access_time; ++ efi_time_t modification_time; ++ __aligned_u64 attribute; ++ efi_char16_t filename[1]; ++} efi_file_info_t; ++ ++typedef struct { ++ u64 revision; ++ void *open; ++ void *close; ++ void *delete; ++ void *read; ++ void *write; ++ void *get_position; ++ void *set_position; ++ void *get_info; ++ void *set_info; ++ void *flush; ++} efi_file_handle_t; ++ ++#define EFI_FILE_MODE_READ 0x0000000000000001 ++#define EFI_FILE_MODE_WRITE 0x0000000000000002 ++#define EFI_FILE_MODE_CREATE 0x8000000000000000 ++ + #define EFI_INVALID_TABLE_ADDR (~0UL) + + /* +@@ -390,7 +517,9 @@ extern int __init efi_setup_pcdp_console(char *); + + #ifdef CONFIG_EFI + # ifdef CONFIG_X86 +-extern int efi_enabled(int facility); ++extern int efi_enabled; /* ABI compat; please use efi_enabled() instead */ ++extern int efi_enabled_facility(int facility); ++#define efi_enabled(f) efi_enabled_facility(f) + # else + static inline int efi_enabled(int facility) + { +@@ -423,6 +552,13 @@ static inline int efi_enabled(int facility) + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_APPEND_WRITE) + /* ++ * The type of search to perform when calling boottime->locate_handle ++ */ ++#define EFI_LOCATE_ALL_HANDLES 0 ++#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 ++#define EFI_LOCATE_BY_PROTOCOL 2 ++ ++/* + * EFI Device Path information + */ + #define EFI_DEV_HW 0x01 +diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h +index 05955cf..ae9c1f6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch new file mode 100644 index 00000000..dff10b32 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch @@ -0,0 +1,61 @@ +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -118,6 +118,24 @@ struct ethtool_eeprom { + }; + + /** ++ * struct ethtool_modinfo - plugin module eeprom information ++ * @cmd: %ETHTOOL_GMODULEINFO ++ * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx ++ * @eeprom_len: Length of the eeprom ++ * ++ * This structure is used to return the information to ++ * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. ++ * The type code indicates the eeprom data format ++ */ ++struct ethtool_modinfo { ++ __u32 cmd; ++ __u32 type; ++ __u32 eeprom_len; ++ __u32 eeprom_nums; ++ __u32 reserved[7]; ++}; ++ ++/** + * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates + * @cmd: ETHTOOL_{G,S}COALESCE + * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after +@@ -930,6 +948,8 @@ struct ethtool_ops { + int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); + void (*get_ethtool_stats)(struct net_device *, + struct ethtool_stats *, u64 *); ++ void (*get_ethtool_stats_clear)(struct net_device *, ++ struct ethtool_stats *, u64 *); + int (*begin)(struct net_device *); + void (*complete)(struct net_device *); + u32 (*get_ufo)(struct net_device *); +@@ -956,6 +976,10 @@ struct ethtool_ops { + int (*get_dump_data)(struct net_device *, + struct ethtool_dump *, void *); + int (*set_dump)(struct net_device *, struct ethtool_dump *); ++ int (*get_module_info)(struct net_device *, ++ struct ethtool_modinfo *); ++ int (*get_module_eeprom)(struct net_device *, ++ struct ethtool_eeprom *, u8 *); + + }; + #endif /* __KERNEL__ */ +@@ -1030,6 +1054,10 @@ struct ethtool_ops { + #define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ + #define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ + #define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ ++#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ ++#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ ++ ++#define ETHTOOL_GSTATS_CLEAR 0x1000001d /* get NIC-specific statistics and clear */ + + /* compatibility with older code */ + #define SPARC_ETH_GSET ETHTOOL_GSET +diff --git a/include/linux/fmd/Kbuild b/include/linux/fmd/Kbuild +new file mode 100644 +index 0000000..56a2040 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch new file mode 100644 index 00000000..d6b63fe4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch @@ -0,0 +1,23 @@ +--- a/include/linux/ftrace_event.h ++++ b/include/linux/ftrace_event.h +@@ -71,8 +71,6 @@ struct trace_iterator { + /* trace_seq for __print_flags() and __print_symbolic() etc. */ + struct trace_seq tmp_seq; + +- cpumask_var_t started; +- + /* The below is zeroed out in pipe_read */ + struct trace_seq seq; + struct trace_entry *ent; +@@ -85,7 +83,7 @@ struct trace_iterator { + loff_t pos; + long idx; + +- /* All new field here will be zeroed out in pipe_read */ ++ cpumask_var_t started; + }; + + +diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h +new file mode 100644 +index 0000000..227c624 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch new file mode 100644 index 00000000..adef322b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch @@ -0,0 +1,197 @@ +--- /dev/null ++++ b/include/linux/hashtable.h +@@ -0,0 +1,192 @@ ++/* ++ * Statically sized hash table implementation ++ * (C) 2012 Sasha Levin ++ */ ++ ++#ifndef _LINUX_HASHTABLE_H ++#define _LINUX_HASHTABLE_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define DEFINE_HASHTABLE(name, bits) \ ++ struct hlist_head name[1 << (bits)] = \ ++ { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } ++ ++#define DECLARE_HASHTABLE(name, bits) \ ++ struct hlist_head name[1 << (bits)] ++ ++#define HASH_SIZE(name) (ARRAY_SIZE(name)) ++#define HASH_BITS(name) ilog2(HASH_SIZE(name)) ++ ++/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */ ++#define hash_min(val, bits) \ ++ (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)) ++ ++static inline void __hash_init(struct hlist_head *ht, unsigned int sz) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < sz; i++) ++ INIT_HLIST_HEAD(&ht[i]); ++} ++ ++/** ++ * hash_init - initialize a hash table ++ * @hashtable: hashtable to be initialized ++ * ++ * Calculates the size of the hashtable from the given parameter, otherwise ++ * same as hash_init_size. ++ * ++ * This has to be a macro since HASH_BITS() will not work on pointers since ++ * it calculates the size during preprocessing. ++ */ ++#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable)) ++ ++/** ++ * hash_add - add an object to a hashtable ++ * @hashtable: hashtable to add to ++ * @node: the &struct hlist_node of the object to be added ++ * @key: the key of the object to be added ++ */ ++#define hash_add(hashtable, node, key) \ ++ hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) ++ ++/** ++ * hash_add_rcu - add an object to a rcu enabled hashtable ++ * @hashtable: hashtable to add to ++ * @node: the &struct hlist_node of the object to be added ++ * @key: the key of the object to be added ++ */ ++#define hash_add_rcu(hashtable, node, key) \ ++ hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) ++ ++/** ++ * hash_hashed - check whether an object is in any hashtable ++ * @node: the &struct hlist_node of the object to be checked ++ */ ++static inline bool hash_hashed(struct hlist_node *node) ++{ ++ return !hlist_unhashed(node); ++} ++ ++static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < sz; i++) ++ if (!hlist_empty(&ht[i])) ++ return false; ++ ++ return true; ++} ++ ++/** ++ * hash_empty - check whether a hashtable is empty ++ * @hashtable: hashtable to check ++ * ++ * This has to be a macro since HASH_BITS() will not work on pointers since ++ * it calculates the size during preprocessing. ++ */ ++#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable)) ++ ++/** ++ * hash_del - remove an object from a hashtable ++ * @node: &struct hlist_node of the object to remove ++ */ ++static inline void hash_del(struct hlist_node *node) ++{ ++ hlist_del_init(node); ++} ++ ++/** ++ * hash_del_rcu - remove an object from a rcu enabled hashtable ++ * @node: &struct hlist_node of the object to remove ++ */ ++static inline void hash_del_rcu(struct hlist_node *node) ++{ ++ hlist_del_init_rcu(node); ++} ++ ++/** ++ * hash_for_each - iterate over a hashtable ++ * @name: hashtable to iterate ++ * @bkt: integer to use as bucket loop cursor ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @obj: the type * to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ */ ++#define hash_for_each(name, bkt, node, obj, member) \ ++ for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ ++ hlist_for_each_entry(obj, node, &name[bkt], member) ++ ++/** ++ * hash_for_each_rcu - iterate over a rcu enabled hashtable ++ * @name: hashtable to iterate ++ * @bkt: integer to use as bucket loop cursor ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @obj: the type * to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ */ ++#define hash_for_each_rcu(name, bkt, node, obj, member) \ ++ for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ ++ hlist_for_each_entry_rcu(obj, node, &name[bkt], member) ++ ++/** ++ * hash_for_each_safe - iterate over a hashtable safe against removal of ++ * hash entry ++ * @name: hashtable to iterate ++ * @bkt: integer to use as bucket loop cursor ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @tmp: a &struct used for temporary storage ++ * @obj: the type * to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ */ ++#define hash_for_each_safe(name, bkt, node, tmp, obj, member) \ ++ for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ ++ hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member) ++ ++/** ++ * hash_for_each_possible - iterate over all possible objects hashing to the ++ * same bucket ++ * @name: hashtable to iterate ++ * @obj: the type * to use as a loop cursor for each entry ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ * @key: the key of the objects to iterate over ++ */ ++#define hash_for_each_possible(name, obj, node, member, key) \ ++ hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member) ++ ++/** ++ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the ++ * same bucket in an rcu enabled hashtable ++ * in a rcu enabled hashtable ++ * @name: hashtable to iterate ++ * @obj: the type * to use as a loop cursor for each entry ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ * @key: the key of the objects to iterate over ++ */ ++#define hash_for_each_possible_rcu(name, obj, node, member, key) \ ++ hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member) ++ ++/** ++ * hash_for_each_possible_safe - iterate over all possible objects hashing to the ++ * same bucket safe against removals ++ * @name: hashtable to iterate ++ * @obj: the type * to use as a loop cursor for each entry ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @tmp: a &struct used for temporary storage ++ * @member: the name of the hlist_node within the struct ++ * @key: the key of the objects to iterate over ++ */ ++#define hash_for_each_possible_safe(name, obj, node, tmp, member, key) \ ++ hlist_for_each_entry_safe(obj, node, tmp, \ ++ &name[hash_min(key, HASH_BITS(name))], member) ++ ++ ++#endif +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 19fe719..0d07520 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch new file mode 100644 index 00000000..ed32ebdd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch @@ -0,0 +1,48 @@ +--- /dev/null ++++ b/include/linux/i2c-mux-gpio.h +@@ -0,0 +1,43 @@ ++/* ++ * i2c-mux-gpio interface to platform code ++ * ++ * Peter Korsgaard ++ * ++ * 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 _LINUX_I2C_MUX_GPIO_H ++#define _LINUX_I2C_MUX_GPIO_H ++ ++/* MUX has no specific idle mode */ ++#define I2C_MUX_GPIO_NO_IDLE ((unsigned)-1) ++ ++/** ++ * struct i2c_mux_gpio_platform_data - Platform-dependent data for i2c-mux-gpio ++ * @parent: Parent I2C bus adapter number ++ * @base_nr: Base I2C bus number to number adapters from or zero for dynamic ++ * @values: Array of bitmasks of GPIO settings (low/high) for each ++ * position ++ * @n_values: Number of multiplexer positions (busses to instantiate) ++ * @classes: Optional I2C auto-detection classes ++ * @gpio_chip: Optional GPIO chip name; if set, GPIO pin numbers are given ++ * relative to the base GPIO number of that chip ++ * @gpios: Array of GPIO numbers used to control MUX ++ * @n_gpios: Number of GPIOs used to control MUX ++ * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used ++ */ ++struct i2c_mux_gpio_platform_data { ++ int parent; ++ int base_nr; ++ const unsigned *values; ++ int n_values; ++ const unsigned *classes; ++ char *gpio_chip; ++ const unsigned *gpios; ++ int n_gpios; ++ unsigned idle; ++}; ++ ++#endif /* _LINUX_I2C_MUX_GPIO_H */ +diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h +index 34536ef..260ca6a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch new file mode 100644 index 00000000..9fc0acdc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/i2c-mux.h ++++ b/include/linux/i2c-mux.h +@@ -33,7 +33,8 @@ + * mux control. + */ + 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 *mux_dev, u32 chan_id), + int (*deselect) (struct i2c_adapter *, +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index 07d103a..8e25a91 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch new file mode 100644 index 00000000..1d2bdba9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch @@ -0,0 +1,24 @@ +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -482,6 +482,19 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) + { + return adap->nr; + } ++ ++/** ++ * module_i2c_driver() - Helper macro for registering a I2C driver ++ * @__i2c_driver: i2c_driver struct ++ * ++ * Helper macro for I2C drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_i2c_driver(__i2c_driver) \ ++ module_driver(__i2c_driver, i2c_add_driver, \ ++ i2c_del_driver) ++ + #endif /* I2C */ + #endif /* __KERNEL__ */ + +diff --git a/include/linux/i2c/at24.h b/include/linux/i2c/at24.h +index 8ace930..3bdb466 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch new file mode 100644 index 00000000..baf04915 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch @@ -0,0 +1,24 @@ +--- a/include/linux/i2c/at24.h ++++ b/include/linux/i2c/at24.h +@@ -3,6 +3,7 @@ + + #include + #include ++#include + + /* + * As seen through Linux I2C, differences between the most common types of I2C +@@ -24,9 +25,11 @@ struct at24_platform_data { + #define AT24_FLAG_READONLY 0x40 /* sysfs-entry will be read-only */ + #define AT24_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */ + #define AT24_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */ ++#define AT24_FLAG_DISABLE_I2CBLOCK 0x08 /*disable smbus i2c block access */ + + void (*setup)(struct memory_accessor *, void *context); + void *context; ++ struct eeprom_platform_data *eeprom_data; /* extra data for the eeprom_class */ + }; + + #endif /* _LINUX_AT24_H */ +diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h +index 139ba52..2a69244 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch new file mode 100644 index 00000000..1ee3f606 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/i2c/pca953x.h ++++ b/include/linux/i2c/pca953x.h +@@ -11,7 +11,7 @@ struct pca953x_platform_data { + unsigned gpio_base; + + /* initial polarity inversion setting */ +- uint16_t invert; ++ uint32_t invert; + + /* interrupt base */ + int irq_base; +diff --git a/include/linux/i2c/quanta-i2cmux.h b/include/linux/i2c/quanta-i2cmux.h +new file mode 100644 +index 0000000..042dcd2 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch new file mode 100644 index 00000000..2a8a4506 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch @@ -0,0 +1,38 @@ +--- /dev/null ++++ b/include/linux/i2c/sff-8436.h +@@ -0,0 +1,33 @@ ++#ifndef _LINUX_SFF_8436_H ++#define _LINUX_SFF_8436_H ++ ++#include ++#include ++#include ++ ++/* ++ * As seen through Linux I2C, differences between the most common types of I2C ++ * memory include: ++ * - How much memory is available (usually specified in bit)? ++ * - What write page size does it support? ++ * - Special flags (read_only, world readable...)? ++ * ++ * If you set up a custom eeprom type, please double-check the parameters. ++ * Especially page_size needs extra care, as you risk data loss if your value ++ * is bigger than what the chip actually supports! ++ */ ++ ++struct sff_8436_platform_data { ++ u32 byte_len; /* size (sum of all addr) */ ++ u16 page_size; /* for writes */ ++ u8 flags; ++#define SFF_8436_FLAG_READONLY 0x40 /* sysfs-entry will be read-only */ ++#define SFF_8436_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */ ++#define SFF_8436_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */ ++ ++ void (*setup)(struct memory_accessor *, void *context); ++ void *context; ++ struct eeprom_platform_data *eeprom_data; /* extra data for the eeprom_class */ ++}; ++ ++#endif /* _LINUX_SFF_8436_H */ +diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h +index a17edda..13f3ed0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch new file mode 100644 index 00000000..4401a0d9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch @@ -0,0 +1,132 @@ +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -14,6 +14,7 @@ + #define _LINUX_IF_BRIDGE_H + + #include ++#include + + #define SYSFS_BRIDGE_ATTR "bridge" + #define SYSFS_BRIDGE_FDB "brforward" +@@ -94,9 +95,118 @@ struct __fdb_entry { + __u32 ageing_timer_value; + __u8 port_hi; + __u8 pad0; +- __u16 unused; ++ __u16 vlan; + }; + ++/* Bridge Flags */ ++#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ ++#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ ++ ++#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ ++#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ ++ ++/* Bridge management nested attributes ++ * [IFLA_AF_SPEC] = { ++ * [IFLA_BRIDGE_FLAGS] ++ * [IFLA_BRIDGE_MODE] ++ * [IFLA_BRIDGE_VLAN_INFO] ++ * } ++ */ ++enum { ++ IFLA_BRIDGE_FLAGS, ++ IFLA_BRIDGE_MODE, ++ IFLA_BRIDGE_VLAN_INFO, ++ __IFLA_BRIDGE_MAX, ++}; ++#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) ++ ++#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */ ++#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */ ++#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ ++ ++struct bridge_vlan_info { ++ __u16 flags; ++ __u16 vid; ++ __u16 vid_end; ++}; ++ ++/* Bridge multicast database attributes ++ * [MDBA_MDB] = { ++ * [MDBA_MDB_ENTRY] = { ++ * [MDBA_MDB_ENTRY_INFO] ++ * } ++ * } ++ * [MDBA_ROUTER] = { ++ * [MDBA_ROUTER_PORT] ++ * } ++ */ ++enum { ++ MDBA_UNSPEC, ++ MDBA_MDB, ++ MDBA_ROUTER, ++ __MDBA_MAX, ++}; ++#define MDBA_MAX (__MDBA_MAX - 1) ++ ++enum { ++ MDBA_MDB_UNSPEC, ++ MDBA_MDB_ENTRY, ++ __MDBA_MDB_MAX, ++}; ++#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) ++ ++enum { ++ MDBA_MDB_ENTRY_UNSPEC, ++ MDBA_MDB_ENTRY_INFO, ++ __MDBA_MDB_ENTRY_MAX, ++}; ++#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) ++ ++enum { ++ MDBA_ROUTER_UNSPEC, ++ MDBA_ROUTER_PORT, ++ __MDBA_ROUTER_MAX, ++}; ++#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) ++ ++struct br_port_msg { ++ __u8 family; ++ __u16 vlan; ++ __u32 ifindex; ++}; ++ ++struct br_mdb_entry { ++ __u32 ifindex; ++#define MDB_TEMPORARY 0 ++#define MDB_PERMANENT 1 ++ __u8 state; ++ struct { ++ union { ++ __be32 ip4; ++ struct in6_addr ip6; ++ } u; ++ __be16 proto; ++ __be16 vlan_id; ++ } addr; ++ __u32 timer; ++}; ++ ++struct br_mdb_rtr_entry { ++ __u32 ifindex; ++ __u32 timer; ++#define MDB_RTR_TEMPORARY 0 ++#define MDB_RTR_PERMANENT 1 ++ __u8 state; ++}; ++ ++enum { ++ MDBA_SET_ENTRY_UNSPEC, ++ MDBA_SET_ENTRY, ++ __MDBA_SET_ENTRY_MAX, ++}; ++#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) ++ ++ + #ifdef __KERNEL__ + + #include +diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h +index e473003..2d21664 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch new file mode 100644 index 00000000..86bc35f6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/if_ether.h ++++ b/include/linux/if_ether.h +@@ -91,6 +91,9 @@ + #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ + #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ + ++#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value ++ * then the frame is Ethernet II. Else it is 802.3 */ ++ + /* + * Non DIX types. Won't clash for 1500 types. + */ +diff --git a/include/linux/if_link.h b/include/linux/if_link.h +index 4b24ff4..eb0b75d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch new file mode 100644 index 00000000..3ae02294 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch @@ -0,0 +1,210 @@ +--- a/include/linux/if_link.h ++++ b/include/linux/if_link.h +@@ -137,7 +137,20 @@ enum { + IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ + IFLA_NET_NS_FD, ++#ifndef __GENKSYMS__ + IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ ++#endif ++ IFLA_PROMISCUITY, /* not supported */ ++#define IFLA_PROMISCUITY IFLA_PROMISCUITY ++ IFLA_NUM_TX_QUEUES, /* not supported */ ++ IFLA_NUM_RX_QUEUES, /* not supported */ ++ IFLA_CARRIER, /* not supported */ ++ IFLA_PHYS_PORT_ID, /* not supported */ ++ IFLA_CARRIER_CHANGES, ++ IFLA_PHYS_SWITCH_ID, /* not supported */ ++ IFLA_LINK_NETNSID, /* not supported */ ++ IFLA_PHYS_PORT_NAME, /* not supported */ ++ IFLA_PROTO_DOWN, + __IFLA_MAX + }; + +@@ -201,6 +214,44 @@ enum { + + #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + ++/* Bridge section */ ++/* CL note: ageing_time, stp_state and priority are not supported */ ++enum { ++ IFLA_BR_UNSPEC, ++ IFLA_BR_FORWARD_DELAY, ++ IFLA_BR_HELLO_TIME, ++ IFLA_BR_MAX_AGE, ++ IFLA_BR_AGEING_TIME, ++ IFLA_BR_STP_STATE, ++ IFLA_BR_PRIORITY, ++ IFLA_BR_VLAN_FILTERING, ++ __IFLA_BR_MAX, ++}; ++ ++#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) ++ ++enum { ++ BRIDGE_MODE_UNSPEC, ++ BRIDGE_MODE_HAIRPIN, ++}; ++ ++enum { ++ IFLA_BRPORT_UNSPEC, ++ IFLA_BRPORT_STATE, /* Spanning tree state */ ++ IFLA_BRPORT_PRIORITY, /* " priority */ ++ IFLA_BRPORT_COST, /* " cost */ ++ IFLA_BRPORT_MODE, /* mode (hairpin) */ ++ IFLA_BRPORT_GUARD, /* bpdu guard */ ++ IFLA_BRPORT_PROTECT, /* root port protection */ ++ IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ ++ IFLA_BRPORT_LEARNING, /* mac learning */ ++ IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ ++ IFLA_BRPORT_PEER_LINK = 253, /* MLAG peer link */ ++ IFLA_BRPORT_DUAL_LINK, /* MLAG Dual Connected link */ ++ __IFLA_BRPORT_MAX ++}; ++#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) ++ + struct ifla_cacheinfo { + __u32 max_reasm_len; + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ +@@ -213,6 +264,8 @@ enum { + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, ++ IFLA_INFO_SLAVE_KIND, ++ IFLA_INFO_SLAVE_DATA, + __IFLA_INFO_MAX, + }; + +@@ -226,6 +279,7 @@ enum { + IFLA_VLAN_FLAGS, + IFLA_VLAN_EGRESS_QOS, + IFLA_VLAN_INGRESS_QOS, ++ IFLA_VLAN_PROTOCOL, + __IFLA_VLAN_MAX, + }; + +@@ -265,6 +319,122 @@ enum macvlan_mode { + MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ + }; + ++/* VXLAN section */ ++enum { ++ IFLA_VXLAN_UNSPEC, ++ IFLA_VXLAN_ID, ++ IFLA_VXLAN_GROUP, ++ IFLA_VXLAN_LINK, ++ IFLA_VXLAN_LOCAL, ++ IFLA_VXLAN_TTL, ++ IFLA_VXLAN_TOS, ++ IFLA_VXLAN_LEARNING, ++ IFLA_VXLAN_AGEING, ++ IFLA_VXLAN_LIMIT, ++ IFLA_VXLAN_PORT_RANGE, ++ IFLA_VXLAN_PROXY, ++ IFLA_VXLAN_RSC, ++ IFLA_VXLAN_L2MISS, ++ IFLA_VXLAN_L3MISS, ++ IFLA_VXLAN_PORT, /* destination port */ ++ IFLA_VXLAN_GROUP6, ++ IFLA_VXLAN_LOCAL6, ++ IFLA_VXLAN_UDP_CSUM, ++ IFLA_VXLAN_UDP_ZERO_CSUM6_TX, ++ IFLA_VXLAN_UDP_ZERO_CSUM6_RX, ++ IFLA_VXLAN_REMCSUM_TX, ++ IFLA_VXLAN_REMCSUM_RX, ++ IFLA_VXLAN_GBP, ++ IFLA_VXLAN_REMCSUM_NOPARTIAL, ++ IFLA_VXLAN_REPLICATION_NODE = 253, ++ IFLA_VXLAN_REPLICATION_TYPE, ++ __IFLA_VXLAN_MAX ++}; ++#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) ++ ++struct ifla_vxlan_port_range { ++ __be16 low; ++ __be16 high; ++}; ++ ++#define MAX_VXLAN_REPLICATION_NODE_ADDRS 64 ++struct ifla_vxlan_repl_node_addrs { ++ __u32 addrs[MAX_VXLAN_REPLICATION_NODE_ADDRS]; ++}; ++ ++enum { ++ VXLAN_REPLICATION_NONE = 0, ++ VXLAN_REPLICATION_SERVICE_NODE, /* service node based replication */ ++ VXLAN_REPLICATION_SELF, /* self or head-end replication */ ++}; ++ ++/* Bonding section */ ++ ++enum { ++ IFLA_BOND_UNSPEC, ++ IFLA_BOND_MODE, ++ IFLA_BOND_ACTIVE_SLAVE, ++ IFLA_BOND_MIIMON, ++ IFLA_BOND_UPDELAY, ++ IFLA_BOND_DOWNDELAY, ++ IFLA_BOND_USE_CARRIER, ++ IFLA_BOND_ARP_INTERVAL, ++ IFLA_BOND_ARP_IP_TARGET, ++ IFLA_BOND_ARP_VALIDATE, ++ IFLA_BOND_ARP_ALL_TARGETS, ++ IFLA_BOND_PRIMARY, ++ IFLA_BOND_PRIMARY_RESELECT, ++ IFLA_BOND_FAIL_OVER_MAC, ++ IFLA_BOND_XMIT_HASH_POLICY, ++ IFLA_BOND_RESEND_IGMP, ++ IFLA_BOND_NUM_PEER_NOTIF, ++ IFLA_BOND_ALL_SLAVES_ACTIVE, ++ IFLA_BOND_MIN_LINKS, ++ IFLA_BOND_LP_INTERVAL, ++ IFLA_BOND_PACKETS_PER_SLAVE, ++ IFLA_BOND_AD_LACP_RATE, ++ IFLA_BOND_AD_SELECT, ++ IFLA_BOND_AD_INFO, ++ ++ IFLA_BOND_CL_START = 100, ++ IFLA_BOND_CL_LACP_BYPASS_ALLOW = IFLA_BOND_CL_START, ++ IFLA_BOND_CL_LACP_BYPASS_ACTIVE, ++ IFLA_BOND_CL_LACP_BYPASS_PERIOD, ++ IFLA_BOND_CL_CLAG_ENABLE, ++ IFLA_BOND_CL_LACP_BYPASS_ALL_ACTIVE, ++ __IFLA_BOND_MAX, ++}; ++ ++#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) ++ ++enum { ++ IFLA_BOND_AD_INFO_UNSPEC, ++ IFLA_BOND_AD_INFO_AGGREGATOR, ++ IFLA_BOND_AD_INFO_NUM_PORTS, ++ IFLA_BOND_AD_INFO_ACTOR_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_MAC, ++ __IFLA_BOND_AD_INFO_MAX, ++}; ++ ++#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) ++ ++enum { ++ IFLA_BOND_SLAVE_UNSPEC, ++ IFLA_BOND_SLAVE_STATE, ++ IFLA_BOND_SLAVE_MII_STATUS, ++ IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, ++ IFLA_BOND_SLAVE_PERM_HWADDR, ++ IFLA_BOND_SLAVE_QUEUE_ID, ++ IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, ++ ++ IFLA_BOND_SLAVE_CL_START = 50, ++ IFLA_BOND_SLAVE_CL_LACP_BYPASS_PRIO = IFLA_BOND_SLAVE_CL_START, ++ __IFLA_BOND_SLAVE_MAX, ++}; ++ ++#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) ++ + /* SR-IOV virtual function management section */ + + enum { +diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h +index 06b1829..6dd06d3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch new file mode 100644 index 00000000..dd36db07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch @@ -0,0 +1,40 @@ +--- a/include/linux/if_tun.h ++++ b/include/linux/if_tun.h +@@ -34,6 +34,7 @@ + #define TUN_ONE_QUEUE 0x0080 + #define TUN_PERSIST 0x0100 + #define TUN_VNET_HDR 0x0200 ++#define TUN_SET_CARRIER 0x0400 + + /* Ioctl defines */ + #define TUNSETNOCSUM _IOW('T', 200, int) +@@ -55,12 +56,13 @@ + #define TUNSETVNETHDRSZ _IOW('T', 216, int) + + /* TUNSETIFF ifr flags */ +-#define IFF_TUN 0x0001 +-#define IFF_TAP 0x0002 +-#define IFF_NO_PI 0x1000 +-#define IFF_ONE_QUEUE 0x2000 +-#define IFF_VNET_HDR 0x4000 +-#define IFF_TUN_EXCL 0x8000 ++#define IFF_TUN 0x0001 ++#define IFF_TAP 0x0002 ++#define IFF_NO_PI 0x1000 ++#define IFF_ONE_QUEUE 0x2000 ++#define IFF_VNET_HDR 0x4000 ++#define IFF_TUN_EXCL 0x8000 ++#define IFF_TUN_SET_CARRIER 0x0008 + + /* Features for GSO (TUNSETOFFLOAD). */ + #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ +@@ -68,6 +70,7 @@ + #define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ + #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ + #define TUN_F_UFO 0x10 /* I can handle UFO packets */ ++#define TUN_F_HW_SWITCH_OFFLOAD 0x20 /* I can handle switch offloaded packets */ + + /* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ + #define TUN_PKT_STRIP 0x0001 +diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h +index c944c4f..344e6ab 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch new file mode 100644 index 00000000..435b379f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/init.h ++++ b/include/linux/init.h +@@ -82,12 +82,22 @@ + #define __exit __section(.exit.text) __exitused __cold notrace + + /* Used for HOTPLUG */ ++/* XXX - hack to disable __devinit for DPA drivers */ ++#ifdef CONFIG_DPA ++#define __devinit ++#define __devinitdata ++#define __devinitconst ++#define __devexit ++#define __devexitdata ++#define __devexitconst ++#else + #define __devinit __section(.devinit.text) __cold notrace + #define __devinitdata __section(.devinit.data) + #define __devinitconst __section(.devinit.rodata) + #define __devexit __section(.devexit.text) __exitused __cold notrace + #define __devexitdata __section(.devexit.data) + #define __devexitconst __section(.devexit.rodata) ++#endif + + /* Used for HOTPLUG_CPU */ + #define __cpuinit __section(.cpuinit.text) __cold notrace +diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h +index 318bb82..0c74dfd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch new file mode 100644 index 00000000..d0cd6c52 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch @@ -0,0 +1,24 @@ +--- a/include/linux/irqdesc.h ++++ b/include/linux/irqdesc.h +@@ -55,8 +55,6 @@ struct irq_desc { + unsigned int irq_count; /* For detecting broken IRQs */ + unsigned long last_unhandled; /* Aging timer for unhandled count */ + unsigned int irqs_unhandled; +- atomic_t threads_handled; +- int threads_handled_last; + raw_spinlock_t lock; + struct cpumask *percpu_enabled; + #ifdef CONFIG_SMP +@@ -74,6 +72,10 @@ struct irq_desc { + #endif + struct module *owner; + const char *name; ++#ifndef __GENKSYMS__ ++ atomic_t threads_handled; ++ int threads_handled_last; ++#endif + } ____cacheline_internodealigned_in_smp; + + #ifndef CONFIG_SPARSE_IRQ +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 4920c55..dce0ef5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch new file mode 100644 index 00000000..716b3624 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -470,7 +470,9 @@ struct transaction_s + T_COMMIT, + T_COMMIT_DFLUSH, + T_COMMIT_JFLUSH, ++#ifndef __GENKSYMS__ + T_COMMIT_CALLBACK, ++#endif + T_FINISHED + } t_state; + +diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h +index f4e8578..333dea6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch new file mode 100644 index 00000000..8abe5bfc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -292,6 +292,11 @@ extern unsigned long timeval_to_jiffies(const struct timeval *value); + extern void jiffies_to_timeval(const unsigned long jiffies, + struct timeval *value); + extern clock_t jiffies_to_clock_t(unsigned long x); ++static inline clock_t jiffies_delta_to_clock_t(long delta) ++{ ++ return jiffies_to_clock_t(max(0L, delta)); ++} ++ + extern unsigned long clock_t_to_jiffies(unsigned long x); + extern u64 jiffies_64_to_clock_t(u64 x); + extern u64 nsec_to_clock_t(u64 x); +diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h +index ee0c952..35f7237 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch new file mode 100644 index 00000000..02d95f30 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -50,6 +50,7 @@ + #define KVM_REQ_APF_HALT 12 + #define KVM_REQ_STEAL_UPDATE 13 + #define KVM_REQ_NMI 14 ++#define KVM_REQ_IMMEDIATE_EXIT 15 + + #define KVM_USERSPACE_IRQ_SOURCE_ID 0 + +diff --git a/include/linux/libata.h b/include/linux/libata.h +index 000434e..a548ffd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch new file mode 100644 index 00000000..a0a960a6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch @@ -0,0 +1,61 @@ +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -42,7 +42,11 @@ + #define MDIO_PKGID2 15 + #define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ + #define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ ++#define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */ ++#define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */ + #define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ ++#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ ++#define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */ + + /* Media-dependent registers. */ + #define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */ +@@ -55,7 +59,6 @@ + #define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */ + #define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */ + #define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */ +-#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ + + /* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */ + #define MDIO_PMA_LASI_RXCTRL 0x9000 /* RX_ALARM control */ +@@ -81,6 +84,7 @@ + #define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART + #define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE + #define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */ ++#define MDIO_PCS_CTRL1_CLKSTOP_EN 0x400 /* Stop the clock during LPI */ + + /* 10 Gb/s */ + #define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00) +@@ -236,9 +240,25 @@ + #define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */ + #define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */ + +-/* AN EEE Advertisement register. */ +-#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */ +-#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */ ++/* EEE Supported/Advertisement/LP Advertisement registers. ++ * ++ * EEE capability Register (3.20), Advertisement (7.60) and ++ * Link partner ability (7.61) registers have and can use the same identical ++ * bit masks. ++ */ ++#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */ ++#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */ ++/* Note: the two defines above can be potentially used by the user-land ++ * and cannot remove them now. ++ * So, we define the new generic MDIO_EEE_100TX and MDIO_EEE_1000T macros ++ * using the previous ones (that can be considered obsolete). ++ */ ++#define MDIO_EEE_100TX MDIO_AN_EEE_ADV_100TX /* 100TX EEE cap */ ++#define MDIO_EEE_1000T MDIO_AN_EEE_ADV_1000T /* 1000T EEE cap */ ++#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */ ++#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */ ++#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */ ++#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */ + + /* LASI RX_ALARM control/status registers. */ + #define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */ +diff --git a/include/linux/mii.h b/include/linux/mii.h +index 2774823..4212186 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch new file mode 100644 index 00000000..54df4e96 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/mii.h ++++ b/include/linux/mii.h +@@ -20,6 +20,8 @@ + #define MII_EXPANSION 0x06 /* Expansion register */ + #define MII_CTRL1000 0x09 /* 1000BASE-T control */ + #define MII_STAT1000 0x0a /* 1000BASE-T status */ ++#define MII_MMD_CTRL 0x0d /* MMD Access Control Register */ ++#define MII_MMD_DATA 0x0e /* MMD Access Data Register */ + #define MII_ESTATUS 0x0f /* Extended Status */ + #define MII_DCOUNTER 0x12 /* Disconnect counter */ + #define MII_FCSCOUNTER 0x13 /* False carrier counter */ +@@ -140,6 +142,13 @@ + #define FLOW_CTRL_TX 0x01 + #define FLOW_CTRL_RX 0x02 + ++/* MMD Access Control register fields */ ++#define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/ ++#define MII_MMD_CTRL_ADDR 0x0000 /* Address */ ++#define MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */ ++#define MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */ ++#define MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */ ++ + /* This structure is used in all SIOCxMIIxxx ioctl calls */ + struct mii_ioctl_data { + __u16 phy_id; +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index de3a321..a94dbfd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch new file mode 100644 index 00000000..6e721117 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch @@ -0,0 +1,23 @@ +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -297,7 +297,6 @@ struct mm_struct { + void (*unmap_area) (struct mm_struct *mm, unsigned long addr); + #endif + unsigned long mmap_base; /* base of mmap area */ +- unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */ + unsigned long task_size; /* size of task vm space */ + unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ + unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ +@@ -390,6 +389,10 @@ struct mm_struct { + #ifdef CONFIG_CPUMASK_OFFSTACK + struct cpumask cpumask_allocation; + #endif ++ ++#ifndef __GENKSYMS__ ++ unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */ ++#endif + }; + + static inline void mm_init_cpumask(struct mm_struct *mm) +diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h +index 87967ee..d424b9d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch new file mode 100644 index 00000000..bce90b44 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch @@ -0,0 +1,44 @@ +--- a/include/linux/mod_devicetable.h ++++ b/include/linux/mod_devicetable.h +@@ -461,8 +461,13 @@ enum dmi_field { + }; + + struct dmi_strmatch { ++#ifndef __GENKSYMS__ ++ /* Layout supported by dmi_check_system_2() and dmi_first_match_2() */ + unsigned char slot:7; + unsigned char exact_match:1; ++#else ++ unsigned char slot; ++#endif + char substr[79]; + }; + +@@ -544,4 +549,25 @@ struct isapnp_device_id { + kernel_ulong_t driver_data; /* data private to the driver */ + }; + ++/* ++ * Match x86 CPUs for CPU specific drivers. ++ * See documentation of "x86_match_cpu" for details. ++ */ ++ ++struct x86_cpu_id { ++ __u16 vendor; ++ __u16 family; ++ __u16 model; ++ __u16 feature; /* bit index */ ++ kernel_ulong_t driver_data; ++}; ++ ++#define X86_FEATURE_MATCH(x) \ ++ { X86_VENDOR_ANY, X86_FAMILY_ANY, X86_MODEL_ANY, x } ++ ++#define X86_VENDOR_ANY 0xffff ++#define X86_FAMILY_ANY 0 ++#define X86_MODEL_ANY 0 ++#define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ ++ + #endif /* LINUX_MOD_DEVICETABLE_H */ +diff --git a/include/linux/mount.h b/include/linux/mount.h +index fc17c4d..e1e7aba 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch new file mode 100644 index 00000000..0552b53d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/mroute.h ++++ b/include/linux/mroute.h +@@ -34,7 +34,7 @@ + #define SIOCGETSGCNT (SIOCPROTOPRIVATE+1) + #define SIOCGETRPF (SIOCPROTOPRIVATE+2) + +-#define MAXVIFS 32 ++#define MAXVIFS 256 + typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */ + typedef unsigned short vifi_t; + #define ALL_VIFS ((vifi_t)(-1)) +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 05acced..11b750e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch new file mode 100644 index 00000000..d5972d3b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -1,6 +1,7 @@ + #ifndef LINUX_MSI_H + #define LINUX_MSI_H + ++#include + #include + + struct msi_msg { +diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h +index d249254..d5d2ec6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch new file mode 100644 index 00000000..9556fb99 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch @@ -0,0 +1,60 @@ +--- a/include/linux/mtd/cfi.h ++++ b/include/linux/mtd/cfi.h +@@ -354,10 +354,10 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf + onecmd = cmd; + break; + case 2: +- onecmd = cpu_to_cfi16(cmd); ++ onecmd = cpu_to_cfi16(map, cmd); + break; + case 4: +- onecmd = cpu_to_cfi32(cmd); ++ onecmd = cpu_to_cfi32(map, cmd); + break; + } + +@@ -437,10 +437,10 @@ static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, + case 1: + break; + case 2: +- res = cfi16_to_cpu(res); ++ res = cfi16_to_cpu(map, res); + break; + case 4: +- res = cfi32_to_cpu(res); ++ res = cfi32_to_cpu(map, res); + break; + default: BUG(); + } +@@ -480,12 +480,12 @@ static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr) + if (map_bankwidth_is_1(map)) { + return val.x[0]; + } else if (map_bankwidth_is_2(map)) { +- return cfi16_to_cpu(val.x[0]); ++ return cfi16_to_cpu(map, val.x[0]); + } else { + /* No point in a 64-bit byteswap since that would just be + swapping the responses from different chips, and we are + only interested in one chip (a representative sample) */ +- return cfi32_to_cpu(val.x[0]); ++ return cfi32_to_cpu(map, val.x[0]); + } + } + +@@ -496,12 +496,12 @@ static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr) + if (map_bankwidth_is_1(map)) { + return val.x[0] & 0xff; + } else if (map_bankwidth_is_2(map)) { +- return cfi16_to_cpu(val.x[0]); ++ return cfi16_to_cpu(map, val.x[0]); + } else { + /* No point in a 64-bit byteswap since that would just be + swapping the responses from different chips, and we are + only interested in one chip (a representative sample) */ +- return cfi32_to_cpu(val.x[0]); ++ return cfi32_to_cpu(map, val.x[0]); + } + } + +diff --git a/include/linux/mtd/cfi_endian.h b/include/linux/mtd/cfi_endian.h +index 51cc3f5..c785284 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch new file mode 100644 index 00000000..0f2ef19c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch @@ -0,0 +1,77 @@ +--- a/include/linux/mtd/cfi_endian.h ++++ b/include/linux/mtd/cfi_endian.h +@@ -37,35 +37,48 @@ + #define CFI_BIG_ENDIAN + #endif + ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++#define CFI_OF_BYTE_SWAP ++#endif ++ + #endif + + #if defined(CFI_LITTLE_ENDIAN) +-#define cpu_to_cfi8(x) (x) +-#define cfi8_to_cpu(x) (x) +-#define cpu_to_cfi16(x) cpu_to_le16(x) +-#define cpu_to_cfi32(x) cpu_to_le32(x) +-#define cpu_to_cfi64(x) cpu_to_le64(x) +-#define cfi16_to_cpu(x) le16_to_cpu(x) +-#define cfi32_to_cpu(x) le32_to_cpu(x) +-#define cfi64_to_cpu(x) le64_to_cpu(x) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) cpu_to_le16(x) ++#define cpu_to_cfi32(m,x) cpu_to_le32(x) ++#define cpu_to_cfi64(m,x) cpu_to_le64(x) ++#define cfi16_to_cpu(m,x) le16_to_cpu(x) ++#define cfi32_to_cpu(m,x) le32_to_cpu(x) ++#define cfi64_to_cpu(m,x) le64_to_cpu(x) + #elif defined (CFI_BIG_ENDIAN) +-#define cpu_to_cfi8(x) (x) +-#define cfi8_to_cpu(x) (x) +-#define cpu_to_cfi16(x) cpu_to_be16(x) +-#define cpu_to_cfi32(x) cpu_to_be32(x) +-#define cpu_to_cfi64(x) cpu_to_be64(x) +-#define cfi16_to_cpu(x) be16_to_cpu(x) +-#define cfi32_to_cpu(x) be32_to_cpu(x) +-#define cfi64_to_cpu(x) be64_to_cpu(x) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) cpu_to_be16(x) ++#define cpu_to_cfi32(m,x) cpu_to_be32(x) ++#define cpu_to_cfi64(m,x) cpu_to_be64(x) ++#define cfi16_to_cpu(m,x) be16_to_cpu(x) ++#define cfi32_to_cpu(m,x) be32_to_cpu(x) ++#define cfi64_to_cpu(m,x) be64_to_cpu(x) + #elif defined (CFI_HOST_ENDIAN) +-#define cpu_to_cfi8(x) (x) +-#define cfi8_to_cpu(x) (x) +-#define cpu_to_cfi16(x) (x) +-#define cpu_to_cfi32(x) (x) +-#define cpu_to_cfi64(x) (x) +-#define cfi16_to_cpu(x) (x) +-#define cfi32_to_cpu(x) (x) +-#define cfi64_to_cpu(x) (x) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) (x) ++#define cpu_to_cfi32(m,x) (x) ++#define cpu_to_cfi64(m,x) (x) ++#define cfi16_to_cpu(m,x) (x) ++#define cfi32_to_cpu(m,x) (x) ++#define cfi64_to_cpu(m,x) (x) ++#elif defined (CFI_OF_BYTE_SWAP) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) ((m)->byteswap ? swab16(x) : (x)) ++#define cpu_to_cfi32(m,x) ((m)->byteswap ? swab32(x) : (x)) ++#define cpu_to_cfi64(m,x) ((m)->byteswap ? swab64(x) : (x)) ++#define cfi16_to_cpu(m,x) ((m)->byteswap ? swab16(x) : (x)) ++#define cfi32_to_cpu(m,x) ((m)->byteswap ? swab32(x) : (x)) ++#define cfi64_to_cpu(m,x) ((m)->byteswap ? swab64(x) : (x)) + #else + #error No CFI endianness defined + #endif +diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h +index 3887901..b8ca7de 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch new file mode 100644 index 00000000..0ea52eff --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch @@ -0,0 +1,15 @@ +--- a/include/linux/mtd/map.h ++++ b/include/linux/mtd/map.h +@@ -219,6 +219,10 @@ struct map_info { + in bytes, before you are talking to the first chip again. + */ + ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++ int byteswap; /* get byte swap configuration from device tree */ ++#endif ++ + #ifdef CONFIG_MTD_COMPLEX_MAPPINGS + map_word (*read)(struct map_info *, unsigned long); + void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t); +diff --git a/include/linux/namei.h b/include/linux/namei.h +index ffc0213..ef35a31 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch new file mode 100644 index 00000000..dc3e4214 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch @@ -0,0 +1,26 @@ +--- a/include/linux/neighbour.h ++++ b/include/linux/neighbour.h +@@ -20,6 +20,11 @@ enum { + NDA_LLADDR, + NDA_CACHEINFO, + NDA_PROBES, ++ NDA_VLAN, ++ NDA_PORT, ++ NDA_VNI, ++ NDA_IFINDEX, ++ NDA_MASTER, + __NDA_MAX + }; + +@@ -33,6 +38,9 @@ enum { + #define NTF_PROXY 0x08 /* == ATF_PUBL */ + #define NTF_ROUTER 0x80 + ++#define NTF_SELF 0x02 ++#define NTF_MASTER 0x04 ++ + /* + * Neighbor Cache Entry States. + */ +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 4b04097..e2bde14 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch new file mode 100644 index 00000000..dc989518 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/of_mdio.h ++++ b/include/linux/of_mdio.h +@@ -21,5 +21,8 @@ extern struct phy_device *of_phy_connect(struct net_device *dev, + extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, + void (*hndlr)(struct net_device *), + phy_interface_t iface); ++extern struct phy_device *of_phy_attach(struct net_device *dev, ++ struct device_node *phy_np, u32 flags, ++ phy_interface_t iface); + + #endif /* __LINUX_OF_MDIO_H */ +diff --git a/include/linux/pci.h b/include/linux/pci.h +index fe76a74..cea9ae5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch new file mode 100644 index 00000000..a99511b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch @@ -0,0 +1,101 @@ +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -282,6 +282,10 @@ struct pci_dev { + unsigned int mmio_always_on:1; /* disallow turning off io/mem + decoding during bar sizing */ + unsigned int wakeup_prepared:1; ++#ifndef __GENKSYMS__ ++ unsigned int :4; /* spare */ ++ unsigned int pcie_flags_reg:16; /* cached PCI-E Capabilities Register */ ++#endif + unsigned int d3_delay; /* D3->D0 transition time in ms */ + + #ifdef CONFIG_PCIEASPM +@@ -345,6 +349,9 @@ struct pci_dev { + }; + struct pci_ats *ats; /* Address Translation Service */ + #endif ++#if defined(CONFIG_PCI_MSI) && !defined(__GENKSYMS__) ++ const struct attribute_group *msi_irq_group; ++#endif + }; + + static inline struct pci_dev *pci_physfn(struct pci_dev *dev) +@@ -790,6 +797,39 @@ static inline int pci_write_config_dword(struct pci_dev *dev, int where, + return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); + } + ++int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val); ++int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val); ++int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val); ++int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val); ++int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, ++ u16 clear, u16 set); ++int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, ++ u32 clear, u32 set); ++ ++static inline int pcie_capability_set_word(struct pci_dev *dev, int pos, ++ u16 set) ++{ ++ return pcie_capability_clear_and_set_word(dev, pos, 0, set); ++} ++ ++static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos, ++ u32 set) ++{ ++ return pcie_capability_clear_and_set_dword(dev, pos, 0, set); ++} ++ ++static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos, ++ u16 clear) ++{ ++ return pcie_capability_clear_and_set_word(dev, pos, clear, 0); ++} ++ ++static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos, ++ u32 clear) ++{ ++ return pcie_capability_clear_and_set_dword(dev, pos, clear, 0); ++} ++ + int __must_check pci_enable_device(struct pci_dev *dev); + int __must_check pci_enable_device_io(struct pci_dev *dev); + int __must_check pci_enable_device_mem(struct pci_dev *dev); +@@ -955,6 +995,19 @@ int __must_check __pci_register_driver(struct pci_driver *, struct module *, + __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) + + void pci_unregister_driver(struct pci_driver *dev); ++ ++/** ++ * module_pci_driver() - Helper macro for registering a PCI driver ++ * @__pci_driver: pci_driver struct ++ * ++ * Helper macro for PCI drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_pci_driver(__pci_driver) \ ++ module_driver(__pci_driver, pci_register_driver, \ ++ pci_unregister_driver) ++ + void pci_remove_behind_bridge(struct pci_dev *dev); + struct pci_driver *pci_dev_driver(const struct pci_dev *dev); + int pci_add_dynid(struct pci_driver *drv, +@@ -1531,6 +1584,15 @@ static inline bool pci_is_pcie(struct pci_dev *dev) + return !!pci_pcie_cap(dev); + } + ++/** ++ * pci_pcie_type - get the PCIe device/port type ++ * @dev: PCI device ++ */ ++static inline int pci_pcie_type(const struct pci_dev *dev) ++{ ++ return (dev->pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4; ++} ++ + void pci_request_acs(void); + + +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index d93f417..f1fecb0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch new file mode 100644 index 00000000..4021ab5b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch @@ -0,0 +1,28 @@ +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -721,6 +721,7 @@ + #define PCI_DEVICE_ID_SI_7018 0x7018 + + #define PCI_VENDOR_ID_HP 0x103c ++#define PCI_VENDOR_ID_HP_3PAR 0x1590 + #define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 + #define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 + #define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 +@@ -753,6 +754,7 @@ + #define PCI_DEVICE_ID_HP_CISSE 0x323a + #define PCI_DEVICE_ID_HP_CISSF 0x323b + #define PCI_DEVICE_ID_HP_CISSH 0x323c ++#define PCI_DEVICE_ID_HP_CISSI 0x3239 + #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 + + #define PCI_VENDOR_ID_PCTECH 0x1042 +@@ -2484,6 +2486,7 @@ + #define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F + #define PCI_DEVICE_ID_INTEL_I960 0x0960 + #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 ++#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 + #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 + #define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085 + #define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108F +diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h +index 411c412..7451a34 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch new file mode 100644 index 00000000..6487eccd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/pci_regs.h ++++ b/include/linux/pci_regs.h +@@ -441,6 +441,8 @@ + #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ + #define PCI_EXP_LNKCTL 16 /* Link Control */ + #define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ ++#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */ ++#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */ + #define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */ + #define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */ + #define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */ +@@ -520,7 +522,13 @@ + #define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ + #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ + #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ ++#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ ++#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ ++#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ ++#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ ++#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ + #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ ++#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ + #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ + + /* Extended Capabilities (PCI-X 2.0 and Express) */ +diff --git a/include/linux/percpu.h b/include/linux/percpu.h +index 9ca008f..c925813 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch new file mode 100644 index 00000000..76dba9af --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/percpu.h ++++ b/include/linux/percpu.h +@@ -73,9 +73,9 @@ + * intelligent way to determine this would be nice. + */ + #if BITS_PER_LONG > 32 +-#define PERCPU_DYNAMIC_RESERVE (20 << 10) ++#define PERCPU_DYNAMIC_RESERVE (28 << 10) + #else +-#define PERCPU_DYNAMIC_RESERVE (12 << 10) ++#define PERCPU_DYNAMIC_RESERVE (20 << 14) + #endif + + extern void *pcpu_base_addr; +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 8d5b91e..aaed55b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch new file mode 100644 index 00000000..d1fdb2ca --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch @@ -0,0 +1,38 @@ +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -796,7 +796,11 @@ struct perf_event { + struct hw_perf_event hw; + + struct perf_event_context *ctx; ++#ifdef __GENKSYMS__ ++ struct file *filp; ++#else + atomic_long_t refcount; ++#endif + + /* + * These accumulate total time (in nanoseconds) that children +@@ -821,6 +825,9 @@ struct perf_event { + /* mmap bits */ + struct mutex mmap_mutex; + atomic_t mmap_count; ++ /* These two are unused but kept here for ABI compat */ ++ int mmap_locked; ++ struct user_struct *mmap_user; + + struct ring_buffer *rb; + struct list_head rb_entry; +@@ -929,7 +936,11 @@ struct perf_cpu_context { + int exclusive; + struct list_head rotation_list; + int jiffies_interval; ++#ifdef __GENKSYMS__ ++ struct pmu *active_pmu; ++#else + struct pmu *unique_pmu; ++#endif + struct perf_cgroup *cgrp; + }; + +diff --git a/include/linux/phy.h b/include/linux/phy.h +index 79f337c..1efebc0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch new file mode 100644 index 00000000..48ce3607 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch @@ -0,0 +1,112 @@ +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -65,6 +65,7 @@ typedef enum { + PHY_INTERFACE_MODE_RGMII_TXID, + PHY_INTERFACE_MODE_RTBI, + PHY_INTERFACE_MODE_SMII, ++ PHY_INTERFACE_MODE_XGMII, + } phy_interface_t; + + +@@ -96,8 +97,10 @@ struct mii_bus { + const char *name; + char id[MII_BUS_ID_SIZE]; + void *priv; +- int (*read)(struct mii_bus *bus, int phy_id, int regnum); +- int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val); ++ int (*read)(struct mii_bus *bus, int port_addr, int dev_addr, ++ int regnum); ++ int (*write)(struct mii_bus *bus, int port_addr, int dev_addr, ++ int regnum, u16 val); + int (*reset)(struct mii_bus *bus); + + /* +@@ -126,6 +129,9 @@ struct mii_bus { + * interrupt at the index matching its address + */ + int *irq; ++ ++ /* indicate whether it's for Clause 45 PHY */ ++ bool is_c45; + }; + #define to_mii_bus(d) container_of(d, struct mii_bus, dev) + +@@ -134,8 +140,9 @@ int mdiobus_register(struct mii_bus *bus); + void mdiobus_unregister(struct mii_bus *bus); + void mdiobus_free(struct mii_bus *bus); + struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); +-int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); +-int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); ++int mdiobus_read(struct mii_bus *bus, int addr, int devad, u16 regnum); ++int mdiobus_write(struct mii_bus *bus, int addr, int devad, ++ u16 regnum, u16 val); + + + #define PHY_INTERRUPT_DISABLED 0x0 +@@ -307,6 +314,7 @@ struct phy_device { + /* See mii.h for more info */ + u32 supported; + u32 advertising; ++ u32 mmds; + + int autoneg; + +@@ -453,7 +461,22 @@ struct phy_fixup { + */ + static inline int phy_read(struct phy_device *phydev, u32 regnum) + { +- return mdiobus_read(phydev->bus, phydev->addr, regnum); ++ return mdiobus_read(phydev->bus, phydev->addr, 0, regnum); ++} ++ ++/** ++ * phy45_read - Convenience function for reading a given port/dev/reg address ++ * @phydev: The phy_device struct ++ * @devad: The device address to read ++ * @regnum: The register number to read ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++static inline int phy45_read(struct phy_device *phydev, int devad, u16 regnum) ++{ ++ return mdiobus_read(phydev->bus, phydev->addr, devad, regnum); + } + + /** +@@ -468,12 +491,31 @@ static inline int phy_read(struct phy_device *phydev, u32 regnum) + */ + static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val) + { +- return mdiobus_write(phydev->bus, phydev->addr, regnum, val); ++ return mdiobus_write(phydev->bus, phydev->addr, 0, regnum, val); ++} ++ ++/** ++ * phy45_write - Convenience function for writing a given port/dev/reg ++ * @phydev: the phy_device struct ++ * @devad: the device addr ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++static inline int phy45_write(struct phy_device *phydev, u16 regnum, ++ int devad, u16 val) ++{ ++ return mdiobus_write(phydev->bus, phydev->addr, devad, regnum, val); + } + + int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); + struct phy_device* get_phy_device(struct mii_bus *bus, int addr); + int phy_device_register(struct phy_device *phy); ++int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ++ u32 flags, phy_interface_t interface); + int phy_init_hw(struct phy_device *phydev); + struct phy_device * phy_attach(struct net_device *dev, + const char *bus_id, u32 flags, phy_interface_t interface); +diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h +index 38d1032..e7cf666 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch new file mode 100644 index 00000000..f73d0c03 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/pid_namespace.h ++++ b/include/linux/pid_namespace.h +@@ -30,6 +30,8 @@ struct pid_namespace { + #ifdef CONFIG_BSD_PROCESS_ACCT + struct bsd_acct_struct *bacct; + #endif ++ gid_t pid_gid; ++ int hide_pid; + }; + + extern struct pid_namespace init_pid_ns; +diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h +index 7281d5a..443655d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch new file mode 100644 index 00000000..e2354c66 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch @@ -0,0 +1,90 @@ +--- a/include/linux/pkt_sched.h ++++ b/include/linux/pkt_sched.h +@@ -603,4 +603,84 @@ struct tc_qfq_stats { + __u32 lmax; + }; + ++/* CODEL */ ++ ++enum { ++ TCA_CODEL_UNSPEC, ++ TCA_CODEL_TARGET, ++ TCA_CODEL_LIMIT, ++ TCA_CODEL_INTERVAL, ++ TCA_CODEL_ECN, ++ __TCA_CODEL_MAX ++}; ++ ++#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1) ++ ++struct tc_codel_xstats { ++ __u32 maxpacket; /* largest packet we've seen so far */ ++ __u32 count; /* how many drops we've done since the last time we ++ * entered dropping state ++ */ ++ __u32 lastcount; /* count at entry to dropping state */ ++ __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */ ++ __s32 drop_next; /* time to drop next packet */ ++ __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */ ++ __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */ ++ __u32 dropping; /* are we in dropping state ? */ ++}; ++ ++/* FQ_CODEL */ ++ ++enum { ++ TCA_FQ_CODEL_UNSPEC, ++ TCA_FQ_CODEL_TARGET, ++ TCA_FQ_CODEL_LIMIT, ++ TCA_FQ_CODEL_INTERVAL, ++ TCA_FQ_CODEL_ECN, ++ TCA_FQ_CODEL_FLOWS, ++ TCA_FQ_CODEL_QUANTUM, ++ __TCA_FQ_CODEL_MAX ++}; ++ ++#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1) ++ ++enum { ++ TCA_FQ_CODEL_XSTATS_QDISC, ++ TCA_FQ_CODEL_XSTATS_CLASS, ++}; ++ ++struct tc_fq_codel_qd_stats { ++ __u32 maxpacket; /* largest packet we've seen so far */ ++ __u32 drop_overlimit; /* number of time max qdisc ++ * packet limit was hit ++ */ ++ __u32 ecn_mark; /* number of packets we ECN marked ++ * instead of being dropped ++ */ ++ __u32 new_flow_count; /* number of time packets ++ * created a 'new flow' ++ */ ++ __u32 new_flows_len; /* count of flows in new list */ ++ __u32 old_flows_len; /* count of flows in old list */ ++}; ++ ++struct tc_fq_codel_cl_stats { ++ __s32 deficit; ++ __u32 ldelay; /* in-queue delay seen by most recently ++ * dequeued packet ++ */ ++ __u32 count; ++ __u32 lastcount; ++ __u32 dropping; ++ __s32 drop_next; ++}; ++ ++struct tc_fq_codel_xstats { ++ __u32 type; ++ union { ++ struct tc_fq_codel_qd_stats qdisc_stats; ++ struct tc_fq_codel_cl_stats class_stats; ++ }; ++}; ++ + #endif +diff --git a/include/linux/platform_data/max6697.h b/include/linux/platform_data/max6697.h +new file mode 100644 +index 0000000..ed9d3b3 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch new file mode 100644 index 00000000..b9856ddb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch @@ -0,0 +1,41 @@ +--- /dev/null ++++ b/include/linux/platform_data/max6697.h +@@ -0,0 +1,36 @@ ++/* ++ * max6697.h ++ * Copyright (c) 2012 Guenter Roeck ++ * ++ * 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 MAX6697_H ++#define MAX6697_H ++ ++#include ++ ++/* ++ * For all bit masks: ++ * bit 0: local temperature ++ * bit 1..7: remote temperatures ++ */ ++struct max6697_platform_data { ++ bool smbus_timeout_disable; /* set to disable SMBus timeouts */ ++ bool extended_range_enable; /* set to enable extended temp range */ ++ bool beta_compensation; /* set to enable beta compensation */ ++ u8 alert_mask; /* set bit to 1 to disable alert */ ++ u8 over_temperature_mask; /* set bit to 1 to disable */ ++ u8 resistance_cancellation; /* set bit to 0 to disable ++ * bit mask for MAX6581, ++ * boolean for other chips ++ */ ++ u8 ideality_mask; /* set bit to 0 to disable */ ++ u8 ideality_value; /* transistor ideality as per ++ * MAX6581 datasheet ++ */ ++}; ++ ++#endif /* MAX6697_H */ +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index 2a23f7d..4cf54aa 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch new file mode 100644 index 00000000..e082122d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch @@ -0,0 +1,34 @@ +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -14,6 +14,9 @@ + #include + #include + ++#define PLATFORM_DEVID_NONE (-1) ++#define PLATFORM_DEVID_AUTO (-2) ++ + struct mfd_cell; + + struct platform_device { +@@ -196,16 +199,8 @@ static inline void platform_set_drvdata(struct platform_device *pdev, void *data + * calling it replaces module_init() and module_exit() + */ + #define module_platform_driver(__platform_driver) \ +-static int __init __platform_driver##_init(void) \ +-{ \ +- return platform_driver_register(&(__platform_driver)); \ +-} \ +-module_init(__platform_driver##_init); \ +-static void __exit __platform_driver##_exit(void) \ +-{ \ +- platform_driver_unregister(&(__platform_driver)); \ +-} \ +-module_exit(__platform_driver##_exit); ++ module_driver(__platform_driver, platform_driver_register, \ ++ platform_driver_unregister) + + extern struct platform_device *platform_create_bundle(struct platform_driver *driver, + int (*probe)(struct platform_device *), +diff --git a/include/linux/port.h b/include/linux/port.h +new file mode 100644 +index 0000000..6389048 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch new file mode 100644 index 00000000..90cdcf8e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/include/linux/port.h +@@ -0,0 +1,79 @@ ++/* ++ * port.h - defines for generic netlink port handler ++ * Copyright (C) 2013 Cumulus Networks ++ */ ++ ++#ifndef _LINUX_PORT_H ++#define _LINUX_PORT_H ++ ++#ifdef __KERNEL__ ++#include ++#endif ++#include ++ ++enum { ++ PORT_ATTR_UNSPEC, ++ PORT_ATTR_STATUS, ++ PORT_ATTR_IFINDEX, ++ PORT_ATTR_FLAGS, ++ PORT_ATTR_CARRIER, ++ PORT_ATTR_PHYS_ID_STATE, ++ PORT_ATTR_SETTINGS, ++ PORT_ATTR_PAUSE, ++ PORT_ATTR_MODINFO, ++ PORT_ATTR_EEPROM, ++ PORT_ATTR_EEPROM_DATA, ++ PORT_ATTR_STATS, ++ PORT_ATTR_STAT, ++ PORT_ATTR_STRINGS, ++ PORT_ATTR_STRING, ++ PORT_ATTR_SSET, ++ PORT_ATTR_SSET_COUNT, ++ __PORT_ATTR_MAX, ++}; ++#define PORT_ATTR_MAX (__PORT_ATTR_MAX - 1) ++ ++enum { ++ PORT_CMD_UNSPEC, ++ PORT_CMD_REPLY, ++ PORT_CMD_GET_SETTINGS, ++ PORT_CMD_SET_SETTINGS, ++ PORT_CMD_GET_PAUSE, ++ PORT_CMD_SET_PAUSE, ++ PORT_CMD_GET_MODULE_INFO, ++ PORT_CMD_GET_MODULE_EEPROM, ++ PORT_CMD_SET_STATS, ++ PORT_CMD_GET_STRINGS, ++ PORT_CMD_GET_SSET_COUNT, ++ PORT_CMD_SET_CARRIER, ++ PORT_CMD_SET_PHYS_ID_STATE, ++ PORT_CMD_GET_CACHED_SETTINGS, ++ __PORT_CMD_MAX, ++}; ++ ++#ifdef __KERNEL__ ++ ++#define PORT_ATTR_FLAG_STAT_RESTART (1 << 0) ++ ++void port_init_ethtool_stats(struct net_device *dev); ++void port_uninit_ethtool_stats(struct net_device *dev); ++int port_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); ++int port_set_settings(struct net_device *dev, struct ethtool_cmd *cmd); ++void port_get_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause); ++int port_set_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam * pause); ++void port_get_ethtool_stats(struct net_device *dev, ++ struct ethtool_stats *stats, u64 *data); ++void port_get_ethtool_stats_clear(struct net_device *dev, ++ struct ethtool_stats *stats, u64 *data); ++void port_get_strings(struct net_device *dev, u32 stringset, u8 *data); ++int port_get_sset_count(struct net_device *dev, int sset); ++int port_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state); ++int port_get_module_info(struct net_device *dev, struct ethtool_modinfo *info); ++int port_get_module_eeprom(struct net_device *dev, ++ struct ethtool_eeprom *eeprom, u8 *data); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _LINUX_PORT_H */ +diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h +index ce2ab3d..d189738 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch new file mode 100644 index 00000000..5eadec05 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch @@ -0,0 +1,20 @@ +--- a/include/linux/pps_kernel.h ++++ b/include/linux/pps_kernel.h +@@ -69,11 +69,14 @@ struct pps_device { + wait_queue_head_t queue; /* PPS event queue */ + + unsigned int id; /* PPS source unique ID */ +- void const *lookup_cookie; /* pps_lookup_dev only */ + struct cdev cdev; + struct device *dev; + struct fasync_struct *async_queue; /* fasync method */ + spinlock_t lock; ++ ++#ifndef __GENKSYMS__ ++ void const *lookup_cookie; /* pps_lookup_dev only */ ++#endif + }; + + /* +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index e49240b..ecbd207 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch new file mode 100644 index 00000000..d4caad94 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -112,7 +112,9 @@ + + #include /* For unlikely. */ + #include /* For struct task_struct. */ ++#ifndef __GENKSYMS__ + #include /* For task_active_pid_ns. */ ++#endif + + + extern long arch_ptrace(struct task_struct *child, long request, +diff --git a/include/linux/random.h b/include/linux/random.h +index f5e1311..02c1d28 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch new file mode 100644 index 00000000..85486bf5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch @@ -0,0 +1,47 @@ +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -34,6 +34,30 @@ + /* Clear the entropy pool and associated counters. (Superuser only.) */ + #define RNDCLEARPOOL _IO( 'R', 0x06 ) + ++#ifdef CONFIG_FIPS_RNG ++ ++/* Size of seed value - equal to AES blocksize */ ++#define AES_BLOCK_SIZE_BYTES 16 ++#define SEED_SIZE_BYTES AES_BLOCK_SIZE_BYTES ++/* Size of AES key */ ++#define KEY_SIZE_BYTES 16 ++ ++/* ioctl() structure used by FIPS 140-2 Tests */ ++struct rand_fips_test { ++ unsigned char key[KEY_SIZE_BYTES]; /* Input */ ++ unsigned char datetime[SEED_SIZE_BYTES]; /* Input */ ++ unsigned char seed[SEED_SIZE_BYTES]; /* Input */ ++ unsigned char result[SEED_SIZE_BYTES]; /* Output */ ++}; ++ ++/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */ ++#define RNDFIPSVST _IOWR('R', 0x10, struct rand_fips_test) ++ ++/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */ ++#define RNDFIPSMCT _IOWR('R', 0x11, struct rand_fips_test) ++ ++#endif /* #ifdef CONFIG_FIPS_RNG */ ++ + struct rand_pool_info { + int entropy_count; + int buf_size; +@@ -55,6 +79,11 @@ extern void add_input_randomness(unsigned int type, unsigned int code, + unsigned int value); + extern void add_interrupt_randomness(int irq, int irq_flags); + ++extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count); ++extern int random_input_wait(void); ++#define HAS_RANDOM_INPUT_WAIT 1 ++ ++ + extern void get_random_bytes(void *buf, int nbytes); + extern void get_random_bytes_arch(void *buf, int nbytes); + void generate_random_uuid(unsigned char uuid_out[16]); +diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h +index f7756d1..34234fd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch new file mode 100644 index 00000000..866db67d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch @@ -0,0 +1,19 @@ +--- a/include/linux/regulator/consumer.h ++++ b/include/linux/regulator/consumer.h +@@ -258,6 +258,13 @@ static inline int regulator_get_voltage(struct regulator *regulator) + return 0; + } + ++static inline int regulator_is_supported_voltage(struct regulator *regulator, ++ int min_uV, int max_uV) ++{ ++ return 0; ++} ++ ++ + static inline int regulator_set_current_limit(struct regulator *regulator, + int min_uA, int max_uA) + { +diff --git a/include/linux/retimer_class.h b/include/linux/retimer_class.h +new file mode 100644 +index 0000000..6f37318 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch new file mode 100644 index 00000000..679e553d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch @@ -0,0 +1,40 @@ +--- /dev/null ++++ b/include/linux/retimer_class.h +@@ -0,0 +1,35 @@ ++/* ++ * retimer_class.c ++ * ++ * This file exports interface functions for the sysfs class "retimer", ++ * for use by RETIMER drivers. ++ * ++ * Copyright (C) 2014 Cumulus Networks, Inc. ++ * 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; 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. ++ * ++ */ ++ ++#ifndef RETIMER_CLASS_H__ ++#define RETIMER_CLASS_H__ ++ ++#include ++#include ++ ++struct device *retimer_device_register(struct device *dev); ++ ++void retimer_device_unregister(struct device *dev); ++ ++#endif /* RETIMER_CLASS_H__ */ +diff --git a/include/linux/rmap.h b/include/linux/rmap.h +index b0df05a..590ea0f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch new file mode 100644 index 00000000..1f7d3c31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch @@ -0,0 +1,40 @@ +--- a/include/linux/rmap.h ++++ b/include/linux/rmap.h +@@ -37,16 +37,6 @@ struct anon_vma { + atomic_t refcount; + + /* +- * Count of child anon_vmas and VMAs which points to this anon_vma. +- * +- * This counter is used for making decision about reusing anon_vma +- * instead of forking new one. See comments in function anon_vma_clone. +- */ +- unsigned degree; +- +- struct anon_vma *parent; /* Parent of this anon_vma */ +- +- /* + * NOTE: the LSB of the head.next is set by + * mm_take_all_locks() _after_ taking the above lock. So the + * head must only be read/written after taking the above lock +@@ -55,6 +45,18 @@ struct anon_vma { + * mm_take_all_locks() (mm_all_locks_mutex). + */ + struct list_head head; /* Chain of private "related" vmas */ ++ ++#ifndef __GENKSYMS__ ++ /* ++ * Count of child anon_vmas and VMAs which points to this anon_vma. ++ * ++ * This counter is used for making decision about reusing anon_vma ++ * instead of forking new one. See comments in function anon_vma_clone. ++ */ ++ unsigned degree; ++ ++ struct anon_vma *parent; /* Parent of this anon_vma */ ++#endif + }; + + /* +diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h +index 577592e..2aa8240 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch new file mode 100644 index 00000000..93b83705 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch @@ -0,0 +1,31 @@ +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -446,8 +446,8 @@ struct sk_buff { + + /* 0/13 bit hole */ + +-#ifdef CONFIG_NET_DMA +- dma_cookie_t dma_cookie; ++#ifdef CONFIG_NET_DMA_DUMMY ++ dma_cookie_t dma_cookie; /* now unused */ + #endif + #ifdef CONFIG_NETWORK_SECMARK + __u32 secmark; +@@ -455,9 +455,15 @@ struct sk_buff { + union { + __u32 mark; + __u32 dropcount; ++ /* For use by TCP only */ ++#ifdef __GENKSYMS__ ++ __u32 avail_size; ++#else + __u32 reserved_tailroom; ++#endif + }; + ++ __be16 vlan_proto; + __u16 vlan_tci; + + sk_buff_data_t transport_header; +diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h +index d00e0ba..fbd1117 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch new file mode 100644 index 00000000..7719ed6d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/slab_def.h ++++ b/include/linux/slab_def.h +@@ -15,8 +15,6 @@ + #include /* kmalloc_sizes.h needs L1_CACHE_BYTES */ + #include + +-#include +- + /* + * struct kmem_cache + * +diff --git a/include/linux/snmp.h b/include/linux/snmp.h +index 64f5ca7..b49eae1 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch new file mode 100644 index 00000000..9b2e753f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch @@ -0,0 +1,23 @@ +--- a/include/linux/snmp.h ++++ b/include/linux/snmp.h +@@ -210,6 +210,7 @@ enum + LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ + LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ + LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ ++ LINUX_MIB_TCPABORTONSYN, /* unused, binary compat */ + LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ + LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ + LINUX_MIB_TCPABORTONTIMEOUT, /* TCPAbortOnTimeout */ +@@ -232,8 +233,10 @@ enum + LINUX_MIB_TCPTIMEWAITOVERFLOW, /* TCPTimeWaitOverflow */ + LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ + LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ ++#ifndef __GENKSYMS__ + LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ + LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ ++#endif + __LINUX_MIB_MAX + }; + +diff --git a/include/linux/splice.h b/include/linux/splice.h +index 09a545a..1ac5727 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch new file mode 100644 index 00000000..0de224d6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/swiotlb.h ++++ b/include/linux/swiotlb.h +@@ -24,7 +24,7 @@ extern int swiotlb_force; + + extern void swiotlb_init(int verbose); + extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); +-extern unsigned long swioltb_nr_tbl(void); ++extern unsigned long swiotlb_nr_tbl(void); + + /* + * Enumeration for sync targets +diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h +index 703cfa3..4154bd4 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch new file mode 100644 index 00000000..5b1dda47 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/sysctl.h ++++ b/include/linux/sysctl.h +@@ -275,6 +275,7 @@ enum + NET_CORE_AEVENT_ETIME=20, + NET_CORE_AEVENT_RSEQTH=21, + NET_CORE_WARNINGS=22, ++ NET_CORE_KILL_ROUTES_ON_LINKDOWN=23, + }; + + /* /proc/sys/net/ethernet */ +diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h +index 2b9cd8d..ecd4cc5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch new file mode 100644 index 00000000..e1f77eec --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch @@ -0,0 +1,19 @@ +--- a/include/linux/sysfs.h ++++ b/include/linux/sysfs.h +@@ -78,6 +78,14 @@ struct attribute_group { + .show = _name##_show, \ + } + ++#define __ATTR_WO(_name) { \ ++ .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ ++ .store = _name##_store, \ ++} ++ ++#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ ++ _name##_show, _name##_store) ++ + #define __ATTR_NULL { .attr = { .name = NULL } } + + #define ATTRIBUTE_GROUPS(name) \ +diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h +index 7faf933..cbbbbe3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch new file mode 100644 index 00000000..c57ee1d0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/sysrq.h ++++ b/include/linux/sysrq.h +@@ -18,7 +18,7 @@ + #include + + /* Enable/disable SYSRQ support by default (0==no, 1==yes). */ +-#define SYSRQ_DEFAULT_ENABLE 1 ++#define SYSRQ_DEFAULT_ENABLE CONFIG_MAGIC_SYSRQ_DEFAULT_MASK + + /* Possible values of bitmask for enabling sysrq functions */ + /* 0x0001 is reserved for enable everything */ +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index 7f59ee9..0d62739 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch new file mode 100644 index 00000000..fff47999 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch @@ -0,0 +1,15 @@ +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -325,8 +325,8 @@ struct tcp_sock { + struct iovec *iov; + int memory; + int len; +-#ifdef CONFIG_NET_DMA +- /* members for async copy */ ++#ifdef CONFIG_NET_DMA_DUMMY ++ /* members for async copy, now unused */ + struct dma_chan *dma_chan; + int wakeup; + struct dma_pinned_list *pinned_list; +diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h +index 8da8c4e..3dc2be5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch new file mode 100644 index 00000000..e65a1fe8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch @@ -0,0 +1,17 @@ +--- a/include/linux/u64_stats_sync.h ++++ b/include/linux/u64_stats_sync.h +@@ -67,6 +67,12 @@ struct u64_stats_sync { + #endif + }; + ++#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) ++# define u64_stats_init(syncp) seqcount_init(syncp.seq) ++#else ++# define u64_stats_init(syncp) do { } while (0) ++#endif ++ + static inline void u64_stats_update_begin(struct u64_stats_sync *syncp) + { + #if BITS_PER_LONG==32 && defined(CONFIG_SMP) +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 93629fc..3959c62 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch new file mode 100644 index 00000000..3e983308 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch @@ -0,0 +1,51 @@ +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -796,6 +796,27 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + ++/** ++ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces ++ * @vend: the 16 bit USB Vendor ID ++ * @cl: bInterfaceClass value ++ * @sc: bInterfaceSubClass value ++ * @pr: bInterfaceProtocol value ++ * ++ * This macro is used to create a struct usb_device_id that matches a ++ * specific vendor with a specific class of interfaces. ++ * ++ * This is especially useful when explicitly matching devices that have ++ * vendor specific bDeviceClass values, but standards-compliant interfaces. ++ */ ++#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ ++ | USB_DEVICE_ID_MATCH_VENDOR, \ ++ .idVendor = (vend), \ ++ .bInterfaceClass = (cl), \ ++ .bInterfaceSubClass = (sc), \ ++ .bInterfaceProtocol = (pr) ++ + /* ----------------------------------------------------------------------- */ + + /* Stuff for dynamic usb ids */ +@@ -974,6 +995,18 @@ extern int usb_register_driver(struct usb_driver *, struct module *, + + extern void usb_deregister(struct usb_driver *); + ++/** ++ * module_usb_driver() - Helper macro for registering a USB driver ++ * @__usb_driver: usb_driver struct ++ * ++ * Helper macro for USB drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_usb_driver(__usb_driver) \ ++ module_driver(__usb_driver, usb_register, \ ++ usb_deregister) ++ + extern int usb_register_device_driver(struct usb_device_driver *, + struct module *); + extern void usb_deregister_device_driver(struct usb_device_driver *); +diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h +index 7cc95ee..2ca3076 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch new file mode 100644 index 00000000..a184e029 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch @@ -0,0 +1,60 @@ +--- a/include/linux/usb/ehci_def.h ++++ b/include/linux/usb/ehci_def.h +@@ -111,7 +111,13 @@ struct ehci_regs { + /* ASYNCLISTADDR: offset 0x18 */ + u32 async_next; /* address of next async queue head */ + +- u32 reserved[9]; ++ u32 reserved1[2]; ++ ++ /* TXFILLTUNING: offset 0x24 */ ++ u32 txfill_tuning; /* TX FIFO Tuning register */ ++#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */ ++ ++ u32 reserved2[6]; + + /* CONFIGFLAG: offset 0x40 */ + u32 configured_flag; +@@ -155,26 +161,35 @@ struct ehci_regs { + #define PORT_CSC (1<<1) /* connect status change */ + #define PORT_CONNECT (1<<0) /* device connected */ + #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) +-}; + +-#define USBMODE 0x68 /* USB Device mode */ ++ u32 reserved3[9]; ++ ++ /* USBMODE: offset 0x68 */ ++ u32 usbmode; /* USB Device mode */ + #define USBMODE_SDIS (1<<3) /* Stream disable */ + #define USBMODE_BE (1<<2) /* BE/LE endianness select */ + #define USBMODE_CM_HC (3<<0) /* host controller mode */ + #define USBMODE_CM_IDLE (0<<0) /* idle state */ + ++ u32 reserved4[7]; ++ + /* Moorestown has some non-standard registers, partially due to the fact that + * its EHCI controller has both TT and LPM support. HOSTPCx are extensions to + * PORTSCx + */ ++ /* HOSTPC: offset 0x84 */ ++ u32 hostpc[0]; /* HOSTPC extension */ + #define HOSTPC0 0x84 /* HOSTPC extension */ + #define HOSTPC_PHCD (1<<22) /* Phy clock disable */ + #define HOSTPC_PSPD (3<<25) /* Port speed detection */ +-#define USBMODE_EX 0xc8 /* USB Device mode extension */ ++ ++ u32 reserved5[17]; ++ ++ /* USBMODE_EX: offset 0xc8 */ ++ u32 usbmode_ex; /* USB Device mode extension */ + #define USBMODE_EX_VBPS (1<<5) /* VBus Power Select On */ + #define USBMODE_EX_HC (3<<0) /* host controller mode */ +-#define TXFILLTUNING 0x24 /* TX FIFO Tuning register */ +-#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */ ++}; + + /* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index 4fc3e5d..c4ad44f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch new file mode 100644 index 00000000..044284b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -128,8 +128,11 @@ struct usb_hcd { + unsigned wireless:1; /* Wireless USB HCD */ + unsigned authorized_default:1; + unsigned has_tt:1; /* Integrated TT in root hub */ ++#ifndef __GENKSYMS__ + unsigned cant_recv_wakeups:1; + /* wakeup requests from downstream aren't received */ ++ /* 24 bits spare */ ++#endif + + int irq; /* irq allocated */ + void __iomem *regs; /* device memory/io */ +diff --git a/include/linux/virtio.h b/include/linux/virtio.h +index e4807af..f12924f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch new file mode 100644 index 00000000..02b29ea9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/vmalloc.h ++++ b/include/linux/vmalloc.h +@@ -131,6 +131,7 @@ extern long vwrite(char *buf, char *addr, unsigned long count); + */ + extern rwlock_t vmlist_lock; + extern struct vm_struct *vmlist; ++extern __init void vm_area_add_early(struct vm_struct *vm); + extern __init void vm_area_register_early(struct vm_struct *vm, size_t align); + + #ifdef CONFIG_SMP +diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h +index 111843f..6e4e300 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch new file mode 100644 index 00000000..caf4c26d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch @@ -0,0 +1,18 @@ +--- a/include/linux/watchdog.h ++++ b/include/linux/watchdog.h +@@ -122,6 +122,13 @@ struct watchdog_device { + #define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */ + }; + ++/* Use the following function to set the nowayout feature */ ++static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout) ++{ ++ if (nowayout) ++ set_bit(WDOG_NO_WAY_OUT, &wdd->status); ++} ++ + /* Use the following functions to manipulate watchdog driver specific data */ + static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) + { +diff --git a/include/net/addrconf.h b/include/net/addrconf.h +index 44b1110..401ed48 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch new file mode 100644 index 00000000..5297b973 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch @@ -0,0 +1,14 @@ +--- a/include/trace/syscall.h ++++ b/include/trace/syscall.h +@@ -4,7 +4,9 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include ++#endif + + #include + +diff --git a/init/Kconfig b/init/Kconfig +index b8dc1de..d37670d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch new file mode 100644 index 00000000..0c5d86b3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch @@ -0,0 +1,19 @@ +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -660,6 +660,14 @@ config CGROUP_MEM_RES_CTLR + This config option also selects MM_OWNER config option, which + could in turn add some fork/exit overhead. + ++config CGROUP_MEM_RES_CTLR_DISABLED ++ bool "Memory Resource Controller disabled by default" ++ depends on CGROUP_MEM_RES_CTLR ++ default n ++ help ++ Disable the memory group resource controller unless explicitly ++ enabled using the kernel parameter "cgroup_enable=memory". ++ + config CGROUP_MEM_RES_CTLR_SWAP + bool "Memory Resource Controller Swap Extension" + depends on CGROUP_MEM_RES_CTLR && SWAP +diff --git a/kernel/audit.c b/kernel/audit.c +index e14bc74..51420a8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch b/packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch new file mode 100644 index 00000000..f0e75bd7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch @@ -0,0 +1,12 @@ +diff -uNpr a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +--- a/fs/overlayfs/inode.c 2015-04-07 13:55:17.487864270 -0700 ++++ b/fs/overlayfs/inode.c 2015-04-07 13:56:24.948259512 -0700 +@@ -68,7 +68,7 @@ int ovl_permission(struct inode *inode, + spin_unlock(&inode->i_lock); + return -ENOENT; + } +- alias = list_entry(inode->i_dentry.next, struct dentry, d_alias); ++ alias = list_entry(inode->i_dentry.next, struct dentry, d_u.d_alias); + dget(alias); + spin_unlock(&inode->i_lock); + oe = alias->d_fsdata; diff --git a/packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch b/packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch new file mode 100644 index 00000000..f336a65f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch @@ -0,0 +1,3178 @@ +--- /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/MAINTAINERS b/MAINTAINERS +index 768ceee..6701e5a 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -4910,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 +diff --git a/fs/Kconfig b/fs/Kconfig +index ded2ffb..7f618e9 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -63,6 +63,7 @@ source "fs/quota/Kconfig" + + source "fs/autofs4/Kconfig" + source "fs/fuse/Kconfig" ++source "fs/overlayfs/Kconfig" + + config CUSE + tristate "Character device in Userspace support" +diff --git a/fs/Makefile b/fs/Makefile +index 680ad8a..1727784 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -104,6 +104,7 @@ obj-$(CONFIG_QNX4FS_FS) += qnx4/ + obj-$(CONFIG_AUTOFS4_FS) += autofs4/ + obj-$(CONFIG_ADFS_FS) += adfs/ + obj-$(CONFIG_FUSE_FS) += fuse/ ++obj-$(CONFIG_OVERLAYFS_FS) += overlayfs/ + obj-$(CONFIG_UDF_FS) += udf/ + obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ + obj-$(CONFIG_OMFS_FS) += omfs/ +diff --git a/fs/namespace.c b/fs/namespace.c +index 99d2154..0719c07 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1493,6 +1493,23 @@ void drop_collected_mounts(struct vfsmount *mnt) + release_mounts(&umount_list); + } + ++struct vfsmount *clone_private_mount(struct path *path) ++{ ++ struct vfsmount *mnt; ++ ++ if (IS_MNT_UNBINDABLE(path->mnt)) ++ return ERR_PTR(-EINVAL); ++ ++ down_read(&namespace_sem); ++ mnt = clone_mnt(path->mnt, path->dentry, CL_PRIVATE); ++ up_read(&namespace_sem); ++ if (!mnt) ++ return ERR_PTR(-ENOMEM); ++ ++ return mnt; ++} ++EXPORT_SYMBOL_GPL(clone_private_mount); ++ + int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, + struct vfsmount *root) + { +diff --git a/fs/open.c b/fs/open.c +index a57313e..1d4de26 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -645,8 +645,7 @@ static inline int __get_file_write_access(struct inode *inode, + return error; + } + +-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, +- struct file *f, ++static struct file *__dentry_open(struct path *path, struct file *f, + int (*open)(struct inode *, struct file *), + const struct cred *cred) + { +@@ -654,15 +653,16 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, + struct inode *inode; + int error; + ++ path_get(path); + f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | + FMODE_PREAD | FMODE_PWRITE; + + if (unlikely(f->f_flags & O_PATH)) + f->f_mode = FMODE_PATH; + +- inode = dentry->d_inode; ++ inode = path->dentry->d_inode; + if (f->f_mode & FMODE_WRITE) { +- error = __get_file_write_access(inode, mnt); ++ error = __get_file_write_access(inode, path->mnt); + if (error) + goto cleanup_file; + if (!special_file(inode->i_mode)) +@@ -670,8 +670,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, + } + + f->f_mapping = inode->i_mapping; +- f->f_path.dentry = dentry; +- f->f_path.mnt = mnt; ++ f->f_path = *path; + f->f_pos = 0; + file_sb_list_add(f, inode->i_sb); + +@@ -728,7 +727,7 @@ cleanup_all: + * here, so just reset the state. + */ + file_reset_write(f); +- mnt_drop_write(mnt); ++ mnt_drop_write(path->mnt); + } + } + file_sb_list_del(f); +@@ -736,8 +735,7 @@ cleanup_all: + f->f_path.mnt = NULL; + cleanup_file: + put_filp(f); +- dput(dentry); +- mntput(mnt); ++ path_put(path); + return ERR_PTR(error); + } + +@@ -763,14 +761,14 @@ cleanup_file: + struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, + int (*open)(struct inode *, struct file *)) + { ++ struct path path = { .dentry = dentry, .mnt = nd->path.mnt }; + const struct cred *cred = current_cred(); + + if (IS_ERR(nd->intent.open.file)) + goto out; + if (IS_ERR(dentry)) + goto out_err; +- nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), +- nd->intent.open.file, ++ nd->intent.open.file = __dentry_open(&path, nd->intent.open.file, + open, cred); + out: + return nd->intent.open.file; +@@ -799,10 +797,17 @@ struct file *nameidata_to_filp(struct nameidata *nd) + + /* Has the filesystem initialised the file for us? */ + if (filp->f_path.dentry == NULL) { +- path_get(&nd->path); +- filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, +- NULL, cred); ++ struct inode *inode = nd->path.dentry->d_inode; ++ ++ if (inode->i_op->open) { ++ int flags = filp->f_flags; ++ put_filp(filp); ++ filp = inode->i_op->open(nd->path.dentry, flags, cred); ++ } else { ++ filp = __dentry_open(&nd->path, filp, NULL, cred); ++ } + } ++ + return filp; + } + +@@ -813,26 +818,45 @@ struct file *nameidata_to_filp(struct nameidata *nd) + struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, + const struct cred *cred) + { +- int error; +- struct file *f; +- +- validate_creds(cred); ++ struct path path = { .dentry = dentry, .mnt = mnt }; ++ struct file *ret; + + /* We must always pass in a valid mount pointer. */ + BUG_ON(!mnt); + +- error = -ENFILE; ++ ret = vfs_open(&path, flags, cred); ++ path_put(&path); ++ ++ return ret; ++} ++EXPORT_SYMBOL(dentry_open); ++ ++/** ++ * vfs_open - open the file at the given path ++ * @path: path to open ++ * @flags: open flags ++ * @cred: credentials to use ++ * ++ * Open the file. If successful, the returned file will have acquired ++ * an additional reference for path. ++ */ ++struct file *vfs_open(struct path *path, int flags, const struct cred *cred) ++{ ++ struct file *f; ++ struct inode *inode = path->dentry->d_inode; ++ ++ validate_creds(cred); ++ ++ if (inode->i_op->open) ++ return inode->i_op->open(path->dentry, flags, cred); + f = get_empty_filp(); +- if (f == NULL) { +- dput(dentry); +- mntput(mnt); +- return ERR_PTR(error); +- } ++ if (f == NULL) ++ return ERR_PTR(-ENFILE); + + f->f_flags = flags; +- return __dentry_open(dentry, mnt, f, NULL, cred); ++ return __dentry_open(path, f, NULL, cred); + } +-EXPORT_SYMBOL(dentry_open); ++EXPORT_SYMBOL(vfs_open); + + static void __put_unused_fd(struct files_struct *files, unsigned int fd) + { +diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig +new file mode 100644 +index 0000000..c4517da +--- /dev/null ++++ b/fs/overlayfs/Kconfig +@@ -0,0 +1,4 @@ ++config OVERLAYFS_FS ++ tristate "Overlay filesystem support" ++ help ++ Add support for overlay filesystem. +diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile +new file mode 100644 +index 0000000..8f91889 +--- /dev/null ++++ b/fs/overlayfs/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for the overlay filesystem. ++# ++ ++obj-$(CONFIG_OVERLAYFS_FS) += overlayfs.o ++ ++overlayfs-objs := super.o inode.o dir.o readdir.o copy_up.o +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +new file mode 100644 +index 0000000..308a80a +--- /dev/null ++++ b/fs/overlayfs/copy_up.c +@@ -0,0 +1,383 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell 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 "overlayfs.h" ++ ++#define OVL_COPY_UP_CHUNK_SIZE (1 << 20) ++ ++static int ovl_copy_up_xattr(struct dentry *old, struct dentry *new) ++{ ++ ssize_t list_size, size; ++ char *buf, *name, *value; ++ int error; ++ ++ if (!old->d_inode->i_op->getxattr || ++ !new->d_inode->i_op->getxattr) ++ return 0; ++ ++ list_size = vfs_listxattr(old, NULL, 0); ++ if (list_size <= 0) { ++ if (list_size == -EOPNOTSUPP) ++ return 0; ++ return list_size; ++ } ++ ++ buf = kzalloc(list_size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ error = -ENOMEM; ++ value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL); ++ if (!value) ++ goto out; ++ ++ list_size = vfs_listxattr(old, buf, list_size); ++ if (list_size <= 0) { ++ error = list_size; ++ goto out_free_value; ++ } ++ ++ for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { ++ size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX); ++ if (size <= 0) { ++ error = size; ++ goto out_free_value; ++ } ++ error = vfs_setxattr(new, name, value, size, 0); ++ if (error) ++ goto out_free_value; ++ } ++ ++out_free_value: ++ kfree(value); ++out: ++ kfree(buf); ++ return error; ++} ++ ++static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) ++{ ++ struct file *old_file; ++ struct file *new_file; ++ int error = 0; ++ ++ if (len == 0) ++ return 0; ++ ++ old_file = vfs_open(old, O_RDONLY, current_cred()); ++ if (IS_ERR(old_file)) ++ return PTR_ERR(old_file); ++ ++ new_file = vfs_open(new, O_WRONLY, current_cred()); ++ if (IS_ERR(new_file)) { ++ error = PTR_ERR(new_file); ++ goto out_fput; ++ } ++ ++ /* FIXME: copy up sparse files efficiently */ ++ while (len) { ++ loff_t offset = new_file->f_pos; ++ size_t this_len = OVL_COPY_UP_CHUNK_SIZE; ++ long bytes; ++ ++ if (len < this_len) ++ this_len = len; ++ ++ if (signal_pending_state(TASK_KILLABLE, current)) { ++ error = -EINTR; ++ break; ++ } ++ ++ bytes = do_splice_direct(old_file, &offset, new_file, this_len, ++ SPLICE_F_MOVE); ++ if (bytes <= 0) { ++ error = bytes; ++ break; ++ } ++ ++ len -= bytes; ++ } ++ ++ fput(new_file); ++out_fput: ++ fput(old_file); ++ return error; ++} ++ ++static char *ovl_read_symlink(struct dentry *realdentry) ++{ ++ int res; ++ char *buf; ++ struct inode *inode = realdentry->d_inode; ++ mm_segment_t old_fs; ++ ++ res = -EINVAL; ++ if (!inode->i_op->readlink) ++ goto err; ++ ++ res = -ENOMEM; ++ buf = (char *) __get_free_page(GFP_KERNEL); ++ if (!buf) ++ goto err; ++ ++ old_fs = get_fs(); ++ set_fs(get_ds()); ++ /* The cast to a user pointer is valid due to the set_fs() */ ++ res = inode->i_op->readlink(realdentry, ++ (char __user *)buf, PAGE_SIZE - 1); ++ set_fs(old_fs); ++ if (res < 0) { ++ free_page((unsigned long) buf); ++ goto err; ++ } ++ buf[res] = '\0'; ++ ++ return buf; ++ ++err: ++ return ERR_PTR(res); ++} ++ ++static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) ++{ ++ struct iattr attr = { ++ .ia_valid = ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, ++ .ia_atime = stat->atime, ++ .ia_mtime = stat->mtime, ++ }; ++ ++ return notify_change(upperdentry, &attr); ++} ++ ++static int ovl_set_mode(struct dentry *upperdentry, umode_t mode) ++{ ++ struct iattr attr = { ++ .ia_valid = ATTR_MODE, ++ .ia_mode = mode, ++ }; ++ ++ return notify_change(upperdentry, &attr); ++} ++ ++static int ovl_copy_up_locked(struct dentry *upperdir, struct dentry *dentry, ++ struct path *lowerpath, struct kstat *stat, ++ const char *link) ++{ ++ int err; ++ struct path newpath; ++ umode_t mode = stat->mode; ++ ++ /* Can't properly set mode on creation because of the umask */ ++ stat->mode &= S_IFMT; ++ ++ ovl_path_upper(dentry, &newpath); ++ WARN_ON(newpath.dentry); ++ newpath.dentry = ovl_upper_create(upperdir, dentry, stat, link); ++ if (IS_ERR(newpath.dentry)) ++ return PTR_ERR(newpath.dentry); ++ ++ if (S_ISREG(stat->mode)) { ++ err = ovl_copy_up_data(lowerpath, &newpath, stat->size); ++ if (err) ++ goto err_remove; ++ } ++ ++ err = ovl_copy_up_xattr(lowerpath->dentry, newpath.dentry); ++ if (err) ++ goto err_remove; ++ ++ mutex_lock(&newpath.dentry->d_inode->i_mutex); ++ if (!S_ISLNK(stat->mode)) ++ err = ovl_set_mode(newpath.dentry, mode); ++ if (!err) ++ err = ovl_set_timestamps(newpath.dentry, stat); ++ mutex_unlock(&newpath.dentry->d_inode->i_mutex); ++ if (err) ++ goto err_remove; ++ ++ ovl_dentry_update(dentry, newpath.dentry); ++ ++ /* ++ * Easiest way to get rid of the lower dentry reference is to ++ * drop this dentry. This is neither needed nor possible for ++ * directories. ++ */ ++ if (!S_ISDIR(stat->mode)) ++ d_drop(dentry); ++ ++ return 0; ++ ++err_remove: ++ if (S_ISDIR(stat->mode)) ++ vfs_rmdir(upperdir->d_inode, newpath.dentry); ++ else ++ vfs_unlink(upperdir->d_inode, newpath.dentry); ++ ++ dput(newpath.dentry); ++ ++ return err; ++} ++ ++/* ++ * Copy up a single dentry ++ * ++ * Directory renames only allowed on "pure upper" (already created on ++ * upper filesystem, never copied up). Directories which are on lower or ++ * are merged may not be renamed. For these -EXDEV is returned and ++ * userspace has to deal with it. This means, when copying up a ++ * directory we can rely on it and ancestors being stable. ++ * ++ * Non-directory renames start with copy up of source if necessary. The ++ * actual rename will only proceed once the copy up was successful. Copy ++ * up uses upper parent i_mutex for exclusion. Since rename can change ++ * d_parent it is possible that the copy up will lock the old parent. At ++ * that point the file will have already been copied up anyway. ++ */ ++static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, ++ struct path *lowerpath, struct kstat *stat) ++{ ++ int err; ++ struct kstat pstat; ++ struct path parentpath; ++ struct dentry *upperdir; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ char *link = NULL; ++ ++ ovl_path_upper(parent, &parentpath); ++ upperdir = parentpath.dentry; ++ ++ err = vfs_getattr(parentpath.mnt, parentpath.dentry, &pstat); ++ if (err) ++ return err; ++ ++ if (S_ISLNK(stat->mode)) { ++ link = ovl_read_symlink(lowerpath->dentry); ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ } ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_free_link; ++ ++ override_cred->fsuid = stat->uid; ++ override_cred->fsgid = stat->gid; ++ /* ++ * CAP_SYS_ADMIN for copying up extended attributes ++ * CAP_DAC_OVERRIDE for create ++ * CAP_FOWNER for chmod, timestamp update ++ * CAP_FSETID for chmod ++ * CAP_MKNOD for mknod ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ cap_raise(override_cred->cap_effective, CAP_FSETID); ++ cap_raise(override_cred->cap_effective, CAP_MKNOD); ++ old_cred = override_creds(override_cred); ++ ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ if (ovl_path_type(dentry) != OVL_PATH_LOWER) { ++ err = 0; ++ } else { ++ err = ovl_copy_up_locked(upperdir, dentry, lowerpath, ++ stat, link); ++ if (!err) { ++ /* Restore timestamps on parent (best effort) */ ++ ovl_set_timestamps(upperdir, &pstat); ++ } ++ } ++ ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++out_free_link: ++ if (link) ++ free_page((unsigned long) link); ++ ++ return err; ++} ++ ++int ovl_copy_up(struct dentry *dentry) ++{ ++ int err; ++ ++ err = 0; ++ while (!err) { ++ struct dentry *next; ++ struct dentry *parent; ++ struct path lowerpath; ++ struct kstat stat; ++ enum ovl_path_type type = ovl_path_type(dentry); ++ ++ if (type != OVL_PATH_LOWER) ++ break; ++ ++ next = dget(dentry); ++ /* find the topmost dentry not yet copied up */ ++ for (;;) { ++ parent = dget_parent(next); ++ ++ type = ovl_path_type(parent); ++ if (type != OVL_PATH_LOWER) ++ break; ++ ++ dput(next); ++ next = parent; ++ } ++ ++ ovl_path_lower(next, &lowerpath); ++ err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); ++ if (!err) ++ err = ovl_copy_up_one(parent, next, &lowerpath, &stat); ++ ++ dput(parent); ++ dput(next); ++ } ++ ++ return err; ++} ++ ++/* Optimize by not copying up the file first and truncating later */ ++int ovl_copy_up_truncate(struct dentry *dentry, loff_t size) ++{ ++ int err; ++ struct kstat stat; ++ struct path lowerpath; ++ struct dentry *parent = dget_parent(dentry); ++ ++ err = ovl_copy_up(parent); ++ if (err) ++ goto out_dput_parent; ++ ++ ovl_path_lower(dentry, &lowerpath); ++ err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); ++ if (err) ++ goto out_dput_parent; ++ ++ if (size < stat.size) ++ stat.size = size; ++ ++ err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); ++ ++out_dput_parent: ++ dput(parent); ++ return err; ++} +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +new file mode 100644 +index 0000000..834bed8 +--- /dev/null ++++ b/fs/overlayfs/dir.c +@@ -0,0 +1,596 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell 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 "overlayfs.h" ++ ++static const char *ovl_whiteout_symlink = "(overlay-whiteout)"; ++ ++static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry) ++{ ++ int err; ++ struct dentry *newdentry; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ /* FIXME: recheck lower dentry to see if whiteout is really needed */ ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out; ++ ++ /* ++ * CAP_SYS_ADMIN for setxattr ++ * CAP_DAC_OVERRIDE for symlink creation ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ override_cred->fsuid = 0; ++ override_cred->fsgid = 0; ++ old_cred = override_creds(override_cred); ++ ++ newdentry = lookup_one_len(dentry->d_name.name, upperdir, ++ dentry->d_name.len); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_put_cred; ++ ++ /* Just been removed within the same locked region */ ++ WARN_ON(newdentry->d_inode); ++ ++ err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink); ++ if (err) ++ goto out_dput; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ ++ err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0); ++ if (err) ++ vfs_unlink(upperdir->d_inode, newdentry); ++ ++out_dput: ++ dput(newdentry); ++out_put_cred: ++ revert_creds(old_cred); ++ put_cred(override_cred); ++out: ++ if (err) { ++ /* ++ * There's no way to recover from failure to whiteout. ++ * What should we do? Log a big fat error and... ? ++ */ ++ printk(KERN_ERR "overlayfs: ERROR - failed to whiteout '%s'\n", ++ dentry->d_name.name); ++ } ++ ++ return err; ++} ++ ++static struct dentry *ovl_lookup_create(struct dentry *upperdir, ++ struct dentry *template) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct qstr *name = &template->d_name; ++ ++ newdentry = lookup_one_len(name->name, upperdir, name->len); ++ if (IS_ERR(newdentry)) ++ return newdentry; ++ ++ if (newdentry->d_inode) { ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ /* No need to check whiteout if lower parent is non-existent */ ++ err = -EEXIST; ++ if (!ovl_dentry_lower(template->d_parent)) ++ goto out_dput; ++ ++ if (!S_ISLNK(newdentry->d_inode->i_mode)) ++ goto out_dput; ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_dput; ++ ++ /* ++ * CAP_SYS_ADMIN for getxattr ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ old_cred = override_creds(override_cred); ++ ++ err = -EEXIST; ++ if (ovl_is_whiteout(newdentry)) ++ err = vfs_unlink(upperdir->d_inode, newdentry); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ if (err) ++ goto out_dput; ++ ++ dput(newdentry); ++ newdentry = lookup_one_len(name->name, upperdir, name->len); ++ if (IS_ERR(newdentry)) { ++ ovl_whiteout(upperdir, template); ++ return newdentry; ++ } ++ ++ /* ++ * Whiteout just been successfully removed, parent ++ * i_mutex is still held, there's no way the lookup ++ * could return positive. ++ */ ++ WARN_ON(newdentry->d_inode); ++ } ++ ++ return newdentry; ++ ++out_dput: ++ dput(newdentry); ++ return ERR_PTR(err); ++} ++ ++struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, ++ struct kstat *stat, const char *link) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct inode *dir = upperdir->d_inode; ++ ++ newdentry = ovl_lookup_create(upperdir, dentry); ++ if (IS_ERR(newdentry)) ++ goto out; ++ ++ switch (stat->mode & S_IFMT) { ++ case S_IFREG: ++ err = vfs_create(dir, newdentry, stat->mode, NULL); ++ break; ++ ++ case S_IFDIR: ++ err = vfs_mkdir(dir, newdentry, stat->mode); ++ break; ++ ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ err = vfs_mknod(dir, newdentry, stat->mode, stat->rdev); ++ break; ++ ++ case S_IFLNK: ++ err = vfs_symlink(dir, newdentry, link); ++ break; ++ ++ default: ++ err = -EPERM; ++ } ++ if (err) { ++ if (ovl_dentry_is_opaque(dentry)) ++ ovl_whiteout(upperdir, dentry); ++ dput(newdentry); ++ newdentry = ERR_PTR(err); ++ } else if (WARN_ON(!newdentry->d_inode)) { ++ /* ++ * Not quite sure if non-instantiated dentry is legal or not. ++ * VFS doesn't seem to care so check and warn here. ++ */ ++ dput(newdentry); ++ newdentry = ERR_PTR(-ENOENT); ++ } ++ ++out: ++ return newdentry; ++ ++} ++ ++static int ovl_set_opaque(struct dentry *upperdentry) ++{ ++ int err; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* CAP_SYS_ADMIN for setxattr of "trusted" namespace */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0); ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++static int ovl_remove_opaque(struct dentry *upperdentry) ++{ ++ int err; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* CAP_SYS_ADMIN for removexattr of "trusted" namespace */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ err = vfs_removexattr(upperdentry, ovl_opaque_xattr); ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, ++ struct kstat *stat) ++{ ++ int err; ++ enum ovl_path_type type; ++ struct path realpath; ++ ++ type = ovl_path_real(dentry, &realpath); ++ err = vfs_getattr(realpath.mnt, realpath.dentry, stat); ++ if (err) ++ return err; ++ ++ stat->dev = dentry->d_sb->s_dev; ++ stat->ino = dentry->d_inode->i_ino; ++ ++ /* ++ * It's probably not worth it to count subdirs to get the ++ * correct link count. nlink=1 seems to pacify 'find' and ++ * other utilities. ++ */ ++ if (type == OVL_PATH_MERGE) ++ stat->nlink = 1; ++ ++ return 0; ++} ++ ++static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, ++ const char *link) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct dentry *upperdir; ++ struct inode *inode; ++ struct kstat stat = { ++ .mode = mode, ++ .rdev = rdev, ++ }; ++ ++ err = -ENOMEM; ++ inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata); ++ if (!inode) ++ goto out; ++ ++ err = ovl_copy_up(dentry->d_parent); ++ if (err) ++ goto out_iput; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ ++ newdentry = ovl_upper_create(upperdir, dentry, &stat, link); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ if (ovl_dentry_is_opaque(dentry) && S_ISDIR(mode)) { ++ err = ovl_set_opaque(newdentry); ++ if (err) { ++ vfs_rmdir(upperdir->d_inode, newdentry); ++ ovl_whiteout(upperdir, dentry); ++ goto out_dput; ++ } ++ } ++ ovl_dentry_update(dentry, newdentry); ++ d_instantiate(dentry, inode); ++ inode = NULL; ++ newdentry = NULL; ++ err = 0; ++ ++out_dput: ++ dput(newdentry); ++out_unlock: ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++out_iput: ++ iput(inode); ++out: ++ return err; ++} ++ ++static int ovl_create(struct inode *dir, struct dentry *dentry, int mode, ++ struct nameidata *nd) ++{ ++ return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL); ++} ++ ++static int ovl_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++{ ++ return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL); ++} ++ ++static int ovl_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ dev_t rdev) ++{ ++ return ovl_create_object(dentry, mode, rdev, NULL); ++} ++ ++static int ovl_symlink(struct inode *dir, struct dentry *dentry, ++ const char *link) ++{ ++ return ovl_create_object(dentry, S_IFLNK, 0, link); ++} ++ ++static int ovl_do_remove(struct dentry *dentry, bool is_dir) ++{ ++ int err; ++ enum ovl_path_type type; ++ struct path realpath; ++ struct dentry *upperdir; ++ ++ err = ovl_copy_up(dentry->d_parent); ++ if (err) ++ return err; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ type = ovl_path_real(dentry, &realpath); ++ if (type != OVL_PATH_LOWER) { ++ err = -ESTALE; ++ if (realpath.dentry->d_parent != upperdir) ++ goto out_d_drop; ++ ++ /* FIXME: create whiteout up front and rename to target */ ++ ++ if (is_dir) ++ err = vfs_rmdir(upperdir->d_inode, realpath.dentry); ++ else ++ err = vfs_unlink(upperdir->d_inode, realpath.dentry); ++ if (err) ++ goto out_d_drop; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ } ++ ++ if (type != OVL_PATH_UPPER || ovl_dentry_is_opaque(dentry)) ++ err = ovl_whiteout(upperdir, dentry); ++ ++ /* ++ * Keeping this dentry hashed would mean having to release ++ * upperpath/lowerpath, which could only be done if we are the ++ * sole user of this dentry. Too tricky... Just unhash for ++ * now. ++ */ ++out_d_drop: ++ d_drop(dentry); ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++ return err; ++} ++ ++static int ovl_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ return ovl_do_remove(dentry, false); ++} ++ ++ ++static int ovl_rmdir(struct inode *dir, struct dentry *dentry) ++{ ++ int err; ++ enum ovl_path_type type; ++ ++ type = ovl_path_type(dentry); ++ if (type != OVL_PATH_UPPER) { ++ err = ovl_check_empty_and_clear(dentry, type); ++ if (err) ++ return err; ++ } ++ ++ return ovl_do_remove(dentry, true); ++} ++ ++static int ovl_link(struct dentry *old, struct inode *newdir, ++ struct dentry *new) ++{ ++ int err; ++ struct dentry *olddentry; ++ struct dentry *newdentry; ++ struct dentry *upperdir; ++ ++ err = ovl_copy_up(old); ++ if (err) ++ goto out; ++ ++ err = ovl_copy_up(new->d_parent); ++ if (err) ++ goto out; ++ ++ upperdir = ovl_dentry_upper(new->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ newdentry = ovl_lookup_create(upperdir, new); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ ++ olddentry = ovl_dentry_upper(old); ++ err = vfs_link(olddentry, upperdir->d_inode, newdentry); ++ if (!err) { ++ if (WARN_ON(!newdentry->d_inode)) { ++ dput(newdentry); ++ err = -ENOENT; ++ goto out_unlock; ++ } ++ ++ ovl_dentry_version_inc(new->d_parent); ++ ovl_dentry_update(new, newdentry); ++ ++ ihold(old->d_inode); ++ d_instantiate(new, old->d_inode); ++ } else { ++ if (ovl_dentry_is_opaque(new)) ++ ovl_whiteout(upperdir, new); ++ dput(newdentry); ++ } ++out_unlock: ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++out: ++ return err; ++ ++} ++ ++static int ovl_rename(struct inode *olddir, struct dentry *old, ++ struct inode *newdir, struct dentry *new) ++{ ++ int err; ++ enum ovl_path_type old_type; ++ enum ovl_path_type new_type; ++ struct dentry *old_upperdir; ++ struct dentry *new_upperdir; ++ struct dentry *olddentry; ++ struct dentry *newdentry; ++ struct dentry *trap; ++ bool old_opaque; ++ bool new_opaque; ++ bool new_create = false; ++ bool is_dir = S_ISDIR(old->d_inode->i_mode); ++ ++ /* Don't copy up directory trees */ ++ old_type = ovl_path_type(old); ++ if (old_type != OVL_PATH_UPPER && is_dir) ++ return -EXDEV; ++ ++ if (new->d_inode) { ++ new_type = ovl_path_type(new); ++ ++ if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) { ++ if (ovl_dentry_lower(old)->d_inode == ++ ovl_dentry_lower(new)->d_inode) ++ return 0; ++ } ++ if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) { ++ if (ovl_dentry_upper(old)->d_inode == ++ ovl_dentry_upper(new)->d_inode) ++ return 0; ++ } ++ ++ if (new_type != OVL_PATH_UPPER && ++ S_ISDIR(new->d_inode->i_mode)) { ++ err = ovl_check_empty_and_clear(new, new_type); ++ if (err) ++ return err; ++ } ++ } else { ++ new_type = OVL_PATH_UPPER; ++ } ++ ++ err = ovl_copy_up(old); ++ if (err) ++ return err; ++ ++ err = ovl_copy_up(new->d_parent); ++ if (err) ++ return err; ++ ++ old_upperdir = ovl_dentry_upper(old->d_parent); ++ new_upperdir = ovl_dentry_upper(new->d_parent); ++ ++ trap = lock_rename(new_upperdir, old_upperdir); ++ ++ olddentry = ovl_dentry_upper(old); ++ newdentry = ovl_dentry_upper(new); ++ if (newdentry) { ++ dget(newdentry); ++ } else { ++ new_create = true; ++ newdentry = ovl_lookup_create(new_upperdir, new); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ } ++ ++ err = -ESTALE; ++ if (olddentry->d_parent != old_upperdir) ++ goto out_dput; ++ if (newdentry->d_parent != new_upperdir) ++ goto out_dput; ++ if (olddentry == trap) ++ goto out_dput; ++ if (newdentry == trap) ++ goto out_dput; ++ ++ old_opaque = ovl_dentry_is_opaque(old); ++ new_opaque = ovl_dentry_is_opaque(new) || new_type != OVL_PATH_UPPER; ++ ++ if (is_dir && !old_opaque && new_opaque) { ++ err = ovl_set_opaque(olddentry); ++ if (err) ++ goto out_dput; ++ } ++ ++ err = vfs_rename(old_upperdir->d_inode, olddentry, ++ new_upperdir->d_inode, newdentry); ++ ++ if (err) { ++ if (new_create && ovl_dentry_is_opaque(new)) ++ ovl_whiteout(new_upperdir, new); ++ if (is_dir && !old_opaque && new_opaque) ++ ovl_remove_opaque(olddentry); ++ goto out_dput; ++ } ++ ++ if (old_type != OVL_PATH_UPPER || old_opaque) ++ err = ovl_whiteout(old_upperdir, old); ++ if (is_dir && old_opaque && !new_opaque) ++ ovl_remove_opaque(olddentry); ++ ++ if (old_opaque != new_opaque) ++ ovl_dentry_set_opaque(old, new_opaque); ++ ++ ovl_dentry_version_inc(old->d_parent); ++ ovl_dentry_version_inc(new->d_parent); ++ ++out_dput: ++ dput(newdentry); ++out_unlock: ++ unlock_rename(new_upperdir, old_upperdir); ++ return err; ++} ++ ++const struct inode_operations ovl_dir_inode_operations = { ++ .lookup = ovl_lookup, ++ .mkdir = ovl_mkdir, ++ .symlink = ovl_symlink, ++ .unlink = ovl_unlink, ++ .rmdir = ovl_rmdir, ++ .rename = ovl_rename, ++ .link = ovl_link, ++ .setattr = ovl_setattr, ++ .create = ovl_create, ++ .mknod = ovl_mknod, ++ .permission = ovl_permission, ++ .getattr = ovl_dir_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++}; +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +new file mode 100644 +index 0000000..40b79d0 +--- /dev/null ++++ b/fs/overlayfs/inode.c +@@ -0,0 +1,383 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell 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 "overlayfs.h" ++ ++int ovl_setattr(struct dentry *dentry, struct iattr *attr) ++{ ++ struct dentry *upperdentry; ++ int err; ++ ++ if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry)) ++ err = ovl_copy_up_truncate(dentry, attr->ia_size); ++ else ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ upperdentry = ovl_dentry_upper(dentry); ++ ++ if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) ++ attr->ia_valid &= ~ATTR_MODE; ++ ++ mutex_lock(&upperdentry->d_inode->i_mutex); ++ err = notify_change(upperdentry, attr); ++ mutex_unlock(&upperdentry->d_inode->i_mutex); ++ ++ return err; ++} ++ ++static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, ++ struct kstat *stat) ++{ ++ struct path realpath; ++ ++ ovl_path_real(dentry, &realpath); ++ return vfs_getattr(realpath.mnt, realpath.dentry, stat); ++} ++ ++int ovl_permission(struct inode *inode, int mask) ++{ ++ struct ovl_entry *oe; ++ struct dentry *alias = NULL; ++ struct inode *realinode; ++ struct dentry *realdentry; ++ bool is_upper; ++ int err; ++ ++ if (S_ISDIR(inode->i_mode)) { ++ oe = inode->i_private; ++ } else if (mask & MAY_NOT_BLOCK) { ++ return -ECHILD; ++ } else { ++ /* ++ * For non-directories find an alias and get the info ++ * from there. ++ */ ++ spin_lock(&inode->i_lock); ++ if (WARN_ON(list_empty(&inode->i_dentry))) { ++ spin_unlock(&inode->i_lock); ++ return -ENOENT; ++ } ++ alias = list_entry(inode->i_dentry.next, struct dentry, d_alias); ++ dget(alias); ++ spin_unlock(&inode->i_lock); ++ oe = alias->d_fsdata; ++ } ++ ++ realdentry = ovl_entry_real(oe, &is_upper); ++ ++ /* Careful in RCU walk mode */ ++ realinode = ACCESS_ONCE(realdentry->d_inode); ++ if (!realinode) { ++ WARN_ON(!(mask & MAY_NOT_BLOCK)); ++ err = -ENOENT; ++ goto out_dput; ++ } ++ ++ if (mask & MAY_WRITE) { ++ umode_t mode = realinode->i_mode; ++ ++ /* ++ * Writes will always be redirected to upper layer, so ++ * ignore lower layer being read-only. ++ * ++ * If the overlay itself is read-only then proceed ++ * with the permission check, don't return EROFS. ++ * This will only happen if this is the lower layer of ++ * another overlayfs. ++ * ++ * If upper fs becomes read-only after the overlay was ++ * constructed return EROFS to prevent modification of ++ * upper layer. ++ */ ++ err = -EROFS; ++ if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && ++ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) ++ goto out_dput; ++ ++ /* ++ * Nobody gets write access to an immutable file. ++ */ ++ err = -EACCES; ++ if (IS_IMMUTABLE(realinode)) ++ goto out_dput; ++ } ++ ++ if (realinode->i_op->permission) ++ err = realinode->i_op->permission(realinode, mask); ++ else ++ err = generic_permission(realinode, mask); ++out_dput: ++ dput(alias); ++ return err; ++} ++ ++ ++struct ovl_link_data { ++ struct dentry *realdentry; ++ void *cookie; ++}; ++ ++static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ void *ret; ++ struct dentry *realdentry; ++ struct inode *realinode; ++ ++ realdentry = ovl_dentry_real(dentry); ++ realinode = realdentry->d_inode; ++ ++ if (WARN_ON(!realinode->i_op->follow_link)) ++ return ERR_PTR(-EPERM); ++ ++ ret = realinode->i_op->follow_link(realdentry, nd); ++ if (IS_ERR(ret)) ++ return ret; ++ ++ if (realinode->i_op->put_link) { ++ struct ovl_link_data *data; ++ ++ data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL); ++ if (!data) { ++ realinode->i_op->put_link(realdentry, nd, ret); ++ return ERR_PTR(-ENOMEM); ++ } ++ data->realdentry = realdentry; ++ data->cookie = ret; ++ ++ return data; ++ } else { ++ return NULL; ++ } ++} ++ ++static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c) ++{ ++ struct inode *realinode; ++ struct ovl_link_data *data = c; ++ ++ if (!data) ++ return; ++ ++ realinode = data->realdentry->d_inode; ++ realinode->i_op->put_link(data->realdentry, nd, data->cookie); ++ kfree(data); ++} ++ ++static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) ++{ ++ struct path realpath; ++ struct inode *realinode; ++ ++ ovl_path_real(dentry, &realpath); ++ realinode = realpath.dentry->d_inode; ++ ++ if (!realinode->i_op->readlink) ++ return -EINVAL; ++ ++ touch_atime(realpath.mnt, realpath.dentry); ++ ++ return realinode->i_op->readlink(realpath.dentry, buf, bufsiz); ++} ++ ++ ++static bool ovl_is_private_xattr(const char *name) ++{ ++ return strncmp(name, "trusted.overlay.", 14) == 0; ++} ++ ++int ovl_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ int err; ++ struct dentry *upperdentry; ++ ++ if (ovl_is_private_xattr(name)) ++ return -EPERM; ++ ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ upperdentry = ovl_dentry_upper(dentry); ++ return vfs_setxattr(upperdentry, name, value, size, flags); ++} ++ ++ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ++ void *value, size_t size) ++{ ++ if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ++ ovl_is_private_xattr(name)) ++ return -ENODATA; ++ ++ return vfs_getxattr(ovl_dentry_real(dentry), name, value, size); ++} ++ ++ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) ++{ ++ ssize_t res; ++ int off; ++ ++ res = vfs_listxattr(ovl_dentry_real(dentry), list, size); ++ if (res <= 0 || size == 0) ++ return res; ++ ++ if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE) ++ return res; ++ ++ /* filter out private xattrs */ ++ for (off = 0; off < res;) { ++ char *s = list + off; ++ size_t slen = strlen(s) + 1; ++ ++ BUG_ON(off + slen > res); ++ ++ if (ovl_is_private_xattr(s)) { ++ res -= slen; ++ memmove(s, s + slen, res - off); ++ } else { ++ off += slen; ++ } ++ } ++ ++ return res; ++} ++ ++int ovl_removexattr(struct dentry *dentry, const char *name) ++{ ++ int err; ++ struct path realpath; ++ enum ovl_path_type type; ++ ++ if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ++ ovl_is_private_xattr(name)) ++ return -ENODATA; ++ ++ type = ovl_path_real(dentry, &realpath); ++ if (type == OVL_PATH_LOWER) { ++ err = vfs_getxattr(realpath.dentry, name, NULL, 0); ++ if (err < 0) ++ return err; ++ ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ ovl_path_upper(dentry, &realpath); ++ } ++ ++ return vfs_removexattr(realpath.dentry, name); ++} ++ ++static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, ++ struct dentry *realdentry) ++{ ++ if (type != OVL_PATH_LOWER) ++ return false; ++ ++ if (special_file(realdentry->d_inode->i_mode)) ++ return false; ++ ++ if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC)) ++ return false; ++ ++ return true; ++} ++ ++static struct file *ovl_open(struct dentry *dentry, int flags, ++ const struct cred *cred) ++{ ++ int err; ++ struct path realpath; ++ enum ovl_path_type type; ++ ++ type = ovl_path_real(dentry, &realpath); ++ if (ovl_open_need_copy_up(flags, type, realpath.dentry)) { ++ if (flags & O_TRUNC) ++ err = ovl_copy_up_truncate(dentry, 0); ++ else ++ err = ovl_copy_up(dentry); ++ if (err) ++ return ERR_PTR(err); ++ ++ ovl_path_upper(dentry, &realpath); ++ } ++ ++ return vfs_open(&realpath, flags, cred); ++} ++ ++static const struct inode_operations ovl_file_inode_operations = { ++ .setattr = ovl_setattr, ++ .permission = ovl_permission, ++ .getattr = ovl_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++ .open = ovl_open, ++}; ++ ++static const struct inode_operations ovl_symlink_inode_operations = { ++ .setattr = ovl_setattr, ++ .follow_link = ovl_follow_link, ++ .put_link = ovl_put_link, ++ .readlink = ovl_readlink, ++ .getattr = ovl_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++}; ++ ++struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, ++ struct ovl_entry *oe) ++{ ++ struct inode *inode; ++ ++ inode = new_inode(sb); ++ if (!inode) ++ return NULL; ++ ++ mode &= S_IFMT; ++ ++ inode->i_ino = get_next_ino(); ++ inode->i_mode = mode; ++ inode->i_flags |= S_NOATIME | S_NOCMTIME; ++ ++ switch (mode) { ++ case S_IFDIR: ++ inode->i_private = oe; ++ inode->i_op = &ovl_dir_inode_operations; ++ inode->i_fop = &ovl_dir_operations; ++ break; ++ ++ case S_IFLNK: ++ inode->i_op = &ovl_symlink_inode_operations; ++ break; ++ ++ case S_IFREG: ++ case S_IFSOCK: ++ case S_IFBLK: ++ case S_IFCHR: ++ case S_IFIFO: ++ inode->i_op = &ovl_file_inode_operations; ++ break; ++ ++ default: ++ WARN(1, "illegal file type: %i\n", mode); ++ inode = NULL; ++ } ++ ++ return inode; ++ ++} +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +new file mode 100644 +index 0000000..07a1fe9 +--- /dev/null ++++ b/fs/overlayfs/overlayfs.h +@@ -0,0 +1,63 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell 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. ++ */ ++ ++struct ovl_entry; ++ ++enum ovl_path_type { ++ OVL_PATH_UPPER, ++ OVL_PATH_MERGE, ++ OVL_PATH_LOWER, ++}; ++ ++extern const char *ovl_opaque_xattr; ++extern const char *ovl_whiteout_xattr; ++extern const struct dentry_operations ovl_dentry_operations; ++ ++enum ovl_path_type ovl_path_type(struct dentry *dentry); ++u64 ovl_dentry_version_get(struct dentry *dentry); ++void ovl_dentry_version_inc(struct dentry *dentry); ++void ovl_path_upper(struct dentry *dentry, struct path *path); ++void ovl_path_lower(struct dentry *dentry, struct path *path); ++enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); ++struct dentry *ovl_dentry_upper(struct dentry *dentry); ++struct dentry *ovl_dentry_lower(struct dentry *dentry); ++struct dentry *ovl_dentry_real(struct dentry *dentry); ++struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper); ++bool ovl_dentry_is_opaque(struct dentry *dentry); ++void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque); ++bool ovl_is_whiteout(struct dentry *dentry); ++void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); ++struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd); ++ ++struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, ++ struct kstat *stat, const char *link); ++ ++/* readdir.c */ ++extern const struct file_operations ovl_dir_operations; ++int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type); ++ ++/* inode.c */ ++int ovl_setattr(struct dentry *dentry, struct iattr *attr); ++int ovl_permission(struct inode *inode, int mask); ++int ovl_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags); ++ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ++ void *value, size_t size); ++ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); ++int ovl_removexattr(struct dentry *dentry, const char *name); ++ ++struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, ++ struct ovl_entry *oe); ++/* dir.c */ ++extern const struct inode_operations ovl_dir_inode_operations; ++ ++/* copy_up.c */ ++int ovl_copy_up(struct dentry *dentry); ++int ovl_copy_up_truncate(struct dentry *dentry, loff_t size); +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +new file mode 100644 +index 0000000..6fcda39 +--- /dev/null ++++ b/fs/overlayfs/readdir.c +@@ -0,0 +1,559 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell 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 "overlayfs.h" ++ ++struct ovl_cache_entry { ++ const char *name; ++ unsigned int len; ++ unsigned int type; ++ u64 ino; ++ bool is_whiteout; ++ struct list_head l_node; ++ struct rb_node node; ++}; ++ ++struct ovl_readdir_data { ++ struct rb_root *root; ++ struct list_head *list; ++ struct list_head *middle; ++ struct dentry *dir; ++ int count; ++ int err; ++}; ++ ++struct ovl_dir_file { ++ bool is_real; ++ bool is_cached; ++ struct list_head cursor; ++ u64 cache_version; ++ struct list_head cache; ++ struct file *realfile; ++}; ++ ++static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n) ++{ ++ return container_of(n, struct ovl_cache_entry, node); ++} ++ ++static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, ++ const char *name, int len) ++{ ++ struct rb_node *node = root->rb_node; ++ int cmp; ++ ++ while (node) { ++ struct ovl_cache_entry *p = ovl_cache_entry_from_node(node); ++ ++ cmp = strncmp(name, p->name, len); ++ if (cmp > 0) ++ node = p->node.rb_right; ++ else if (cmp < 0 || len < p->len) ++ node = p->node.rb_left; ++ else ++ return p; ++ } ++ ++ return NULL; ++} ++ ++static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len, ++ u64 ino, unsigned int d_type) ++{ ++ struct ovl_cache_entry *p; ++ ++ p = kmalloc(sizeof(*p) + len + 1, GFP_KERNEL); ++ if (p) { ++ char *name_copy = (char *) (p + 1); ++ memcpy(name_copy, name, len); ++ name_copy[len] = '\0'; ++ p->name = name_copy; ++ p->len = len; ++ p->type = d_type; ++ p->ino = ino; ++ p->is_whiteout = false; ++ } ++ ++ return p; ++} ++ ++static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd, ++ const char *name, int len, u64 ino, ++ unsigned int d_type) ++{ ++ struct rb_node **newp = &rdd->root->rb_node; ++ struct rb_node *parent = NULL; ++ struct ovl_cache_entry *p; ++ ++ while (*newp) { ++ int cmp; ++ struct ovl_cache_entry *tmp; ++ ++ parent = *newp; ++ tmp = ovl_cache_entry_from_node(*newp); ++ cmp = strncmp(name, tmp->name, len); ++ if (cmp > 0) ++ newp = &tmp->node.rb_right; ++ else if (cmp < 0 || len < tmp->len) ++ newp = &tmp->node.rb_left; ++ else ++ return 0; ++ } ++ ++ p = ovl_cache_entry_new(name, len, ino, d_type); ++ if (p == NULL) ++ return -ENOMEM; ++ ++ list_add_tail(&p->l_node, rdd->list); ++ rb_link_node(&p->node, parent, newp); ++ rb_insert_color(&p->node, rdd->root); ++ ++ return 0; ++} ++ ++static int ovl_fill_lower(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = buf; ++ struct ovl_cache_entry *p; ++ ++ rdd->count++; ++ p = ovl_cache_entry_find(rdd->root, name, namelen); ++ if (p) { ++ list_move_tail(&p->l_node, rdd->middle); ++ } else { ++ p = ovl_cache_entry_new(name, namelen, ino, d_type); ++ if (p == NULL) ++ rdd->err = -ENOMEM; ++ else ++ list_add_tail(&p->l_node, rdd->middle); ++ } ++ ++ return rdd->err; ++} ++ ++static void ovl_cache_free(struct list_head *list) ++{ ++ struct ovl_cache_entry *p; ++ struct ovl_cache_entry *n; ++ ++ list_for_each_entry_safe(p, n, list, l_node) ++ kfree(p); ++ ++ INIT_LIST_HEAD(list); ++} ++ ++static int ovl_fill_upper(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = buf; ++ ++ rdd->count++; ++ return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type); ++} ++ ++static inline int ovl_dir_read(struct path *realpath, ++ struct ovl_readdir_data *rdd, filldir_t filler) ++{ ++ struct file *realfile; ++ int err; ++ ++ realfile = vfs_open(realpath, O_RDONLY | O_DIRECTORY, current_cred()); ++ if (IS_ERR(realfile)) ++ return PTR_ERR(realfile); ++ ++ do { ++ rdd->count = 0; ++ rdd->err = 0; ++ err = vfs_readdir(realfile, filler, rdd); ++ if (err >= 0) ++ err = rdd->err; ++ } while (!err && rdd->count); ++ fput(realfile); ++ ++ return 0; ++} ++ ++static void ovl_dir_reset(struct file *file) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ enum ovl_path_type type = ovl_path_type(file->f_path.dentry); ++ ++ if (ovl_dentry_version_get(file->f_path.dentry) != od->cache_version) { ++ list_del_init(&od->cursor); ++ ovl_cache_free(&od->cache); ++ od->is_cached = false; ++ } ++ WARN_ON(!od->is_real && type != OVL_PATH_MERGE); ++ if (od->is_real && type == OVL_PATH_MERGE) { ++ fput(od->realfile); ++ od->realfile = NULL; ++ od->is_real = false; ++ } ++} ++ ++static int ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd) ++{ ++ struct ovl_cache_entry *p; ++ struct dentry *dentry; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) { ++ ovl_cache_free(rdd->list); ++ return -ENOMEM; ++ } ++ ++ /* ++ * CAP_SYS_ADMIN for getxattr ++ * CAP_DAC_OVERRIDE for lookup ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ old_cred = override_creds(override_cred); ++ ++ mutex_lock(&rdd->dir->d_inode->i_mutex); ++ list_for_each_entry(p, rdd->list, l_node) { ++ if (p->type != DT_LNK) ++ continue; ++ ++ dentry = lookup_one_len(p->name, rdd->dir, p->len); ++ if (IS_ERR(dentry)) ++ continue; ++ ++ p->is_whiteout = ovl_is_whiteout(dentry); ++ dput(dentry); ++ } ++ mutex_unlock(&rdd->dir->d_inode->i_mutex); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return 0; ++} ++ ++static inline int ovl_dir_read_merged(struct path *upperpath, struct path *lowerpath, ++ struct ovl_readdir_data *rdd) ++{ ++ int err; ++ struct rb_root root = RB_ROOT; ++ struct list_head middle; ++ ++ rdd->root = &root; ++ if (upperpath->dentry) { ++ rdd->dir = upperpath->dentry; ++ err = ovl_dir_read(upperpath, rdd, ovl_fill_upper); ++ if (err) ++ goto out; ++ ++ err = ovl_dir_mark_whiteouts(rdd); ++ if (err) ++ goto out; ++ } ++ /* ++ * Insert lowerpath entries before upperpath ones, this allows ++ * offsets to be reasonably constant ++ */ ++ list_add(&middle, rdd->list); ++ rdd->middle = &middle; ++ err = ovl_dir_read(lowerpath, rdd, ovl_fill_lower); ++ list_del(&middle); ++out: ++ rdd->root = NULL; ++ ++ return err; ++} ++ ++static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) ++{ ++ struct list_head *l; ++ loff_t off; ++ ++ l = od->cache.next; ++ for (off = 0; off < pos; off++) { ++ if (l == &od->cache) ++ break; ++ l = l->next; ++ } ++ list_move_tail(&od->cursor, l); ++} ++ ++static int ovl_readdir(struct file *file, void *buf, filldir_t filler) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ int res; ++ ++ if (!file->f_pos) ++ ovl_dir_reset(file); ++ ++ if (od->is_real) { ++ res = vfs_readdir(od->realfile, filler, buf); ++ file->f_pos = od->realfile->f_pos; ++ ++ return res; ++ } ++ ++ if (!od->is_cached) { ++ struct path lowerpath; ++ struct path upperpath; ++ struct ovl_readdir_data rdd = { .list = &od->cache }; ++ ++ ovl_path_lower(file->f_path.dentry, &lowerpath); ++ ovl_path_upper(file->f_path.dentry, &upperpath); ++ ++ res = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd); ++ if (res) { ++ ovl_cache_free(rdd.list); ++ return res; ++ } ++ ++ od->cache_version = ovl_dentry_version_get(file->f_path.dentry); ++ od->is_cached = true; ++ ++ ovl_seek_cursor(od, file->f_pos); ++ } ++ ++ while (od->cursor.next != &od->cache) { ++ int over; ++ loff_t off; ++ struct ovl_cache_entry *p; ++ ++ p = list_entry(od->cursor.next, struct ovl_cache_entry, l_node); ++ off = file->f_pos; ++ if (!p->is_whiteout) { ++ over = filler(buf, p->name, p->len, off, p->ino, p->type); ++ if (over) ++ break; ++ } ++ file->f_pos++; ++ list_move(&od->cursor, &p->l_node); ++ } ++ ++ return 0; ++} ++ ++static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin) ++{ ++ loff_t res; ++ struct ovl_dir_file *od = file->private_data; ++ ++ mutex_lock(&file->f_dentry->d_inode->i_mutex); ++ if (!file->f_pos) ++ ovl_dir_reset(file); ++ ++ if (od->is_real) { ++ res = vfs_llseek(od->realfile, offset, origin); ++ file->f_pos = od->realfile->f_pos; ++ } else { ++ res = -EINVAL; ++ ++ switch (origin) { ++ case SEEK_CUR: ++ offset += file->f_pos; ++ break; ++ case SEEK_SET: ++ break; ++ default: ++ goto out_unlock; ++ } ++ if (offset < 0) ++ goto out_unlock; ++ ++ if (offset != file->f_pos) { ++ file->f_pos = offset; ++ if (od->is_cached) ++ ovl_seek_cursor(od, offset); ++ } ++ res = offset; ++ } ++out_unlock: ++ mutex_unlock(&file->f_dentry->d_inode->i_mutex); ++ ++ return res; ++} ++ ++static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, ++ int datasync) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ ++ /* May need to reopen directory if it got copied up */ ++ if (!od->realfile) { ++ struct path upperpath; ++ ++ ovl_path_upper(file->f_path.dentry, &upperpath); ++ od->realfile = vfs_open(&upperpath, O_RDONLY, current_cred()); ++ if (IS_ERR(od->realfile)) ++ return PTR_ERR(od->realfile); ++ } ++ ++ return vfs_fsync_range(od->realfile, start, end, datasync); ++} ++ ++static int ovl_dir_release(struct inode *inode, struct file *file) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ ++ list_del(&od->cursor); ++ ovl_cache_free(&od->cache); ++ if (od->realfile) ++ fput(od->realfile); ++ kfree(od); ++ ++ return 0; ++} ++ ++static int ovl_dir_open(struct inode *inode, struct file *file) ++{ ++ struct path realpath; ++ struct file *realfile; ++ struct ovl_dir_file *od; ++ enum ovl_path_type type; ++ ++ od = kzalloc(sizeof(struct ovl_dir_file), GFP_KERNEL); ++ if (!od) ++ return -ENOMEM; ++ ++ type = ovl_path_real(file->f_path.dentry, &realpath); ++ realfile = vfs_open(&realpath, file->f_flags, current_cred()); ++ if (IS_ERR(realfile)) { ++ kfree(od); ++ return PTR_ERR(realfile); ++ } ++ INIT_LIST_HEAD(&od->cache); ++ INIT_LIST_HEAD(&od->cursor); ++ od->is_cached = false; ++ od->realfile = realfile; ++ od->is_real = (type != OVL_PATH_MERGE); ++ file->private_data = od; ++ ++ return 0; ++} ++ ++const struct file_operations ovl_dir_operations = { ++ .read = generic_read_dir, ++ .open = ovl_dir_open, ++ .readdir = ovl_readdir, ++ .llseek = ovl_dir_llseek, ++ .fsync = ovl_dir_fsync, ++ .release = ovl_dir_release, ++}; ++ ++static int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) ++{ ++ int err; ++ struct path lowerpath; ++ struct path upperpath; ++ struct ovl_cache_entry *p; ++ struct ovl_readdir_data rdd = { .list = list }; ++ ++ ovl_path_upper(dentry, &upperpath); ++ ovl_path_lower(dentry, &lowerpath); ++ ++ err = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd); ++ if (err) ++ return err; ++ ++ err = 0; ++ ++ list_for_each_entry(p, list, l_node) { ++ if (p->is_whiteout) ++ continue; ++ ++ if (p->name[0] == '.') { ++ if (p->len == 1) ++ continue; ++ if (p->len == 2 && p->name[1] == '.') ++ continue; ++ } ++ err = -ENOTEMPTY; ++ break; ++ } ++ ++ return err; ++} ++ ++static int ovl_remove_whiteouts(struct dentry *dir, struct list_head *list) ++{ ++ struct path upperpath; ++ struct dentry *upperdir; ++ struct ovl_cache_entry *p; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ int err; ++ ++ ovl_path_upper(dir, &upperpath); ++ upperdir = upperpath.dentry; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* ++ * CAP_DAC_OVERRIDE for lookup and unlink ++ * CAP_SYS_ADMIN for setxattr of "trusted" namespace ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ old_cred = override_creds(override_cred); ++ ++ err = vfs_setxattr(upperdir, ovl_opaque_xattr, "y", 1, 0); ++ if (err) ++ goto out_revert_creds; ++ ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ list_for_each_entry(p, list, l_node) { ++ struct dentry *dentry; ++ int ret; ++ ++ if (!p->is_whiteout) ++ continue; ++ ++ dentry = lookup_one_len(p->name, upperdir, p->len); ++ if (IS_ERR(dentry)) { ++ printk(KERN_WARNING "overlayfs: failed to lookup whiteout %.*s: %li\n", p->len, p->name, PTR_ERR(dentry)); ++ continue; ++ } ++ ret = vfs_unlink(upperdir->d_inode, dentry); ++ dput(dentry); ++ if (ret) ++ printk(KERN_WARNING "overlayfs: failed to unlink whiteout %.*s: %i\n", p->len, p->name, ret); ++ } ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++out_revert_creds: ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type) ++{ ++ int err; ++ LIST_HEAD(list); ++ ++ err = ovl_check_empty_dir(dentry, &list); ++ if (!err && type == OVL_PATH_MERGE) ++ err = ovl_remove_whiteouts(dentry, &list); ++ ++ ovl_cache_free(&list); ++ ++ return err; ++} +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +new file mode 100644 +index 0000000..508cf19 +--- /dev/null ++++ b/fs/overlayfs/super.c +@@ -0,0 +1,656 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell 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 "overlayfs.h" ++ ++MODULE_AUTHOR("Miklos Szeredi "); ++MODULE_DESCRIPTION("Overlay filesystem"); ++MODULE_LICENSE("GPL"); ++ ++struct ovl_config { ++ char *lowerdir; ++ char *upperdir; ++}; ++ ++/* private information held for overlayfs's superblock */ ++struct ovl_fs { ++ struct vfsmount *upper_mnt; ++ struct vfsmount *lower_mnt; ++ /* pathnames of lower and upper dirs, for show_options */ ++ struct ovl_config config; ++}; ++ ++/* private information held for every overlayfs dentry */ ++struct ovl_entry { ++ /* ++ * Keep "double reference" on upper dentries, so that ++ * d_delete() doesn't think it's OK to reset d_inode to NULL. ++ */ ++ struct dentry *__upperdentry; ++ struct dentry *lowerdentry; ++ union { ++ struct { ++ u64 version; ++ bool opaque; ++ }; ++ struct rcu_head rcu; ++ }; ++}; ++ ++const char *ovl_whiteout_xattr = "trusted.overlay.whiteout"; ++const char *ovl_opaque_xattr = "trusted.overlay.opaque"; ++ ++ ++enum ovl_path_type ovl_path_type(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ if (oe->__upperdentry) { ++ if (oe->lowerdentry && S_ISDIR(dentry->d_inode->i_mode)) ++ return OVL_PATH_MERGE; ++ else ++ return OVL_PATH_UPPER; ++ } else { ++ return OVL_PATH_LOWER; ++ } ++} ++ ++static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) ++{ ++ struct dentry *upperdentry = ACCESS_ONCE(oe->__upperdentry); ++ smp_read_barrier_depends(); ++ return upperdentry; ++} ++ ++void ovl_path_upper(struct dentry *dentry, struct path *path) ++{ ++ struct ovl_fs *ofs = dentry->d_sb->s_fs_info; ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ path->mnt = ofs->upper_mnt; ++ path->dentry = ovl_upperdentry_dereference(oe); ++} ++ ++void ovl_path_lower(struct dentry *dentry, struct path *path) ++{ ++ struct ovl_fs *ofs = dentry->d_sb->s_fs_info; ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ path->mnt = ofs->lower_mnt; ++ path->dentry = oe->lowerdentry; ++} ++ ++enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) ++{ ++ ++ enum ovl_path_type type = ovl_path_type(dentry); ++ ++ if (type == OVL_PATH_LOWER) ++ ovl_path_lower(dentry, path); ++ else ++ ovl_path_upper(dentry, path); ++ ++ return type; ++} ++ ++struct dentry *ovl_dentry_upper(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ return ovl_upperdentry_dereference(oe); ++} ++ ++struct dentry *ovl_dentry_lower(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ return oe->lowerdentry; ++} ++ ++struct dentry *ovl_dentry_real(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ struct dentry *realdentry; ++ ++ realdentry = ovl_upperdentry_dereference(oe); ++ if (!realdentry) ++ realdentry = oe->lowerdentry; ++ ++ return realdentry; ++} ++ ++struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper) ++{ ++ struct dentry *realdentry; ++ ++ realdentry = ovl_upperdentry_dereference(oe); ++ if (realdentry) { ++ *is_upper = true; ++ } else { ++ realdentry = oe->lowerdentry; ++ *is_upper = false; ++ } ++ return realdentry; ++} ++ ++bool ovl_dentry_is_opaque(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ return oe->opaque; ++} ++ ++void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ oe->opaque = opaque; ++} ++ ++void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&upperdentry->d_parent->d_inode->i_mutex)); ++ WARN_ON(oe->__upperdentry); ++ BUG_ON(!upperdentry->d_inode); ++ smp_wmb(); ++ oe->__upperdentry = dget(upperdentry); ++} ++ ++void ovl_dentry_version_inc(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); ++ oe->version++; ++} ++ ++u64 ovl_dentry_version_get(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); ++ return oe->version; ++} ++ ++bool ovl_is_whiteout(struct dentry *dentry) ++{ ++ int res; ++ char val; ++ ++ if (!dentry) ++ return false; ++ if (!dentry->d_inode) ++ return false; ++ if (!S_ISLNK(dentry->d_inode->i_mode)) ++ return false; ++ ++ res = vfs_getxattr(dentry, ovl_whiteout_xattr, &val, 1); ++ if (res == 1 && val == 'y') ++ return true; ++ ++ return false; ++} ++ ++static bool ovl_is_opaquedir(struct dentry *dentry) ++{ ++ int res; ++ char val; ++ ++ if (!S_ISDIR(dentry->d_inode->i_mode)) ++ return false; ++ ++ res = vfs_getxattr(dentry, ovl_opaque_xattr, &val, 1); ++ if (res == 1 && val == 'y') ++ return true; ++ ++ return false; ++} ++ ++static void ovl_entry_free(struct rcu_head *head) ++{ ++ struct ovl_entry *oe = container_of(head, struct ovl_entry, rcu); ++ kfree(oe); ++} ++ ++static void ovl_dentry_release(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ if (oe) { ++ dput(oe->__upperdentry); ++ dput(oe->__upperdentry); ++ dput(oe->lowerdentry); ++ call_rcu(&oe->rcu, ovl_entry_free); ++ } ++} ++ ++const struct dentry_operations ovl_dentry_operations = { ++ .d_release = ovl_dentry_release, ++}; ++ ++static struct ovl_entry *ovl_alloc_entry(void) ++{ ++ return kzalloc(sizeof(struct ovl_entry), GFP_KERNEL); ++} ++ ++static inline struct dentry *ovl_lookup_real(struct dentry *dir, struct qstr *name) ++{ ++ struct dentry *dentry; ++ ++ mutex_lock(&dir->d_inode->i_mutex); ++ dentry = lookup_one_len(name->name, dir, name->len); ++ mutex_unlock(&dir->d_inode->i_mutex); ++ ++ if (IS_ERR(dentry)) { ++ if (PTR_ERR(dentry) == -ENOENT) ++ dentry = NULL; ++ } else if (!dentry->d_inode) { ++ dput(dentry); ++ dentry = NULL; ++ } ++ return dentry; ++} ++ ++static int ovl_do_lookup(struct dentry *dentry) ++{ ++ struct ovl_entry *oe; ++ struct dentry *upperdir; ++ struct dentry *lowerdir; ++ struct dentry *upperdentry = NULL; ++ struct dentry *lowerdentry = NULL; ++ struct inode *inode = NULL; ++ int err; ++ ++ err = -ENOMEM; ++ oe = ovl_alloc_entry(); ++ if (!oe) ++ goto out; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ lowerdir = ovl_dentry_lower(dentry->d_parent); ++ ++ if (upperdir) { ++ upperdentry = ovl_lookup_real(upperdir, &dentry->d_name); ++ err = PTR_ERR(upperdentry); ++ if (IS_ERR(upperdentry)) ++ goto out_put_dir; ++ ++ if (lowerdir && upperdentry && ++ (S_ISLNK(upperdentry->d_inode->i_mode) || ++ S_ISDIR(upperdentry->d_inode->i_mode))) { ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_dput_upper; ++ ++ /* CAP_SYS_ADMIN needed for getxattr */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ ++ if (ovl_is_opaquedir(upperdentry)) { ++ oe->opaque = true; ++ } else if (ovl_is_whiteout(upperdentry)) { ++ dput(upperdentry); ++ upperdentry = NULL; ++ oe->opaque = true; ++ } ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ } ++ } ++ if (lowerdir && !oe->opaque) { ++ lowerdentry = ovl_lookup_real(lowerdir, &dentry->d_name); ++ err = PTR_ERR(lowerdentry); ++ if (IS_ERR(lowerdentry)) ++ goto out_dput_upper; ++ } ++ ++ if (lowerdentry && upperdentry && ++ (!S_ISDIR(upperdentry->d_inode->i_mode) || ++ !S_ISDIR(lowerdentry->d_inode->i_mode))) { ++ dput(lowerdentry); ++ lowerdentry = NULL; ++ oe->opaque = true; ++ } ++ ++ if (lowerdentry || upperdentry) { ++ struct dentry *realdentry; ++ ++ realdentry = upperdentry ? upperdentry : lowerdentry; ++ err = -ENOMEM; ++ inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode, oe); ++ if (!inode) ++ goto out_dput; ++ } ++ ++ if (upperdentry) ++ oe->__upperdentry = dget(upperdentry); ++ ++ if (lowerdentry) ++ oe->lowerdentry = lowerdentry; ++ ++ dentry->d_fsdata = oe; ++ dentry->d_op = &ovl_dentry_operations; ++ d_add(dentry, inode); ++ ++ return 0; ++ ++out_dput: ++ dput(lowerdentry); ++out_dput_upper: ++ dput(upperdentry); ++out_put_dir: ++ kfree(oe); ++out: ++ return err; ++} ++ ++struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd) ++{ ++ int err = ovl_do_lookup(dentry); ++ ++ if (err) ++ return ERR_PTR(err); ++ ++ return NULL; ++} ++ ++static void ovl_put_super(struct super_block *sb) ++{ ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ if (!(sb->s_flags & MS_RDONLY)) ++ mnt_drop_write(ufs->upper_mnt); ++ ++ mntput(ufs->upper_mnt); ++ mntput(ufs->lower_mnt); ++ ++ kfree(ufs->config.lowerdir); ++ kfree(ufs->config.upperdir); ++ kfree(ufs); ++} ++ ++static int ovl_remount_fs(struct super_block *sb, int *flagsp, char *data) ++{ ++ int flags = *flagsp; ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ /* When remounting rw or ro, we need to adjust the write access to the ++ * upper fs. ++ */ ++ if (((flags ^ sb->s_flags) & MS_RDONLY) == 0) ++ /* No change to readonly status */ ++ return 0; ++ ++ if (flags & MS_RDONLY) { ++ mnt_drop_write(ufs->upper_mnt); ++ return 0; ++ } else ++ return mnt_want_write(ufs->upper_mnt); ++} ++ ++/** ++ * ovl_statfs ++ * @sb: The overlayfs super block ++ * @buf: The struct kstatfs to fill in with stats ++ * ++ * Get the filesystem statistics. As writes always target the upper layer ++ * filesystem pass the statfs to the same filesystem. ++ */ ++static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ struct dentry *root_dentry = dentry->d_sb->s_root; ++ struct path path; ++ ovl_path_upper(root_dentry, &path); ++ ++ if (!path.dentry->d_sb->s_op->statfs) ++ return -ENOSYS; ++ return path.dentry->d_sb->s_op->statfs(path.dentry, buf); ++} ++ ++/** ++ * ovl_show_options ++ * ++ * Prints the mount options for a given superblock. ++ * Returns zero; does not fail. ++ */ ++static int ovl_show_options(struct seq_file *m, struct vfsmount *mnt) ++{ ++ struct super_block *sb = mnt->mnt_sb; ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); ++ seq_printf(m, ",upperdir=%s", ufs->config.upperdir); ++ return 0; ++} ++ ++static const struct super_operations ovl_super_operations = { ++ .put_super = ovl_put_super, ++ .remount_fs = ovl_remount_fs, ++ .statfs = ovl_statfs, ++ .show_options = ovl_show_options, ++}; ++ ++enum { ++ Opt_lowerdir, ++ Opt_upperdir, ++ Opt_err, ++}; ++ ++static const match_table_t ovl_tokens = { ++ {Opt_lowerdir, "lowerdir=%s"}, ++ {Opt_upperdir, "upperdir=%s"}, ++ {Opt_err, NULL} ++}; ++ ++static int ovl_parse_opt(char *opt, struct ovl_config *config) ++{ ++ char *p; ++ ++ config->upperdir = NULL; ++ config->lowerdir = NULL; ++ ++ while ((p = strsep(&opt, ",")) != NULL) { ++ int token; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ if (!*p) ++ continue; ++ ++ token = match_token(p, ovl_tokens, args); ++ switch (token) { ++ case Opt_upperdir: ++ kfree(config->upperdir); ++ config->upperdir = match_strdup(&args[0]); ++ if (!config->upperdir) ++ return -ENOMEM; ++ break; ++ ++ case Opt_lowerdir: ++ kfree(config->lowerdir); ++ config->lowerdir = match_strdup(&args[0]); ++ if (!config->lowerdir) ++ return -ENOMEM; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++static int ovl_fill_super(struct super_block *sb, void *data, int silent) ++{ ++ struct path lowerpath; ++ struct path upperpath; ++ struct inode *root_inode; ++ struct dentry *root_dentry; ++ struct ovl_entry *oe; ++ struct ovl_fs *ufs; ++ int err; ++ ++ err = -ENOMEM; ++ ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); ++ if (!ufs) ++ goto out; ++ ++ err = ovl_parse_opt((char *) data, &ufs->config); ++ if (err) ++ goto out_free_ufs; ++ ++ err = -EINVAL; ++ if (!ufs->config.upperdir || !ufs->config.lowerdir) { ++ printk(KERN_ERR "overlayfs: missing upperdir or lowerdir\n"); ++ goto out_free_config; ++ } ++ ++ oe = ovl_alloc_entry(); ++ if (oe == NULL) ++ goto out_free_config; ++ ++ root_inode = ovl_new_inode(sb, S_IFDIR, oe); ++ if (!root_inode) ++ goto out_free_oe; ++ ++ err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath); ++ if (err) ++ goto out_put_root; ++ ++ err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath); ++ if (err) ++ goto out_put_upperpath; ++ ++ err = -ENOTDIR; ++ if (!S_ISDIR(upperpath.dentry->d_inode->i_mode) || ++ !S_ISDIR(lowerpath.dentry->d_inode->i_mode)) ++ goto out_put_lowerpath; ++ ++ sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth, ++ lowerpath.mnt->mnt_sb->s_stack_depth) + 1; ++ ++ err = -EINVAL; ++ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { ++ printk(KERN_ERR "overlayfs: maximum fs stacking depth exceeded\n"); ++ goto out_put_lowerpath; ++ } ++ ++ ++ ufs->upper_mnt = clone_private_mount(&upperpath); ++ err = PTR_ERR(ufs->upper_mnt); ++ if (IS_ERR(ufs->upper_mnt)) { ++ printk(KERN_ERR "overlayfs: failed to clone upperpath\n"); ++ goto out_put_lowerpath; ++ } ++ ++ ufs->lower_mnt = clone_private_mount(&lowerpath); ++ err = PTR_ERR(ufs->lower_mnt); ++ if (IS_ERR(ufs->lower_mnt)) { ++ printk(KERN_ERR "overlayfs: failed to clone lowerpath\n"); ++ goto out_put_upper_mnt; ++ } ++ ++ /* ++ * Make lower_mnt R/O. That way fchmod/fchown on lower file ++ * will fail instead of modifying lower fs. ++ */ ++ ufs->lower_mnt->mnt_flags |= MNT_READONLY; ++ ++ /* If the upper fs is r/o, we mark overlayfs r/o too */ ++ if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY) ++ sb->s_flags |= MS_RDONLY; ++ ++ if (!(sb->s_flags & MS_RDONLY)) { ++ err = mnt_want_write(ufs->upper_mnt); ++ if (err) ++ goto out_put_lower_mnt; ++ } ++ ++ err = -ENOMEM; ++ root_dentry = d_alloc_root(root_inode); ++ if (!root_dentry) ++ goto out_drop_write; ++ ++ mntput(upperpath.mnt); ++ mntput(lowerpath.mnt); ++ ++ oe->__upperdentry = dget(upperpath.dentry); ++ oe->lowerdentry = lowerpath.dentry; ++ ++ root_dentry->d_fsdata = oe; ++ root_dentry->d_op = &ovl_dentry_operations; ++ ++ sb->s_op = &ovl_super_operations; ++ sb->s_root = root_dentry; ++ sb->s_fs_info = ufs; ++ ++ return 0; ++ ++out_drop_write: ++ if (!(sb->s_flags & MS_RDONLY)) ++ mnt_drop_write(ufs->upper_mnt); ++out_put_lower_mnt: ++ mntput(ufs->lower_mnt); ++out_put_upper_mnt: ++ mntput(ufs->upper_mnt); ++out_put_lowerpath: ++ path_put(&lowerpath); ++out_put_upperpath: ++ path_put(&upperpath); ++out_put_root: ++ iput(root_inode); ++out_free_oe: ++ kfree(oe); ++out_free_config: ++ kfree(ufs->config.lowerdir); ++ kfree(ufs->config.upperdir); ++out_free_ufs: ++ kfree(ufs); ++out: ++ return err; ++} ++ ++static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *raw_data) ++{ ++ return mount_nodev(fs_type, flags, raw_data, ovl_fill_super); ++} ++ ++static struct file_system_type ovl_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "overlayfs", ++ .mount = ovl_mount, ++ .kill_sb = kill_anon_super, ++}; ++ ++static int __init ovl_init(void) ++{ ++ return register_filesystem(&ovl_fs_type); ++} ++ ++static void __exit ovl_exit(void) ++{ ++ unregister_filesystem(&ovl_fs_type); ++} ++ ++module_init(ovl_init); ++module_exit(ovl_exit); +diff --git a/fs/splice.c b/fs/splice.c +index 3bd1700..a12a11f 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1329,6 +1329,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + + return ret; + } ++EXPORT_SYMBOL(do_splice_direct); + + static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 269e920..2a1497c 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1656,6 +1667,7 @@ struct inode_operations { + void (*truncate_range)(struct inode *, loff_t, loff_t); + int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, + u64 len); ++ struct file *(*open)(struct dentry *, int flags, const struct cred *); + } ____cacheline_aligned; + + struct seq_file; +diff --git a/include/linux/mount.h b/include/linux/mount.h +index 33fe53d..30cd21e 100644 +--- a/include/linux/mount.h ++++ b/include/linux/mount.h +@@ -100,5 +100,8 @@ extern void mnt_pin(struct vfsmount *mnt); + extern void mnt_unpin(struct vfsmount *mnt); + extern int __mnt_is_readonly(struct vfsmount *mnt); + ++struct path; ++extern struct vfsmount *clone_private_mount(struct path *path); ++ + extern struct vfsmount *do_kern_mount(const char *fstype, int flags, + const char *name, void *data); + +--- original/include/linux/fs.h 2016-11-20 01:01:45.000000000 +0000 ++++ linux-3.2.84/include/linux/fs.h 2017-02-18 18:00:23.041049898 +0000 +@@ -2087,6 +2088,7 @@ extern struct file *file_open_root(struc + const char *, int, umode_t); + extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, + const struct cred *); ++extern struct file *vfs_open(struct path *, int flags, const struct cred *); + extern int filp_close(struct file *, fl_owner_t id); + extern char * getname(const char __user *); + diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch new file mode 100644 index 00000000..a16d6c5c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch @@ -0,0 +1,35 @@ +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -62,6 +62,14 @@ config MAGIC_SYSRQ + keys are documented in . Don't say Y + unless you really know what this hack does. + ++config MAGIC_SYSRQ_DEFAULT_MASK ++ hex "Default mask for Magic SysRq keys on the console" ++ depends on MAGIC_SYSRQ ++ default 1 ++ help ++ Specifies the default mask for the allowed SysRq keys. This can be ++ used to disable several sensitive keys by default. ++ + config STRIP_ASM_SYMS + bool "Strip assembler-generated symbols during link" + default n +@@ -278,6 +286,15 @@ config BOOTPARAM_HUNG_TASK_PANIC_VALUE + default 0 if !BOOTPARAM_HUNG_TASK_PANIC + default 1 if BOOTPARAM_HUNG_TASK_PANIC + ++config PANIC_TIMEOUT ++ int "panic timeout" ++ default 0 ++ help ++ Set the timeout value (in seconds) until a reboot occurs when the ++ the kernel panics. If n = 0, then we wait forever. A timeout ++ value n > 0 will wait n seconds before rebooting, while a timeout ++ value n < 0 will reboot immediately. ++ + config SCHED_DEBUG + bool "Collect scheduler debugging info" + depends on DEBUG_KERNEL && PROC_FS +diff --git a/lib/Makefile b/lib/Makefile +index c06efca..fba5b91 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch new file mode 100644 index 00000000..e881fc9d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch @@ -0,0 +1,14 @@ +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -244,6 +244,9 @@ config CPU_RMAP + bool + depends on SMP + ++config DQL ++ bool ++ + # + # Netlink attribute parsing support is select'ed if needed + # +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index 82928f5..005f0b9 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch new file mode 100644 index 00000000..32a1cdae --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch @@ -0,0 +1,14 @@ +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -116,6 +116,8 @@ obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o + + obj-$(CONFIG_CORDIC) += cordic.o + ++obj-$(CONFIG_DQL) += dynamic_queue_limits.o ++ + hostprogs-y := gen_crc32table + clean-files := crc32table.h + +diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c +new file mode 100644 +index 0000000..0777c5a diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch b/packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch new file mode 100644 index 00000000..08a56ac3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch @@ -0,0 +1,143 @@ +--- /dev/null ++++ b/lib/dynamic_queue_limits.c +@@ -0,0 +1,138 @@ ++/* ++ * Dynamic byte queue limits. See include/linux/dynamic_queue_limits.h ++ * ++ * Copyright (c) 2011, Tom Herbert ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define POSDIFF(A, B) ((int)((A) - (B)) > 0 ? (A) - (B) : 0) ++#define AFTER_EQ(A, B) ((int)((A) - (B)) >= 0) ++ ++/* Records completed count and recalculates the queue limit */ ++void dql_completed(struct dql *dql, unsigned int count) ++{ ++ unsigned int inprogress, prev_inprogress, limit; ++ unsigned int ovlimit, completed, num_queued; ++ bool all_prev_completed; ++ ++ num_queued = ACCESS_ONCE(dql->num_queued); ++ ++ /* Can't complete more than what's in queue */ ++ BUG_ON(count > num_queued - dql->num_completed); ++ ++ completed = dql->num_completed + count; ++ limit = dql->limit; ++ ovlimit = POSDIFF(num_queued - dql->num_completed, limit); ++ inprogress = num_queued - completed; ++ prev_inprogress = dql->prev_num_queued - dql->num_completed; ++ all_prev_completed = AFTER_EQ(completed, dql->prev_num_queued); ++ ++ if ((ovlimit && !inprogress) || ++ (dql->prev_ovlimit && all_prev_completed)) { ++ /* ++ * Queue considered starved if: ++ * - The queue was over-limit in the last interval, ++ * and there is no more data in the queue. ++ * OR ++ * - The queue was over-limit in the previous interval and ++ * when enqueuing it was possible that all queued data ++ * had been consumed. This covers the case when queue ++ * may have becomes starved between completion processing ++ * running and next time enqueue was scheduled. ++ * ++ * When queue is starved increase the limit by the amount ++ * of bytes both sent and completed in the last interval, ++ * plus any previous over-limit. ++ */ ++ limit += POSDIFF(completed, dql->prev_num_queued) + ++ dql->prev_ovlimit; ++ dql->slack_start_time = jiffies; ++ dql->lowest_slack = UINT_MAX; ++ } else if (inprogress && prev_inprogress && !all_prev_completed) { ++ /* ++ * Queue was not starved, check if the limit can be decreased. ++ * A decrease is only considered if the queue has been busy in ++ * the whole interval (the check above). ++ * ++ * If there is slack, the amount of execess data queued above ++ * the the amount needed to prevent starvation, the queue limit ++ * can be decreased. To avoid hysteresis we consider the ++ * minimum amount of slack found over several iterations of the ++ * completion routine. ++ */ ++ unsigned int slack, slack_last_objs; ++ ++ /* ++ * Slack is the maximum of ++ * - The queue limit plus previous over-limit minus twice ++ * the number of objects completed. Note that two times ++ * number of completed bytes is a basis for an upper bound ++ * of the limit. ++ * - Portion of objects in the last queuing operation that ++ * was not part of non-zero previous over-limit. That is ++ * "round down" by non-overlimit portion of the last ++ * queueing operation. ++ */ ++ slack = POSDIFF(limit + dql->prev_ovlimit, ++ 2 * (completed - dql->num_completed)); ++ slack_last_objs = dql->prev_ovlimit ? ++ POSDIFF(dql->prev_last_obj_cnt, dql->prev_ovlimit) : 0; ++ ++ slack = max(slack, slack_last_objs); ++ ++ if (slack < dql->lowest_slack) ++ dql->lowest_slack = slack; ++ ++ if (time_after(jiffies, ++ dql->slack_start_time + dql->slack_hold_time)) { ++ limit = POSDIFF(limit, dql->lowest_slack); ++ dql->slack_start_time = jiffies; ++ dql->lowest_slack = UINT_MAX; ++ } ++ } ++ ++ /* Enforce bounds on limit */ ++ limit = clamp(limit, dql->min_limit, dql->max_limit); ++ ++ if (limit != dql->limit) { ++ dql->limit = limit; ++ ovlimit = 0; ++ } ++ ++ dql->adj_limit = limit + completed; ++ dql->prev_ovlimit = ovlimit; ++ dql->prev_last_obj_cnt = dql->last_obj_cnt; ++ dql->num_completed = completed; ++ dql->prev_num_queued = num_queued; ++} ++EXPORT_SYMBOL(dql_completed); ++ ++void dql_reset(struct dql *dql) ++{ ++ /* Reset all dynamic values */ ++ dql->limit = 0; ++ dql->num_queued = 0; ++ dql->num_completed = 0; ++ dql->last_obj_cnt = 0; ++ dql->prev_num_queued = 0; ++ dql->prev_last_obj_cnt = 0; ++ dql->prev_ovlimit = 0; ++ dql->lowest_slack = UINT_MAX; ++ dql->slack_start_time = jiffies; ++} ++EXPORT_SYMBOL(dql_reset); ++ ++int dql_init(struct dql *dql, unsigned hold_time) ++{ ++ dql->max_limit = DQL_MAX_LIMIT; ++ dql->min_limit = 0; ++ dql->slack_hold_time = hold_time; ++ dql_reset(dql); ++ return 0; ++} ++EXPORT_SYMBOL(dql_init); +diff --git a/lib/nlattr.c b/lib/nlattr.c +index be25e35..e7c6bca 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch b/packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch new file mode 100644 index 00000000..5f85fc54 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch @@ -0,0 +1,15 @@ +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -12,8 +12,10 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include + #include ++#endif + #include + #include + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 99093b3..058935e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch b/packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch new file mode 100644 index 00000000..4444356a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch @@ -0,0 +1,26 @@ +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -110,11 +110,11 @@ setup_io_tlb_npages(char *str) + __setup("swiotlb=", setup_io_tlb_npages); + /* make io_tlb_overflow tunable too? */ + +-unsigned long swioltb_nr_tbl(void) ++unsigned long swiotlb_nr_tbl(void) + { + return io_tlb_nslabs; + } +- ++EXPORT_SYMBOL_GPL(swiotlb_nr_tbl); + /* Note that this doesn't work with highmem page */ + static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, + volatile void *address) +@@ -321,6 +321,7 @@ void __init swiotlb_free(void) + free_bootmem_late(__pa(io_tlb_start), + PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); + } ++ io_tlb_nslabs = 0; + } + + static int is_swiotlb_buffer(phys_addr_t paddr) +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 2b49dd2..de77b4f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch new file mode 100644 index 00000000..25bd27c7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch @@ -0,0 +1,13 @@ +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -225,7 +225,7 @@ static ssize_t max_ratio_store(struct device *dev, + } + BDI_SHOW(max_ratio, bdi->max_ratio) + +-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) ++//#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) + + static struct device_attribute bdi_dev_attrs[] = { + __ATTR_RW(read_ahead_kb), +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 204de6a..ebaebf8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch new file mode 100644 index 00000000..374ecd05 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch @@ -0,0 +1,14 @@ +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5561,6 +5561,9 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, + + struct cgroup_subsys mem_cgroup_subsys = { + .name = "memory", ++#ifdef CONFIG_CGROUP_MEM_RES_CTLR_DISABLED ++ .disabled = 1, ++#endif + .subsys_id = mem_cgroup_subsys_id, + .create = mem_cgroup_create, + .pre_destroy = mem_cgroup_pre_destroy, +diff --git a/mm/rmap.c b/mm/rmap.c +index 98f0bf7..242fb4c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch new file mode 100644 index 00000000..835e394d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch @@ -0,0 +1,14 @@ +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -56,7 +56,9 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include ++#endif + + #include + +diff --git a/mm/slab.c b/mm/slab.c +index aea5e42..7c11f1f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch new file mode 100644 index 00000000..e8477483 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch @@ -0,0 +1,13 @@ +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -121,6 +121,8 @@ + #include + #include + ++#include ++ + /* + * DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON. + * 0 for faster, smaller code (especially in the critical paths). +diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c +index 1b7e22a..22b7e18 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch new file mode 100644 index 00000000..136b3d2d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch @@ -0,0 +1,20 @@ +--- a/mm/sparse-vmemmap.c ++++ b/mm/sparse-vmemmap.c +@@ -53,10 +53,12 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node) + struct page *page; + + if (node_state(node, N_HIGH_MEMORY)) +- page = alloc_pages_node(node, +- GFP_KERNEL | __GFP_ZERO, get_order(size)); ++ page = alloc_pages_node( ++ node, GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT, ++ get_order(size)); + else +- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, ++ page = alloc_pages( ++ GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT, + get_order(size)); + if (page) + return page_address(page); +diff --git a/mm/swap.c b/mm/swap.c +index a4b9016..6f3642b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch new file mode 100644 index 00000000..329c1c8d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch @@ -0,0 +1,14 @@ +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -31,7 +31,9 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include ++#endif + + #include "internal.h" + +diff --git a/mm/truncate.c b/mm/truncate.c +index 143883a..3915b9e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch new file mode 100644 index 00000000..ee561779 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch @@ -0,0 +1,14 @@ +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -20,7 +20,9 @@ + #include /* grr. try_to_release_page, + do_invalidatepage */ + #include ++#ifndef __GENKSYMS__ + #include ++#endif + #include "internal.h" + + +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index 1431458..bfe67ef 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch new file mode 100644 index 00000000..93d1bb93 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch @@ -0,0 +1,47 @@ +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -1124,6 +1124,32 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro + EXPORT_SYMBOL(vm_map_ram); + + /** ++ * vm_area_add_early - add vmap area early during boot ++ * @vm: vm_struct to add ++ * ++ * This function is used to add fixed kernel vm area to vmlist before ++ * vmalloc_init() is called. @vm->addr, @vm->size, and @vm->flags ++ * should contain proper values and the other fields should be zero. ++ * ++ * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING. ++ */ ++void __init vm_area_add_early(struct vm_struct *vm) ++{ ++ struct vm_struct *tmp, **p; ++ ++ BUG_ON(vmap_initialized); ++ for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) { ++ if (tmp->addr >= vm->addr) { ++ BUG_ON(tmp->addr < vm->addr + vm->size); ++ break; ++ } else ++ BUG_ON(tmp->addr + tmp->size > vm->addr); ++ } ++ vm->next = *p; ++ *p = vm; ++} ++ ++/** + * vm_area_register_early - register vmap area early during boot + * @vm: vm_struct to register + * @align: requested alignment +@@ -1145,8 +1171,7 @@ void __init vm_area_register_early(struct vm_struct *vm, size_t align) + + vm->addr = (void *)addr; + +- vm->next = vmlist; +- vmlist = vm; ++ vm_area_add_early(vm); + } + + void __init vmalloc_init(void) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index ab98dc6..f206e4b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch new file mode 100644 index 00000000..7046e44d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch @@ -0,0 +1,13 @@ +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3496,7 +3496,7 @@ void check_move_unevictable_pages(struct page **pages, int nr_pages) + + static void warn_scan_unevictable_pages(void) + { +- printk_once(KERN_WARNING ++ printk_once(KERN_DEBUG + "The scan_unevictable_pages sysctl/node-interface has been " + "disabled for lack of a legitimate use case. If you have " + "one, please send an email to linux-mm@kvack.org.\n"); +diff --git a/net/8021q/Kconfig b/net/8021q/Kconfig +index fa073a5..4232018 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch b/packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch new file mode 100644 index 00000000..e5af6d21 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch @@ -0,0 +1,264 @@ +Fix issues with OverlayFS not interacting correctly with the notify system + +diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig +index b981fc0..137d3fa 100644 +--- a/fs/notify/inotify/Kconfig ++++ b/fs/notify/inotify/Kconfig +@@ -15,3 +15,13 @@ config INOTIFY_USER + For more information, see + + If unsure, say Y. ++ ++ ++config INOTIFY_STACKFS ++ bool "Inotify support for stackable filesystem" ++ select INOTIFY_USER ++ default y ++ ---help--- ++ Say Y here to enable inotify support for stackable filesystem. ++ ++ If unsure, say N. +diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c +index f255d37..e555ac5 100644 +--- a/fs/notify/inotify/inotify_user.c ++++ b/fs/notify/inotify/inotify_user.c +@@ -24,6 +24,7 @@ + + #include + #include /* struct inode */ ++#include + #include + #include + #include /* module_init */ +@@ -86,6 +87,93 @@ ctl_table inotify_table[] = { + }; + #endif /* CONFIG_SYSCTL */ + ++#ifdef CONFIG_INOTIFY_STACKFS ++ ++static DEFINE_RWLOCK(inotify_fs_lock); ++static LIST_HEAD(inotify_fs_list); ++ ++static inline struct file_system_type* peek_fs_type(struct path *path) ++{ ++ return path->mnt->mnt_sb->s_type; ++} ++ ++static struct inotify_stackfs* inotify_get_stackfs(struct path *path) ++{ ++ struct file_system_type *fs; ++ struct inotify_stackfs *fse, *ret = NULL; ++ ++ fs = peek_fs_type(path); ++ ++ read_lock(&inotify_fs_lock); ++ list_for_each_entry(fse, &inotify_fs_list, list) { ++ if (fse->fs_type == fs) { ++ ret = fse; ++ break; ++ } ++ } ++ read_unlock(&inotify_fs_lock); ++ ++ return ret; ++} ++ ++static inline void inotify_put_stackfs(struct inotify_stackfs *fs) ++{ ++} ++ ++int inotify_register_stackfs(struct inotify_stackfs *fs) ++{ ++ int ret = 0; ++ struct inotify_stackfs *fse; ++ ++ BUG_ON(IS_ERR_OR_NULL(fs->fs_type)); ++ BUG_ON(IS_ERR_OR_NULL(fs->func)); ++ ++ INIT_LIST_HEAD(&fs->list); ++ ++ write_lock(&inotify_fs_lock); ++ list_for_each_entry(fse, &inotify_fs_list, list) { ++ if (fse->fs_type == fs->fs_type) { ++ write_unlock(&inotify_fs_lock); ++ ret = -EBUSY; ++ goto out; ++ } ++ } ++ list_add_tail(&fs->list, &inotify_fs_list); ++ write_unlock(&inotify_fs_lock); ++ ++out: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(inotify_register_stackfs); ++ ++void inotify_unregister_stackfs(struct inotify_stackfs *fs) ++{ ++ struct inotify_stackfs *fse, *n; ++ ++ write_lock(&inotify_fs_lock); ++ list_for_each_entry_safe(fse, n, &inotify_fs_list, list) { ++ if (fse == fs) { ++ list_del(&fse->list); ++ break; ++ } ++ } ++ write_unlock(&inotify_fs_lock); ++} ++EXPORT_SYMBOL_GPL(inotify_unregister_stackfs); ++ ++#else ++ ++static inline struct inotify_stackfs* inotify_get_stackfs(struct path *path) ++{ ++ return NULL; ++} ++ ++static inline void inotify_put_stackfs(struct inotify_stackfs *fs) ++{ ++} ++ ++#endif /* CONFIG_INOTIFY_STACKFS */ ++ + static inline __u32 inotify_arg_to_mask(u32 arg) + { + __u32 mask; +@@ -348,7 +436,7 @@ static const struct file_operations inotify_fops = { + /* + * find_inode - resolve a user-given path to a specific inode + */ +-static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) ++static inline int __inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) + { + int error; + +@@ -362,6 +450,27 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns + return error; + } + ++static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) ++{ ++ int ret; ++ struct path tpath; ++ struct inotify_stackfs *fse; ++ ++ ret = __inotify_find_inode(dirname, &tpath, flags); ++ if (ret) ++ return ret; ++ fse = inotify_get_stackfs(&tpath); ++ if (fse == NULL) { ++ *path = tpath; ++ return 0; ++ } ++ ret = fse->func(path, &tpath); ++ inotify_put_stackfs(fse); ++ path_put(&tpath); ++ ++ return ret; ++} ++ + static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, + int *last_wd, + struct inotify_inode_mark *i_mark) +diff --git a/overlayfs/super.c b/fs/overlayfs/super.c +index 508cf19..cb39ec9 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include "overlayfs.h" + + MODULE_AUTHOR("Miklos Szeredi "); +@@ -642,14 +643,40 @@ static struct file_system_type ovl_fs_type = { + .kill_sb = kill_anon_super, + }; + ++static int ovl_inotify_path(struct path *dst, struct path *src) ++{ ++ ovl_path_real(src->dentry, dst); ++ ++ path_get(dst); ++ ++ return 0; ++} ++ ++static struct inotify_stackfs ovl_inotify = { ++ .fs_type = &ovl_fs_type, ++ .func = ovl_inotify_path, ++}; ++ + static int __init ovl_init(void) + { +- return register_filesystem(&ovl_fs_type); ++ int ret; ++ ++ ret = register_filesystem(&ovl_fs_type); ++ if (ret) ++ return ret; ++ ret = inotify_register_stackfs(&ovl_inotify); ++ if (ret) { ++ pr_err("overlayfs: hook inotify error\n"); ++ unregister_filesystem(&ovl_fs_type); ++ } ++ ++ return ret; + } + + static void __exit ovl_exit(void) + { +- unregister_filesystem(&ovl_fs_type); ++ inotify_unregister_stackfs(&ovl_inotify); ++ unregister_filesystem(&ovl_fs_type); + } + + module_init(ovl_init); +diff --git a/include/linux/inotify.h b/include/linux/inotify.h +index d33041e..9d7e36f 100644 +--- a/include/linux/inotify.h ++++ b/include/linux/inotify.h +@@ -10,6 +10,8 @@ + /* For O_CLOEXEC and O_NONBLOCK */ + #include + #include ++#include ++#include + + /* + * struct inotify_event - structure read from the inotify device for each event +@@ -82,6 +84,32 @@ extern struct ctl_table inotify_table[]; /* for sysctl */ + IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \ + IN_ISDIR | IN_ONESHOT) + ++typedef int (*inotify_path_proc)(struct path *dst, struct path *src); ++ ++struct inotify_stackfs { ++ struct list_head list; /* entry in inotify_fs_list */ ++ struct file_system_type *fs_type; /* registed file_system_type */ ++ inotify_path_proc func; /* registed callback function */ ++}; ++ ++#ifdef CONFIG_INOTIFY_STACKFS ++ ++extern int inotify_register_stackfs(struct inotify_stackfs *fs); ++extern void inotify_unregister_stackfs(struct inotify_stackfs *fs); ++ ++#else ++ ++static inline int inotify_register_stackfs(struct inotify_stackfs *fs) ++{ ++ return 0; ++} ++ ++static inline void inotify_unregister_stackfs(struct inotify_stackfs *fs) ++{ ++} ++ ++#endif /* CONFIG_INOTIFY_STACKFS */ ++ + #endif + + #endif /* _LINUX_INOTIFY_H */ diff --git a/packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch b/packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch new file mode 100644 index 00000000..66ba4882 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch @@ -0,0 +1,3932 @@ +Device driver patches for accton as4610 54 (fan/psu/cpld/led/sfp) + +diff --git a/arch/arm/boot/dts/accton_as4610_54.dts b/arch/arm/boot/dts/accton_as4610_54.dts +index 9276c0a..8848f8c 100644 +--- a/arch/arm/boot/dts/accton_as4610_54.dts ++++ b/arch/arm/boot/dts/accton_as4610_54.dts +@@ -105,46 +105,46 @@ + }; + + i2c0: i2c@18038000 { +- compatible = "iproc-smb"; +- reg = <0x18038000 0x1000>; ++ 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 = <0>; +- interrupts = < 127 >; +- clock-frequency = <400000>; +- cpld@1,0 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "accton,as4610-54-cpld"; +- label = "cpld"; +- reg = <0x30>; +- }; ++ #size-cells = <1>; ++ compatible = "accton,as4610_54_cpld"; ++ label = "cpld"; ++ reg = <0x30>; ++ }; + }; + + i2c1: i2c@1803b000 { +- compatible = "iproc-smb"; +- reg = <0x1803b000 0x1000>; ++ 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>; +- interrupts = < 128 >; +- clock-frequency = <100000>; +- mux@70 { +- compatible = "ti,pca9548"; +- reg = <0x70>; ++ deselect-on-exit; ++ ++ // SFP+ 1 ++ i2c@0 { + #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"; +- }; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,as4610_sfp1"; ++ reg = <0x50>; ++ label = "port49"; + }; ++ }; + + // SFP+ 2 + i2c@1 { +@@ -152,7 +152,7 @@ + #size-cells = <0>; + reg = <1>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp2"; + reg = <0x50>; + label = "port50"; + }; +@@ -164,7 +164,7 @@ + #size-cells = <0>; + reg = <2>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp3"; + reg = <0x50>; + label = "port51"; + }; +@@ -176,7 +176,7 @@ + #size-cells = <0>; + reg = <3>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp4"; + reg = <0x50>; + label = "port52"; + }; +@@ -188,7 +188,7 @@ + #size-cells = <0>; + reg = <4>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp5"; + reg = <0x50>; + }; + }; +@@ -199,7 +199,7 @@ + #size-cells = <0>; + reg = <5>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp6"; + reg = <0x50>; + }; + }; +@@ -209,17 +209,21 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; +- psu_eeprom@50 { +- compatible = "at,24c02"; ++ psu1_eeprom@50 { ++ compatible = "accton,as4610_psu1"; + reg = <0x50>; +- label = "psu1_eeprom"; +- read-only; + }; +- psu_eeprom@51 { +- compatible = "at,24c02"; ++ psu1_pmbus@58 { ++ compatible = "3y-power,ym1921"; ++ reg = <0x58>; ++ }; ++ psu2_eeprom@51 { ++ compatible = "accton,as4610_psu2"; + reg = <0x51>; +- label = "psu2_eeprom"; +- read-only; ++ }; ++ psu2_pmbus@59 { ++ compatible = "3y-power,ym1921"; ++ reg = <0x59>; + }; + }; + +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 5c984a6..df89e25 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1412,6 +1412,43 @@ config SENSORS_MC13783_ADC + help + Support for the A/D converter on MC13783 PMIC. + ++config SENSORS_ACCTON_I2C_CPLD ++ tristate "Accton i2c cpld" ++ depends on I2C ++ help ++ If you say yes here you get support for Accton i2c cpld. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_i2c_cpld. ++ ++config SENSORS_ACCTON_AS4610_FAN ++ tristate "Accton as4610 fan" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 fan. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_fan. ++ ++config SENSORS_ACCTON_AS4610_PSU ++ tristate "Accton as4610 psu" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 psu. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_psu. ++ ++config SENSORS_YM2651Y ++ tristate "3Y Power (YM-2651Y, YM1921Y) Power Module" ++ depends on I2C ++ help ++ If you say yes here you get support for 3Y Power YM-2651Y and YM1921Y ++ Power Module. ++ ++ This driver can also be built as a module. If so, the module will ++ be called ym2651y. ++ + if ACPI + + comment "ACPI drivers" +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index ff3a18e..39c9888 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -21,6 +21,9 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o + + obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o + obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o ++obj-$(CONFIG_SENSORS_ACCTON_I2C_CPLD) += accton_i2c_cpld.o ++obj-$(CONFIG_SENSORS_ACCTON_AS4610_FAN) += accton_as4610_fan.o ++obj-$(CONFIG_SENSORS_ACCTON_AS4610_PSU) += accton_as4610_psu.o + obj-$(CONFIG_SENSORS_AD7314) += ad7314.o + obj-$(CONFIG_SENSORS_AD7414) += ad7414.o + obj-$(CONFIG_SENSORS_AD7418) += ad7418.o +@@ -130,6 +133,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o + obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o + obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o + obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o ++obj-$(CONFIG_SENSORS_YM2651Y) += ym2651y.o + + obj-$(CONFIG_PMBUS) += pmbus/ + +diff --git a/drivers/hwmon/accton_as4610_fan.c b/drivers/hwmon/accton_as4610_fan.c +new file mode 100644 +index 0000000..3934bcd +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_fan.c +@@ -0,0 +1,344 @@ ++/* ++ * A hwmon driver for the Accton as4610 fan ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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 ++ ++#define DRVNAME "as4610_fan" ++ ++static struct as4610_fan_data *as4610_fan_update_device(struct device *dev); ++static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count); ++ ++/* fan related data, the index should match sysfs_fan_attributes ++ */ ++static const u8 fan_reg[] = { ++ 0x2B, /* fan PWM(for all fan) */ ++ 0x2D, /* fan 1 speed(rpm) */ ++ 0x2C, /* fan 2 speed(rpm) */ ++ 0x11, /* fan1-2 operating status */ ++}; ++ ++static struct as4610_fan_data *fan_data = NULL; ++ ++/* Each client has this additional data */ ++struct as4610_fan_data { ++ struct platform_device *pdev; ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* != 0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ ++}; ++ ++enum fan_id { ++ FAN1_ID, ++ FAN2_ID ++}; ++ ++enum sysfs_fan_attributes { ++ FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ ++ FAN1_SPEED_RPM, ++ FAN2_SPEED_RPM, ++ FAN_FAULT, ++ FAN1_FAULT, ++ FAN2_FAULT ++}; ++ ++/* Define attributes ++ */ ++#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) ++#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr ++ ++#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) ++#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr ++ ++#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_SPEED_RPM) ++#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_speed_rpm.dev_attr.attr ++ ++/* fan fault attributes in this platform */ ++DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); ++DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); ++/* fan speed(rpm) attributes in this platform */ ++DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); ++DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); ++/* 1 fan duty cycle attribute in this platform */ ++DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); ++ ++static struct attribute *as4610_fan_attributes[] = { ++ /* fan related attributes */ ++ DECLARE_FAN_FAULT_ATTR(1), ++ DECLARE_FAN_FAULT_ATTR(2), ++ DECLARE_FAN_SPEED_RPM_ATTR(1), ++ DECLARE_FAN_SPEED_RPM_ATTR(2), ++ DECLARE_FAN_DUTY_CYCLE_ATTR(), ++ NULL ++}; ++ ++#define FAN_DUTY_CYCLE_REG_MASK 0xF ++#define FAN_MAX_DUTY_CYCLE 100 ++#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 ++ ++static int as4610_fan_read_value(u8 reg) ++{ ++ return accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, reg); ++} ++ ++static int as4610_fan_write_value(u8 reg, u8 value) ++{ ++ return accton_i2c_cpld_write(AS4610_CPLD_SLAVE_ADDR, reg, value); ++} ++ ++/* fan utility functions ++ */ ++static u32 reg_val_to_duty_cycle(u8 reg_val) ++{ ++ reg_val &= FAN_DUTY_CYCLE_REG_MASK; ++ return (u32)((reg_val * 125 + 5)/10); ++} ++ ++static u8 duty_cycle_to_reg_val(u8 duty_cycle) ++{ ++ return ((u32)duty_cycle * 10 / 125); ++} ++ ++static u32 reg_val_to_speed_rpm(u8 reg_val) ++{ ++ /* Count Frequency is 1.515KHz= 0.66ms ++ * Count Period = 400 cycle = 400*0.66ms = 264ms ++ * R.P.M value = read value x3.79*60/2 ++ * 3.79 = 1000ms/264ms ++ * 60 = 1min =60s ++ * 2 = 1 rotation of fan has two pulses. ++ */ ++ return (u32)reg_val * 379 * 60 / 2 / 100; ++} ++ ++static u8 is_fan_fault(struct as4610_fan_data *data, enum fan_id id) ++{ ++ u8 mask = (id == FAN1_ID) ? 0x20 : 0x10; ++ ++ return !(data->reg_val[FAN_FAULT] & mask); ++} ++ ++static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ int error, value; ++ ++ error = kstrtoint(buf, 10, &value); ++ if (error) ++ return error; ++ ++ if (value < 0 || value > FAN_MAX_DUTY_CYCLE) ++ return -EINVAL; ++ ++ as4610_fan_write_value(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); ++ return count; ++} ++ ++static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct as4610_fan_data *data = as4610_fan_update_device(dev); ++ ssize_t ret = 0; ++ ++ if (data->valid) { ++ switch (attr->index) { ++ case FAN_DUTY_CYCLE_PERCENTAGE: ++ { ++ u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[attr->index]); ++ ret = sprintf(buf, "%u\n", duty_cycle); ++ break; ++ } ++ case FAN1_SPEED_RPM: ++ case FAN2_SPEED_RPM: ++ ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); ++ break; ++ case FAN1_FAULT: ++ case FAN2_FAULT: ++ ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static const struct attribute_group as4610_fan_group = { ++ .attrs = as4610_fan_attributes, ++}; ++ ++static struct as4610_fan_data *as4610_fan_update_device(struct device *dev) ++{ ++ mutex_lock(&fan_data->update_lock); ++ ++ if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || ++ !fan_data->valid) { ++ int i; ++ ++ dev_dbg(fan_data->hwmon_dev, "Starting as4610_fan update\n"); ++ fan_data->valid = 0; ++ ++ /* Update fan data ++ */ ++ for (i = 0; i < ARRAY_SIZE(fan_data->reg_val); i++) { ++ int status = as4610_fan_read_value(fan_reg[i]); ++ ++ if (status < 0) { ++ fan_data->valid = 0; ++ mutex_unlock(&fan_data->update_lock); ++ dev_dbg(fan_data->hwmon_dev, "reg %d, err %d\n", fan_reg[i], status); ++ return fan_data; ++ } ++ else { ++ fan_data->reg_val[i] = status; ++ } ++ } ++ ++ fan_data->last_updated = jiffies; ++ fan_data->valid = 1; ++ } ++ ++ mutex_unlock(&fan_data->update_lock); ++ ++ return fan_data; ++} ++ ++static int as4610_fan_probe(struct platform_device *pdev) ++{ ++ int status = -1; ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&pdev->dev.kobj, &as4610_fan_group); ++ if (status) { ++ goto exit; ++ ++ } ++ ++ fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); ++ if (IS_ERR(fan_data->hwmon_dev)) { ++ status = PTR_ERR(fan_data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&pdev->dev, "accton_as4610_fan\n"); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++exit: ++ return status; ++} ++ ++static int as4610_fan_remove(struct platform_device *pdev) ++{ ++ hwmon_device_unregister(fan_data->hwmon_dev); ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id as4610_fan_id[] = { ++ { "as4610_fan", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_fan_id); ++ ++static struct platform_driver as4610_fan_driver = { ++ .probe = as4610_fan_probe, ++ .remove = as4610_fan_remove, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init as4610_fan_init(void) ++{ ++ int ret; ++ ++ if (as4610_number_of_system_fan() == 0) { ++ return -ENODEV; ++ } ++ ++ ret = platform_driver_register(&as4610_fan_driver); ++ if (ret < 0) { ++ goto exit; ++ } ++ ++ fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL); ++ if (!fan_data) { ++ ret = -ENOMEM; ++ platform_driver_unregister(&as4610_fan_driver); ++ goto exit; ++ } ++ ++ mutex_init(&fan_data->update_lock); ++ fan_data->valid = 0; ++ ++ fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); ++ if (IS_ERR(fan_data->pdev)) { ++ ret = PTR_ERR(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); ++ goto exit; ++ } ++ ++exit: ++ return ret; ++} ++ ++static void __exit as4610_fan_exit(void) ++{ ++ if (!fan_data) { ++ return; ++ } ++ ++ platform_device_unregister(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); ++} ++ ++late_initcall(as4610_fan_init); ++module_exit(as4610_fan_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_fan driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/hwmon/accton_as4610_psu.c b/drivers/hwmon/accton_as4610_psu.c +new file mode 100644 +index 0000000..1f0d79d +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_psu.c +@@ -0,0 +1,286 @@ ++/* ++ * An hwmon driver for accton as4610 Power Module ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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 ++ ++static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); ++static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data,int data_len); ++extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; ++ ++/* Each client has this additional data ++ */ ++struct as4610_psu_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 index; /* PSU index */ ++ u8 status; /* Status(present/power_good) register read from CPLD */ ++ char model_name[9]; /* Model name, read from eeprom */ ++}; ++ ++static struct as4610_psu_data *as4610_psu_update_device(struct device *dev); ++ ++enum as4610_psu_sysfs_attributes { ++ PSU_PRESENT, ++ PSU_MODEL_NAME, ++ PSU_POWER_GOOD ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); ++static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); ++static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); ++ ++static struct attribute *as4610_psu_attributes[] = { ++ &sensor_dev_attr_psu_present.dev_attr.attr, ++ &sensor_dev_attr_psu_model_name.dev_attr.attr, ++ &sensor_dev_attr_psu_power_good.dev_attr.attr, ++ NULL ++}; ++ ++static ssize_t show_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ u8 status = 0; ++ ++ if (attr->index == PSU_PRESENT) { ++ status = (data->status >> (data->index*2) & 0x1); ++ } ++ else { /* PSU_POWER_GOOD */ ++ status = (data->status >> (data->index*2 + 1) & 0x1); ++ } ++ ++ return sprintf(buf, "%d\n", status); ++} ++ ++static ssize_t show_model_name(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ ++ return sprintf(buf, "%s\n", data->model_name); ++} ++ ++static const struct attribute_group as4610_psu_group = { ++ .attrs = as4610_psu_attributes, ++}; ++ ++static int as4610_psu_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct as4610_psu_data *data; ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ data = kzalloc(sizeof(struct as4610_psu_data), GFP_KERNEL); ++ if (!data) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_set_clientdata(client, data); ++ data->valid = 0; ++ data->index = dev_id->driver_data; ++ mutex_init(&data->update_lock); ++ ++ dev_info(&client->dev, "chip found\n"); ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &as4610_psu_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++exit_free: ++ kfree(data); ++exit: ++ ++ return status; ++} ++ ++static int as4610_psu_remove(struct i2c_client *client) ++{ ++ struct as4610_psu_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++ kfree(data); ++ ++ return 0; ++} ++ ++enum psu_index ++{ ++ as4610_psu1, ++ as4610_psu2 ++}; ++ ++static const struct i2c_device_id as4610_psu_id[] = { ++ { "as4610_psu1", as4610_psu1 }, ++ { "as4610_psu2", as4610_psu2 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_psu_id); ++ ++static struct i2c_driver as4610_psu_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "as4610_psu", ++ }, ++ .probe = as4610_psu_probe, ++ .remove = as4610_psu_remove, ++ .id_table = as4610_psu_id, ++ .address_list = normal_i2c, ++}; ++ ++static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data, ++ int count) ++{ ++ int status = 0; ++ ++ while (count) { ++ status = i2c_smbus_read_byte_data(client, command); ++ if (unlikely(status < 0)) { ++ break; ++ } ++ ++ *data = (u8)status; ++ data += 1; ++ command += 1; ++ count -= 1; ++ } ++ ++ return status; ++} ++ ++static struct as4610_psu_data *as4610_psu_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct as4610_psu_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ int status; ++ int present = 0; ++ ++ data->valid = 0; ++ data->status = 0; ++ dev_dbg(&client->dev, "Starting as4610 update\n"); ++ ++ /* Read psu status */ ++ status = accton_i2c_cpld_read(0x30, 0x11); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status); ++ goto exit; ++ } ++ else { ++ data->status = status; ++ } ++ ++ /* Read model name */ ++ memset(data->model_name, 0, sizeof(data->model_name)); ++ present = (data->status >> (data->index*2) & 0x1); ++ ++ if (present) { ++ int len = ARRAY_SIZE(data->model_name)-1; ++ ++ status = as4610_psu_read_data(client, 0x20, data->model_name, ++ ARRAY_SIZE(data->model_name)-1); ++ ++ if (status < 0) { ++ data->model_name[0] = '\0'; ++ dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); ++ goto exit; ++ } ++ else { ++ data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; ++ } ++ } ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init as4610_psu_init(void) ++{ ++ return i2c_add_driver(&as4610_psu_driver); ++} ++ ++static void __exit as4610_psu_exit(void) ++{ ++ i2c_del_driver(&as4610_psu_driver); ++} ++ ++module_init(as4610_psu_init); ++module_exit(as4610_psu_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_psu driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/hwmon/accton_i2c_cpld.c b/drivers/hwmon/accton_i2c_cpld.c +new file mode 100644 +index 0000000..0b9762e +--- /dev/null ++++ b/drivers/hwmon/accton_i2c_cpld.c +@@ -0,0 +1,285 @@ ++/* ++ * A hwmon driver for the accton_i2c_cpld ++ * ++ * Copyright (C) 2013 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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 ++ ++static LIST_HEAD(cpld_client_list); ++static struct mutex list_lock; ++ ++enum cpld_device_id { ++ as4610_30_cpld, ++ as4610_54_cpld ++}; ++ ++struct cpld_data { ++ enum cpld_device_id id; ++}; ++ ++struct cpld_client_node { ++ struct i2c_client *client; ++ struct list_head list; ++}; ++ ++/* Addresses scanned for accton_i2c_cpld ++ */ ++static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; ++ ++static u8 cpld_product_id_offset(enum cpld_device_id id) ++{ ++ switch (id) { ++ case as4610_30_cpld: ++ case as4610_54_cpld: ++ return 0x1; ++ } ++ ++ return 0; ++} ++ ++static int cpld_has_product_id(const struct i2c_device_id *dev_id) ++{ ++ return (dev_id->driver_data == as4610_30_cpld) || ++ (dev_id->driver_data == as4610_54_cpld); ++} ++ ++static ssize_t show_cpld_product_id(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ int val = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cpld_data *data = i2c_get_clientdata(client); ++ ++ val = i2c_smbus_read_byte_data(client, cpld_product_id_offset(data->id)); ++ if (val < 0) { ++ dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", client->addr, cpld_product_id_offset(data->id), val); ++ } ++ ++ return sprintf(buf, "%d\n", (val & 0xF)); ++} ++ ++static u8 cpld_version_offset(enum cpld_device_id id) ++{ ++ switch (id) { ++ case as4610_30_cpld: ++ case as4610_54_cpld: ++ return 0xB; ++ } ++ ++ return 0; ++} ++ ++static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ int val = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cpld_data *data = i2c_get_clientdata(client); ++ ++ val = i2c_smbus_read_byte_data(client, cpld_version_offset(data->id)); ++ if (val < 0) { ++ dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); ++ } ++ ++ return sprintf(buf, "%d\n", val); ++} ++ ++static void accton_i2c_cpld_add_client(struct i2c_client *client, enum cpld_device_id id) ++{ ++ struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); ++ struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); ++ ++ if (!node) { ++ dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); ++ return; ++ } ++ ++ if (!data) { ++ dev_dbg(&client->dev, "Can't allocate cpld_client_data (0x%x)\n", client->addr); ++ return; ++ } ++ ++ data->id = id; ++ i2c_set_clientdata(client, data); ++ node->client = client; ++ ++ mutex_lock(&list_lock); ++ list_add(&node->list, &cpld_client_list); ++ mutex_unlock(&list_lock); ++} ++ ++static void accton_i2c_cpld_remove_client(struct i2c_client *client) ++{ ++ struct list_head *list_node = NULL; ++ struct cpld_client_node *cpld_node = NULL; ++ int found = 0; ++ ++ mutex_lock(&list_lock); ++ ++ list_for_each(list_node, &cpld_client_list) ++ { ++ cpld_node = list_entry(list_node, struct cpld_client_node, list); ++ ++ if (cpld_node->client == client) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (found) { ++ list_del(list_node); ++ kfree(cpld_node); ++ } ++ ++ mutex_unlock(&list_lock); ++} ++ ++static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); ++static struct device_attribute pid = __ATTR(product_id, 0600, show_cpld_product_id, NULL); ++ ++static int accton_i2c_cpld_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); ++ status = -EIO; ++ goto exit; ++ } ++ ++ status = sysfs_create_file(&client->dev.kobj, &ver.attr); ++ if (status) { ++ goto exit; ++ } ++ ++ if (cpld_has_product_id(dev_id)) { ++ status = sysfs_create_file(&client->dev.kobj, &pid.attr); ++ if (status) { ++ goto exit; ++ } ++ } ++ ++ dev_info(&client->dev, "chip found\n"); ++ accton_i2c_cpld_add_client(client, (enum cpld_device_id)dev_id->driver_data); ++ ++ return 0; ++ ++exit: ++ return status; ++} ++ ++static int accton_i2c_cpld_remove(struct i2c_client *client) ++{ ++ sysfs_remove_file(&client->dev.kobj, &ver.attr); ++ accton_i2c_cpld_remove_client(client); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id accton_i2c_cpld_id[] = { ++ { "as4610_30_cpld", as4610_30_cpld }, ++ { "as4610_54_cpld", as4610_54_cpld }, ++ { /* LIST END */} ++}; ++MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); ++ ++static struct i2c_driver accton_i2c_cpld_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "accton_i2c_cpld", ++ }, ++ .probe = accton_i2c_cpld_probe, ++ .remove = accton_i2c_cpld_remove, ++ .id_table = accton_i2c_cpld_id, ++ .address_list = normal_i2c, ++}; ++ ++int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) ++{ ++ struct list_head *list_node = NULL; ++ struct cpld_client_node *cpld_node = NULL; ++ int ret = -EPERM; ++ ++ mutex_lock(&list_lock); ++ ++ list_for_each(list_node, &cpld_client_list) ++ { ++ cpld_node = list_entry(list_node, struct cpld_client_node, list); ++ ++ if (cpld_node->client->addr == cpld_addr) { ++ ret = i2c_smbus_read_byte_data(cpld_node->client, reg); ++ break; ++ } ++ } ++ ++ mutex_unlock(&list_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(accton_i2c_cpld_read); ++ ++int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) ++{ ++ struct list_head *list_node = NULL; ++ struct cpld_client_node *cpld_node = NULL; ++ int ret = -EIO; ++ ++ mutex_lock(&list_lock); ++ ++ list_for_each(list_node, &cpld_client_list) ++ { ++ cpld_node = list_entry(list_node, struct cpld_client_node, list); ++ ++ if (cpld_node->client->addr == cpld_addr) { ++ ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); ++ break; ++ } ++ } ++ ++ mutex_unlock(&list_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(accton_i2c_cpld_write); ++ ++static int __init accton_i2c_cpld_init(void) ++{ ++ mutex_init(&list_lock); ++ return i2c_add_driver(&accton_i2c_cpld_driver); ++} ++ ++static void __exit accton_i2c_cpld_exit(void) ++{ ++ i2c_del_driver(&accton_i2c_cpld_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("accton_i2c_cpld driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(accton_i2c_cpld_init); ++module_exit(accton_i2c_cpld_exit); ++ +diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c +index 8dfc678..b9eafcf 100644 +--- a/drivers/hwmon/lm77.c ++++ b/drivers/hwmon/lm77.c +@@ -36,7 +36,7 @@ + #include + + /* Addresses to scan */ +-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, ++static const unsigned short normal_i2c[] = { /*0x48,*/ 0x49, 0x4a, 0x4b, + I2C_CLIENT_END }; + + /* The LM77 registers */ +diff --git a/drivers/hwmon/ym2651y.c b/drivers/hwmon/ym2651y.c +new file mode 100644 +index 0000000..e761a74 +--- /dev/null ++++ b/drivers/hwmon/ym2651y.c +@@ -0,0 +1,651 @@ ++/* ++ * An hwmon driver for the 3Y Power YM-2651Y Power Module ++ * ++ * Copyright (C) Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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 ++ ++#define USE_I2C_BLOCK_READ 0 ++#if USE_I2C_BLOCK_READ ++ #define I2C_FUNCTION (I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA | \ ++ I2C_FUNC_SMBUS_I2C_BLOCK) ++#else ++ #define I2C_FUNCTION (I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA) ++#endif ++ ++#define MAX_FAN_DUTY_CYCLE 100 ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; ++ ++/* Each client has this additional data ++ */ ++struct ym2651y_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 capability; /* Register value */ ++ u16 status_word; /* Register value */ ++ u8 fan_fault; /* Register value */ ++ u8 over_temp; /* Register value */ ++ u16 v_out; /* Register value */ ++ u16 i_out; /* Register value */ ++ u16 p_out; /* Register value */ ++ u16 temp; /* Register value */ ++ u16 fan_speed; /* Register value */ ++ u16 fan_duty_cycle[2]; /* Register value */ ++ u8 pmbus_revision; /* Register value */ ++ u16 mfr_vin_min; /* Register value */ ++ u16 mfr_vin_max; /* Register value */ ++ u16 mfr_iin_max; /* Register value */ ++ u16 mfr_iout_max; /* Register value */ ++ u16 mfr_pin_max; /* Register value */ ++ u16 mfr_pout_max; /* Register value */ ++ u16 mfr_vout_min; /* Register value */ ++ u16 mfr_vout_max; /* Register value */ ++#if USE_I2C_BLOCK_READ ++ u8 fan_dir[4]; /* Register value */ ++ u8 mfr_id[10]; /* Register value */ ++ u8 mfr_model[10]; /* Register value */ ++ u8 mfr_revsion[3]; /* Register value */ ++#endif ++ ++}; ++ ++static ssize_t show_byte(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_word(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_linear(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_ascii(struct device *dev, struct device_attribute *da, ++ char *buf); ++static struct ym2651y_data *ym2651y_update_device(struct device *dev); ++static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count); ++static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); ++ ++enum ym2651y_sysfs_attributes { ++ PSU_POWER_ON = 0, ++ PSU_TEMP_FAULT, ++ PSU_POWER_GOOD, ++ PSU_FAN1_FAULT, ++ PSU_FAN_DIRECTION, ++ PSU_OVER_TEMP, ++ PSU_V_OUT, ++ PSU_I_OUT, ++ PSU_P_OUT, ++ PSU_TEMP1_INPUT, ++ PSU_FAN1_SPEED, ++ PSU_FAN1_DUTY_CYCLE, ++ PSU_PMBUS_REVISION, ++ PSU_MFR_ID, ++ PSU_MFR_MODEL, ++ PSU_MFR_REVISION, ++ PSU_MFR_VIN_MIN, ++ PSU_MFR_VIN_MAX, ++ PSU_MFR_VOUT_MIN, ++ PSU_MFR_VOUT_MAX, ++ PSU_MFR_IIN_MAX, ++ PSU_MFR_IOUT_MAX, ++ PSU_MFR_PIN_MAX, ++ PSU_MFR_POUT_MAX ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); ++static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); ++static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); ++static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); ++static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); ++static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); ++static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); ++static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); ++static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); ++static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); ++static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); ++static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); ++static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); ++static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); ++static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); ++#if USE_I2C_BLOCK_READ ++static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); ++static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); ++static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); ++static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); ++#endif ++ ++ ++static struct attribute *ym2651y_attributes[] = { ++ &sensor_dev_attr_psu_power_on.dev_attr.attr, ++ &sensor_dev_attr_psu_temp_fault.dev_attr.attr, ++ &sensor_dev_attr_psu_power_good.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, ++ &sensor_dev_attr_psu_over_temp.dev_attr.attr, ++ &sensor_dev_attr_psu_v_out.dev_attr.attr, ++ &sensor_dev_attr_psu_i_out.dev_attr.attr, ++ &sensor_dev_attr_psu_p_out.dev_attr.attr, ++ &sensor_dev_attr_psu_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, ++ &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, ++#if USE_I2C_BLOCK_READ ++ &sensor_dev_attr_psu_fan_dir.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_id.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_model.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, ++#endif ++ NULL ++}; ++ ++static ssize_t show_byte(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : ++ sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_word(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ u16 status = 0; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ ++ status = (data->status_word & 0x40) ? 0 : 1; ++ break; ++ case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ ++ status = (data->status_word & 0x4) >> 2; ++ break; ++ case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ ++ status = (data->status_word & 0x800) ? 0 : 1; ++ break; ++ } ++ ++ return sprintf(buf, "%d\n", status); ++} ++ ++static int two_complement_to_int(u16 data, u8 valid_bit, int mask) ++{ ++ u16 valid_data = data & mask; ++ bool is_negative = valid_data >> (valid_bit - 1); ++ ++ return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; ++} ++ ++static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; ++ long speed; ++ int error; ++ ++ error = kstrtol(buf, 10, &speed); ++ if (error) ++ return error; ++ ++ if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ data->fan_duty_cycle[nr] = speed; ++ ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t show_linear(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ u16 value = 0; ++ int exponent, mantissa; ++ int multiplier = 1000; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_V_OUT: ++ value = data->v_out; ++ break; ++ case PSU_I_OUT: ++ value = data->i_out; ++ break; ++ case PSU_P_OUT: ++ value = data->p_out; ++ break; ++ case PSU_TEMP1_INPUT: ++ value = data->temp; ++ break; ++ case PSU_FAN1_SPEED: ++ value = data->fan_speed; ++ multiplier = 1; ++ break; ++ case PSU_FAN1_DUTY_CYCLE: ++ value = data->fan_duty_cycle[0]; ++ multiplier = 1; ++ break; ++ case PSU_MFR_VIN_MIN: ++ value = data->mfr_vin_min; ++ break; ++ case PSU_MFR_VIN_MAX: ++ value = data->mfr_vin_max; ++ break; ++ case PSU_MFR_VOUT_MIN: ++ value = data->mfr_vout_min; ++ break; ++ case PSU_MFR_VOUT_MAX: ++ value = data->mfr_vout_max; ++ break; ++ case PSU_MFR_PIN_MAX: ++ value = data->mfr_pin_max; ++ break; ++ case PSU_MFR_POUT_MAX: ++ value = data->mfr_pout_max; ++ break; ++ case PSU_MFR_IOUT_MAX: ++ value = data->mfr_iout_max; ++ break; ++ case PSU_MFR_IIN_MAX: ++ value = data->mfr_iin_max; ++ break; ++ } ++ ++ exponent = two_complement_to_int(value >> 11, 5, 0x1f); ++ mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); ++ ++ return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : ++ sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); ++} ++ ++static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return sprintf(buf, "%d\n", data->fan_fault >> shift); ++} ++ ++static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return sprintf(buf, "%d\n", data->over_temp >> 7); ++} ++ ++#if USE_I2C_BLOCK_READ ++static ssize_t show_ascii(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ u8 *ptr = NULL; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_FAN_DIRECTION: /* psu_fan_dir */ ++ ptr = data->fan_dir; ++ break; ++ case PSU_MFR_ID: /* psu_mfr_id */ ++ ptr = data->mfr_id; ++ break; ++ case PSU_MFR_MODEL: /* psu_mfr_model */ ++ ptr = data->mfr_model; ++ break; ++ case PSU_MFR_REVISION: /* psu_mfr_revision */ ++ ptr = data->mfr_revsion; ++ break; ++ default: ++ return 0; ++ } ++ ++ return sprintf(buf, "%s\n", ptr); ++} ++#endif ++ ++static const struct attribute_group ym2651y_group = { ++ .attrs = ym2651y_attributes, ++}; ++ ++static int ym2651y_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct ym2651y_data *data; ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNCTION)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); ++ if (!data) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ dev_info(&client->dev, "chip found\n"); ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &ym2651y_group); ++exit_free: ++ kfree(data); ++exit: ++ ++ return status; ++} ++ ++static int ym2651y_remove(struct i2c_client *client) ++{ ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &ym2651y_group); ++ kfree(data); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ym2651y_id[] = { ++ { "ym2651", 0 }, ++ { "ym1921", 1 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ym2651y_id); ++ ++static struct i2c_driver ym2651y_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "ym2651", ++ }, ++ .probe = ym2651y_probe, ++ .remove = ym2651y_remove, ++ .id_table = ym2651y_id, ++ .address_list = normal_i2c, ++}; ++ ++static int ym2651y_read_byte(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++static int ym2651y_read_word(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_word_data(client, reg); ++} ++ ++static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) ++{ ++ return i2c_smbus_write_word_data(client, reg, value); ++} ++ ++#if USE_I2C_BLOCK_READ ++static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, ++ int data_len) ++{ ++ int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); ++ ++ if (unlikely(result < 0)) ++ goto abort; ++ if (unlikely(result != data_len)) { ++ result = -EIO; ++ goto abort; ++ } ++ ++ result = 0; ++ ++abort: ++ return result; ++} ++#endif ++ ++struct reg_data_byte { ++ u8 reg; ++ u8 *value; ++}; ++ ++struct reg_data_word { ++ u8 reg; ++ u16 *value; ++}; ++ ++static struct ym2651y_data *ym2651y_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ int i, status; ++ u8 command; ++ u8 fan_dir[5] = {0}; ++ struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, ++ {0x7d, &data->over_temp}, ++ {0x81, &data->fan_fault}, ++ {0x98, &data->pmbus_revision}}; ++ struct reg_data_word regs_word[] = { {0x79, &data->status_word}, ++ {0x8b, &data->v_out}, ++ {0x8c, &data->i_out}, ++ {0x96, &data->p_out}, ++ {0x8d, &data->temp}, ++ {0x3b, &(data->fan_duty_cycle[0])}, ++ {0x3c, &(data->fan_duty_cycle[1])}, ++ {0x90, &data->fan_speed}, ++ {0xa0, &data->mfr_vin_min}, ++ {0xa1, &data->mfr_vin_max}, ++ {0xa2, &data->mfr_iin_max}, ++ {0xa3, &data->mfr_pin_max}, ++ {0xa4, &data->mfr_vout_min}, ++ {0xa5, &data->mfr_vout_max}, ++ {0xa6, &data->mfr_iout_max}, ++ {0xa7, &data->mfr_pout_max}}; ++ ++ dev_dbg(&client->dev, "Starting ym2651 update\n"); ++ data->valid = 0; ++ ++ /* Read byte data */ ++ for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { ++ status = ym2651y_read_byte(client, regs_byte[i].reg); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", regs_byte[i].reg, status); ++ goto exit; ++ } ++ else { ++ *(regs_byte[i].value) = status; ++ } ++ } ++ ++ /* Read word data */ ++ for (i = 0; i < ARRAY_SIZE(regs_word); i++) { ++ status = ym2651y_read_word(client, regs_word[i].reg); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", regs_word[i].reg, status); ++ goto exit; ++ } ++ else { ++ *(regs_word[i].value) = status; ++ } ++ } ++ ++#if USE_I2C_BLOCK_READ ++ /* Read fan_direction */ ++ command = 0xC3; ++ status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); ++ data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; ++ ++ /* Read mfr_id */ ++ command = 0x99; ++ status = ym2651y_read_block(client, command, data->mfr_id, ++ ARRAY_SIZE(data->mfr_id)-1); ++ data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ /* Read mfr_model */ ++ command = 0x9a; ++ status = ym2651y_read_block(client, command, data->mfr_model, ++ ARRAY_SIZE(data->mfr_model)-1); ++ data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ /* Read mfr_revsion */ ++ command = 0x9b; ++ status = ym2651y_read_block(client, command, data->mfr_revsion, ++ ARRAY_SIZE(data->mfr_revsion)-1); ++ data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++#endif ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init ym2651y_init(void) ++{ ++ return i2c_add_driver(&ym2651y_driver); ++} ++ ++static void __exit ym2651y_exit(void) ++{ ++ i2c_del_driver(&ym2651y_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(ym2651y_init); ++module_exit(ym2651y_exit); ++ +diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig +index ff203a4..97d4d54 100644 +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -387,6 +387,13 @@ config LEDS_RENESAS_TPU + pin function. The latter to support brightness control. + Brightness control is supported but hardware blinking is not. + ++config LEDS_ACCTON_AS4610 ++ tristate "LED support for the Accton as4610" ++ depends on LEDS_CLASS && SENSORS_ACCTON_I2C_CPLD ++ help ++ This option enables support for the LEDs on the Accton as4610. ++ Say Y to enable LEDs on the Accton as4610. ++ + config LEDS_TRIGGERS + bool "LED Trigger support" + depends on LEDS_CLASS +diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile +index e4f6bf5..db2dab8 100644 +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o + obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o + obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o + obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o ++obj-$(CONFIG_LEDS_ACCTON_AS4610) += leds-accton_as4610.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o +diff --git a/drivers/leds/leds-accton_as4610.c b/drivers/leds/leds-accton_as4610.c +new file mode 100644 +index 0000000..0c4b535 +--- /dev/null ++++ b/drivers/leds/leds-accton_as4610.c +@@ -0,0 +1,678 @@ ++/* ++ * A LED driver for the accton_as4610_led ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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. ++ */ ++ ++/*#define DEBUG*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern int accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg); ++extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++ ++extern void led_classdev_unregister(struct led_classdev *led_cdev); ++extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); ++ ++#define DRVNAME "as4610_led" ++ ++struct as4610_led_data { ++ struct platform_device *pdev; ++ struct mutex update_lock; ++ char valid; /* != 0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ int led_map; ++ u8 reg_val[5]; /* Register value, 0 = (0x1A) Blinking function ++ 1 = (0x30) 7-seg 2 ++ 2 = (0x31) 7-seg 1 ++ 3 = (0x32) SYS/PRI/PSU1-2 LED ++ 4 = (0x33) STK1-2/Fan/PoE/Alarm LED */ ++}; ++ ++static struct as4610_led_data *ledctl = NULL; ++ ++/* LED related data ++ */ ++#define LED_7SEG_REG_MASK 0x0F ++#define LED_7SEG_POINT_REG_MASK 0x10 ++ ++#define LED_NORMAL_MASK 0x03 ++#define LED_NORMAL_GREEN_VALUE 0x02 ++#define LED_NORMAL_AMBER_VALUE 0x01 ++#define LED_NORMAL_OFF_VALUE 0x00 ++ ++#define LED_TYPE_SYS_REG_MASK 0xC0 ++#define LED_MODE_SYS_BLINK_MASK 0x80 ++ ++#define LED_TYPE_PRI_REG_MASK 0x30 ++#define LED_MODE_PRI_BLINK_MASK 0x40 ++ ++#define LED_TYPE_PSU1_REG_MASK 0x0C ++#define LED_MODE_PSU1_BLINK_MASK 0x20 ++ ++#define LED_TYPE_PSU2_REG_MASK 0x03 ++#define LED_MODE_PSU2_BLINK_MASK 0x10 ++ ++#define LED_TYPE_STK1_REG_MASK 0xC0 ++#define LED_MODE_STK1_BLINK_MASK 0x08 ++ ++#define LED_TYPE_STK2_REG_MASK 0x30 ++#define LED_MODE_STK2_BLINK_MASK 0x04 ++ ++#define LED_TYPE_FAN_REG_MASK 0x0C ++#define LED_MODE_FAN_BLINK_MASK 0x02 ++ ++#define LED_TYPE_POE_ALARM_REG_MASK 0x03 ++#define LED_MODE_POE_ALARM_BLINK_MASK 0x01 ++ ++static const u8 led_reg[] = { ++ 0x1A, /* Blinking function */ ++ 0x30, /* 7-seg 1 */ ++ 0x31, /* 7-seg 2 */ ++ 0x32, /* SYS/PRI/PSU1-2 LED */ ++ 0x33, /* STK1-2/Fan/PoE/Alarm LED */ ++}; ++ ++enum led_type { ++ LED_TYPE_SYS, ++ LED_TYPE_PRI, ++ LED_TYPE_PSU1, ++ LED_TYPE_PSU2, ++ LED_TYPE_STK1, ++ LED_TYPE_STK2, ++ LED_TYPE_7SEG_TENS, ++ LED_TYPE_7SEG_TENS_POINT, ++ LED_TYPE_7SEG_DIGITS, ++ LED_TYPE_7SEG_DIGITS_POINT, ++ LED_TYPE_FAN, ++ LED_TYPE_POE, ++ LED_TYPE_ALARM, ++ NUM_OF_LED ++}; ++ ++#define AS4610_COMMON_LED_MAP (BIT(LED_TYPE_SYS) | BIT(LED_TYPE_PRI) | BIT(LED_TYPE_PSU1) | \ ++ BIT(LED_TYPE_PSU2)| BIT(LED_TYPE_STK1)| BIT(LED_TYPE_STK2)) ++#define AS4610_NPOE_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_7SEG_TENS) | \ ++ BIT(LED_TYPE_7SEG_TENS_POINT) | BIT(LED_TYPE_7SEG_DIGITS) | \ ++ BIT(LED_TYPE_7SEG_DIGITS_POINT)) ++#define AS4610_POE_LED_MAP (AS4610_NPOE_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_POE)) ++#define AS4610_54T_B_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_ALARM)) ++ ++static int as4610_ledmaps[] = { ++ [PID_AS4610_30T] = AS4610_NPOE_LED_MAP, ++ [PID_AS4610_30P] = AS4610_POE_LED_MAP, ++ [PID_AS4610_54T] = AS4610_NPOE_LED_MAP, ++ [PID_AS4610_54P] = AS4610_POE_LED_MAP, ++ [PID_AS4610_54T_B] = AS4610_54T_B_LED_MAP, ++ [PID_RESERVED] = 0, ++}; ++ ++enum led_light_mode { ++ LED_MODE_OFF = 0, ++ LED_MODE_GREEN, ++ LED_MODE_GREEN_BLINK, ++ LED_MODE_AMBER, ++ LED_MODE_AMBER_BLINK, ++ LED_MODE_RED, ++ LED_MODE_RED_BLINK, ++ LED_MODE_BLUE, ++ LED_MODE_BLUE_BLINK, ++ LED_MODE_AUTO, ++ LED_MODE_AUTO_BLINKING, ++ LED_MODE_UNKNOWN, ++ LED_MODE_SEVEN_SEGMENT_MAX = 9, ++}; ++ ++static int as4610_led_read_value(u8 reg) ++{ ++ return accton_i2c_cpld_read(0x30, reg); ++} ++ ++static int as4610_led_write_value(u8 reg, u8 value) ++{ ++ return accton_i2c_cpld_write(0x30, reg, value); ++} ++ ++static void as4610_led_update(void) ++{ ++ mutex_lock(&ledctl->update_lock); ++ ++ if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) ++ || !ledctl->valid) { ++ int i; ++ ++ dev_dbg(&ledctl->pdev->dev, "Starting as4610_led update\n"); ++ ++ /* Update LED data ++ */ ++ for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { ++ int status = as4610_led_read_value(led_reg[i]); ++ ++ if (status < 0) { ++ ledctl->valid = 0; ++ dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); ++ goto exit; ++ } ++ else ++ { ++ ledctl->reg_val[i] = status; ++ } ++ } ++ ++ ledctl->last_updated = jiffies; ++ ledctl->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&ledctl->update_lock); ++} ++ ++static enum led_brightness seven_segment_get(struct led_classdev *cdev, u8 reg_id) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[reg_id] & LED_7SEG_REG_MASK); ++} ++ ++static void seven_segment_set(struct led_classdev *cdev, enum led_brightness mode, u8 reg_id) ++{ ++ if (mode > cdev->max_brightness) { ++ return; ++ } ++ ++ ledctl->reg_val[reg_id] &= 0xF0; ++ ledctl->reg_val[reg_id] |= mode; ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness seven_segment_digits_get(struct led_classdev *cdev) ++{ ++ return seven_segment_get(cdev, 1); ++} ++ ++static void seven_segment_digits_set(struct led_classdev *cdev, enum led_brightness mode) ++{ ++ seven_segment_set(cdev, mode, 1); ++} ++ ++static enum led_brightness seven_segment_tens_get(struct led_classdev *cdev) ++{ ++ return seven_segment_get(cdev, 2); ++} ++ ++static void seven_segment_tens_set(struct led_classdev *cdev, enum led_brightness mode) ++{ ++ seven_segment_set(cdev, mode, 2); ++} ++ ++static enum led_brightness seven_segment_point_get(struct led_classdev *cdev, u8 reg_id) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[reg_id] & LED_7SEG_POINT_REG_MASK) ? LED_MODE_GREEN : LED_MODE_OFF; ++} ++ ++static void seven_segment_point_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 reg_id) ++{ ++ /* Validate brightness */ ++ if ((int)mode < LED_MODE_OFF || mode > cdev->max_brightness) { ++ return; ++ } ++ ++ if ((int)mode == (int)LED_MODE_OFF) { ++ ledctl->reg_val[reg_id] &= ~LED_7SEG_POINT_REG_MASK; ++ } ++ else { /* LED_MODE_GREEN */ ++ ledctl->reg_val[reg_id] |= LED_7SEG_POINT_REG_MASK; ++ } ++ ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness seven_segment_tens_point_get(struct led_classdev *cdev) ++{ ++ return seven_segment_point_get(cdev, 2); ++} ++ ++static void seven_segment_tens_point_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ seven_segment_point_set(cdev, mode, 2); ++} ++ ++static enum led_brightness seven_segment_digits_point_get(struct led_classdev *cdev) ++{ ++ return seven_segment_point_get(cdev, 1); ++} ++ ++static void seven_segment_digits_point_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ seven_segment_point_set(cdev, mode, 1); ++} ++ ++static u8 led_is_blinking_mode(enum led_brightness mode) ++{ ++ return ((int)mode == (int)LED_MODE_GREEN_BLINK || ++ (int)mode == (int)LED_MODE_AMBER_BLINK || ++ (int)mode == (int)LED_MODE_AUTO_BLINKING); ++} ++ ++static enum led_brightness as4610_led_auto_get(u8 blink_mask) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[0] & blink_mask) ? LED_MODE_AUTO_BLINKING : LED_MODE_AUTO; ++} ++ ++static void as4610_led_auto_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 blink_mask) ++{ ++ /* Validate brightness */ ++ if ((int)mode < (int)LED_MODE_AUTO || mode > cdev->max_brightness) { ++ return; ++ } ++ ++ /* Set blinking */ ++ if (led_is_blinking_mode(mode)) { ++ ledctl->reg_val[0] |= blink_mask; ++ } ++ else { ++ ledctl->reg_val[0] &= ~blink_mask; ++ } ++ as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); ++} ++ ++static enum led_brightness as4610_led_psu1_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_PSU1_BLINK_MASK); ++} ++ ++static void as4610_led_psu1_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(cdev, mode, LED_MODE_PSU1_BLINK_MASK); ++} ++ ++static enum led_brightness as4610_led_psu2_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_PSU2_BLINK_MASK); ++} ++ ++static void as4610_led_psu2_set(struct led_classdev *led_cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(led_cdev, mode, LED_MODE_PSU2_BLINK_MASK); ++} ++ ++static enum led_brightness as4610_led_fan_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_FAN_BLINK_MASK); ++} ++ ++static void as4610_led_fan_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(cdev, mode, LED_MODE_FAN_BLINK_MASK); ++} ++ ++static u8 led_normal_light_mode_to_reg_val(enum led_brightness mode) ++{ ++ if (led_is_blinking_mode(mode)) { ++ mode -= 1; /* convert blinking mode to non-blinking mode */ ++ } ++ ++ if ((int)mode == (int)LED_MODE_GREEN) { ++ return LED_NORMAL_GREEN_VALUE; ++ } ++ else if ((int)mode == (int)LED_MODE_AMBER) { ++ return LED_NORMAL_AMBER_VALUE; ++ } ++ ++ return LED_NORMAL_OFF_VALUE; ++} ++ ++static enum led_brightness led_normal_reg_val_to_light_mode(u8 reg_val) ++{ ++ reg_val &= LED_NORMAL_MASK; ++ ++ if (reg_val & LED_NORMAL_GREEN_VALUE) { ++ return LED_MODE_GREEN; ++ } ++ else if (reg_val & LED_NORMAL_AMBER_VALUE) { ++ return LED_MODE_AMBER; ++ } ++ ++ return LED_MODE_OFF; ++} ++ ++static void as4610_led_normal_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 blink_mask, u8 reg_id, u8 reg_mask, u8 shift) ++{ ++ /* Validate brightness */ ++ if (mode > cdev->max_brightness) { ++ return; ++ } ++ ++ /* Set blinking */ ++ if (led_is_blinking_mode(mode)) { ++ ledctl->reg_val[0] |= blink_mask; ++ } ++ else { ++ ledctl->reg_val[0] &= ~blink_mask; ++ } ++ as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); ++ ++ /* Set color */ ++ ledctl->reg_val[reg_id] &= ~reg_mask; ++ ledctl->reg_val[reg_id] |= (led_normal_light_mode_to_reg_val(mode) << shift); ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness as4610_led_normal_get(u8 reg_id, u8 blink_mask, u8 shift) ++{ ++ u8 blinking = 0; ++ enum led_brightness mode; ++ ++ as4610_led_update(); ++ ++ mode = led_normal_reg_val_to_light_mode(ledctl->reg_val[reg_id] >> shift); ++ if ((int)mode == (int)LED_MODE_OFF) { ++ return mode; ++ } ++ ++ /* Checking blinking */ ++ if (ledctl->reg_val[0] & blink_mask) { ++ blinking = 1; ++ } ++ ++ return blinking ? (mode+1) : mode; ++} ++ ++static void as4610_led_sys_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_SYS_BLINK_MASK, ++ 3, LED_TYPE_SYS_REG_MASK, 6); ++} ++ ++static enum led_brightness as4610_led_sys_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(3, LED_MODE_SYS_BLINK_MASK, 6); ++} ++ ++static void as4610_led_pri_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_PRI_BLINK_MASK, ++ 3, LED_TYPE_PRI_REG_MASK, 4); ++} ++ ++static enum led_brightness as4610_led_pri_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(3, LED_MODE_PRI_BLINK_MASK, 4); ++} ++ ++static void as4610_led_poe_alarm_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_POE_ALARM_BLINK_MASK, ++ 4, LED_TYPE_POE_ALARM_REG_MASK, 0); ++} ++ ++static enum led_brightness as4610_led_poe_alarm_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_POE_ALARM_BLINK_MASK, 0); ++} ++ ++static void as4610_led_stk1_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_STK1_BLINK_MASK, ++ 4, LED_TYPE_STK1_REG_MASK, 6); ++} ++ ++static enum led_brightness as4610_led_stk1_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_STK1_BLINK_MASK, 6); ++} ++ ++static void as4610_led_stk2_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_STK2_BLINK_MASK, ++ 4, LED_TYPE_STK2_REG_MASK, 4); ++} ++ ++static enum led_brightness as4610_led_stk2_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_STK2_BLINK_MASK, 4); ++} ++ ++static struct led_classdev as4610_leds[] = { ++ [LED_TYPE_SYS] = { ++ .name = "as4610::sys", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_sys_set, ++ .brightness_get = as4610_led_sys_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_PRI] = { ++ .name = "as4610::pri", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_pri_set, ++ .brightness_get = as4610_led_pri_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_PSU1] = { ++ .name = "as4610::psu1", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_psu1_set, ++ .brightness_get = as4610_led_psu1_get, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_PSU2] = { ++ .name = "as4610::psu2", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_psu2_set, ++ .brightness_get = as4610_led_psu2_get, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_STK1] = { ++ .name = "as4610::stk1", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_stk1_set, ++ .brightness_get = as4610_led_stk1_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_STK2] = { ++ .name = "as4610::stk2", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_stk2_set, ++ .brightness_get = as4610_led_stk2_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_7SEG_TENS] = { ++ .name = "as4610::7seg_tens", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_tens_set, ++ .brightness_get = seven_segment_tens_get, ++ .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, ++ }, ++ [LED_TYPE_7SEG_TENS_POINT] = { ++ .name = "as4610::7seg_tens_point", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_tens_point_set, ++ .brightness_get = seven_segment_tens_point_get, ++ .max_brightness = LED_MODE_GREEN, ++ }, ++ [LED_TYPE_7SEG_DIGITS] = { ++ .name = "as4610::7seg_digits", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_digits_set, ++ .brightness_get = seven_segment_digits_get, ++ .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, ++ }, ++ [LED_TYPE_7SEG_DIGITS_POINT] = { ++ .name = "as4610::7seg_digits_point", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_digits_point_set, ++ .brightness_get = seven_segment_digits_point_get, ++ .max_brightness = LED_MODE_GREEN, ++ }, ++ [LED_TYPE_FAN] = { ++ .name = "as4610::fan", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_fan_set, ++ .brightness_get = as4610_led_fan_get, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_POE] = { ++ .name = "as4610::poe", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_poe_alarm_set, ++ .brightness_get = as4610_led_poe_alarm_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_ALARM] = { ++ .name = "as4610::alarm", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_poe_alarm_set, ++ .brightness_get = as4610_led_poe_alarm_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++}; ++ ++static int as4610_led_probe(struct platform_device *pdev) ++{ ++ int ret = 0, i; ++ ++ for (i = 0; i < NUM_OF_LED; i++) { ++ if (!(ledctl->led_map & BIT(i))) { ++ continue; ++ } ++ ++ ret = led_classdev_register(&pdev->dev, &as4610_leds[i]); ++ if (ret < 0) { ++ goto error; ++ } ++ } ++ ++ return 0; ++ ++error: ++ for (i = i-1; i >= 0; i--) { ++ /* only unregister the LEDs that were successfully registered */ ++ if (!(ledctl->led_map & BIT(i))) { ++ continue; ++ } ++ ++ led_classdev_unregister(&as4610_leds[i]); ++ } ++ ++ return ret; ++} ++ ++static int as4610_led_remove(struct platform_device *pdev) ++{ ++ int i; ++ ++ for (i = 0; i < NUM_OF_LED; i++) { ++ if (!(ledctl->led_map & BIT(i))) { ++ continue; ++ } ++ ++ led_classdev_unregister(&as4610_leds[i]); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver as4610_led_driver = { ++ .probe = as4610_led_probe, ++ .remove = as4610_led_remove, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init as4610_led_init(void) ++{ ++ int ret, pid; ++ ++ if (as4610_product_id() == PID_UNKNOWN) { ++ return -ENODEV; ++ } ++ ++ ret = platform_driver_register(&as4610_led_driver); ++ if (ret < 0) { ++ goto exit; ++ } ++ ++ ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL); ++ if (!ledctl) { ++ ret = -ENOMEM; ++ platform_driver_unregister(&as4610_led_driver); ++ goto exit; ++ } ++ ++ pid = as4610_product_id(); ++ if (pid == PID_UNKNOWN) { ++ return -ENODEV; ++ } ++ ++ ledctl->led_map = as4610_ledmaps[pid]; ++ mutex_init(&ledctl->update_lock); ++ ++ ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); ++ if (IS_ERR(ledctl->pdev)) { ++ ret = PTR_ERR(ledctl->pdev); ++ platform_driver_unregister(&as4610_led_driver); ++ kfree(ledctl); ++ goto exit; ++ } ++ ++exit: ++ return ret; ++} ++ ++static void __exit as4610_led_exit(void) ++{ ++ if (!ledctl) { ++ return; ++ } ++ ++ platform_device_unregister(ledctl->pdev); ++ platform_driver_unregister(&as4610_led_driver); ++ kfree(ledctl); ++} ++ ++late_initcall(as4610_led_init); ++module_exit(as4610_led_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_led driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig +index 7c7b208..1c62b33 100644 +--- a/drivers/misc/eeprom/Kconfig ++++ b/drivers/misc/eeprom/Kconfig +@@ -117,5 +117,14 @@ config EEPROM_SFF_8436 + + This driver can also be built as a module. If so, the module + will be called sff_8436. ++ ++config EEPROM_ACCTON_AS4610_SFP ++ tristate "Accton as4610 sfp" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 sfp. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_sfp. + + endmenu +diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile +index 9edd559..12f7cae 100644 +--- a/drivers/misc/eeprom/Makefile ++++ b/drivers/misc/eeprom/Makefile +@@ -7,3 +7,4 @@ 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 ++obj-$(CONFIG_EEPROM_ACCTON_AS4610_SFP) += accton_as4610_sfp.o +diff --git a/drivers/misc/eeprom/accton_as4610_sfp.c b/drivers/misc/eeprom/accton_as4610_sfp.c +new file mode 100644 +index 0000000..39c17ec +--- /dev/null ++++ b/drivers/misc/eeprom/accton_as4610_sfp.c +@@ -0,0 +1,1269 @@ ++/* ++ * SFP driver for accton as4610 sfp ++ * ++ * Copyright (C) Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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 ++ ++#define DRIVER_NAME "as4610_sfp" /* Platform dependent */ ++ ++#define DEBUG_MODE 0 ++ ++#if (DEBUG_MODE == 1) ++ #define DEBUG_PRINT(fmt, args...) \ ++ printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) ++#else ++ #define DEBUG_PRINT(fmt, args...) ++#endif ++ ++#define NUM_OF_SFP_PORT 32 ++#define EEPROM_NAME "sfp_eeprom" ++#define EEPROM_SIZE 256 /* 256 byte eeprom */ ++#define BIT_INDEX(i) (1ULL << (i)) ++#define USE_I2C_BLOCK_READ 0 /* Platform dependent */ ++#define I2C_RW_RETRY_COUNT 3 ++#define I2C_RW_RETRY_INTERVAL 100 /* ms */ ++ ++#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) ++#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) ++ ++#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 ++#define SFF8024_DEVICE_ID_SFP 0x3 ++#define SFF8024_DEVICE_ID_QSFP 0xC ++#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD ++#define SFF8024_DEVICE_ID_QSFP28 0x11 ++ ++#define SFF8472_DIAG_MON_TYPE_ADDR 92 ++#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 ++#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 ++#define SFF8472_10G_BASE_MASK 0xF0 ++ ++#define SFF8436_RX_LOS_ADDR 3 ++#define SFF8436_TX_FAULT_ADDR 4 ++#define SFF8436_TX_DISABLE_ADDR 86 ++ ++static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); ++static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; ++static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); ++static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); ++extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++ ++enum sfp_sysfs_attributes { ++ PRESENT, ++ PRESENT_ALL, ++ PORT_NUMBER, ++ PORT_TYPE, ++ DDM_IMPLEMENTED, ++ TX_FAULT, ++ TX_FAULT1, ++ TX_FAULT2, ++ TX_FAULT3, ++ TX_FAULT4, ++ TX_DISABLE, ++ TX_DISABLE1, ++ TX_DISABLE2, ++ TX_DISABLE3, ++ TX_DISABLE4, ++ RX_LOS, ++ RX_LOS1, ++ RX_LOS2, ++ RX_LOS3, ++ RX_LOS4, ++ RX_LOS_ALL ++}; ++ ++/* SFP/QSFP common attributes for sysfs */ ++static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); ++static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); ++static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); ++static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); ++static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); ++ ++/* QSFP attributes for sysfs */ ++static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); ++static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); ++static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); ++static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); ++static struct attribute *qsfp_attributes[] = { ++ &sensor_dev_attr_sfp_port_number.dev_attr.attr, ++ &sensor_dev_attr_sfp_port_type.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, ++ NULL ++}; ++ ++/* SFP msa attributes for sysfs */ ++static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); ++static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); ++static struct attribute *sfp_msa_attributes[] = { ++ &sensor_dev_attr_sfp_port_number.dev_attr.attr, ++ &sensor_dev_attr_sfp_port_type.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, ++ &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, ++ NULL ++}; ++ ++/* SFP ddm attributes for sysfs */ ++static struct attribute *sfp_ddm_attributes[] = { ++ NULL ++}; ++ ++/* Platform dependent +++ */ ++enum port_numbers { ++as4610_sfp1, /* Port 25 for as4610_30, Port 49 for as4610_54 */ ++as4610_sfp2, /* Port 26 for as4610_30, Port 50 for as4610_54 */ ++as4610_sfp3, /* Port 27 for as4610_30, Port 51 for as4610_54 */ ++as4610_sfp4, /* Port 28 for as4610_30, Port 52 for as4610_54 */ ++as4610_sfp5, /* Port 29 for as4610_30, Port 53 for as4610_54 */ ++as4610_sfp6, /* Port 30 for as4610_30, Port 54 for as4610_54 */ ++}; ++ ++static const struct i2c_device_id sfp_device_id[] = { ++{"as4610_sfp1", as4610_sfp1}, ++{"as4610_sfp2", as4610_sfp2}, ++{"as4610_sfp3", as4610_sfp3}, ++{"as4610_sfp4", as4610_sfp4}, ++{"as4610_sfp5", as4610_sfp5}, ++{"as4610_sfp6", as4610_sfp6}, ++{ /* LIST END */ } ++}; ++MODULE_DEVICE_TABLE(i2c, sfp_device_id); ++/* Platform dependent --- */ ++ ++/* ++ * list of valid port types ++ * note OOM_PORT_TYPE_NOT_PRESENT to indicate no ++ * module is present in this port ++ */ ++typedef enum oom_driver_port_type_e { ++ OOM_DRIVER_PORT_TYPE_INVALID, ++ OOM_DRIVER_PORT_TYPE_NOT_PRESENT, ++ OOM_DRIVER_PORT_TYPE_SFP, ++ OOM_DRIVER_PORT_TYPE_SFP_PLUS, ++ OOM_DRIVER_PORT_TYPE_QSFP, ++ OOM_DRIVER_PORT_TYPE_QSFP_PLUS, ++ OOM_DRIVER_PORT_TYPE_QSFP28 ++} oom_driver_port_type_t; ++ ++enum driver_type_e { ++ DRIVER_TYPE_SFP_MSA, ++ DRIVER_TYPE_SFP_DDM, ++ DRIVER_TYPE_QSFP ++}; ++ ++/* Each client has this additional data ++ */ ++struct eeprom_data { ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ struct bin_attribute bin; /* eeprom data */ ++}; ++ ++struct sfp_msa_data { ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u64 status[6]; /* bit0:port0, bit1:port1 and so on */ ++ /* index 0 => tx_fail ++ 1 => tx_disable ++ 2 => rx_loss ++ 3 => device id ++ 4 => 10G Ethernet Compliance Codes ++ to distinguish SFP or SFP+ ++ 5 => DIAGNOSTIC MONITORING TYPE */ ++ struct eeprom_data eeprom; ++}; ++ ++struct sfp_ddm_data { ++ struct eeprom_data eeprom; ++}; ++ ++struct qsfp_data { ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 status[3]; /* bit0:port0, bit1:port1 and so on */ ++ /* index 0 => tx_fail ++ 1 => tx_disable ++ 2 => rx_loss */ ++ ++ u8 device_id; ++ struct eeprom_data eeprom; ++}; ++ ++struct sfp_port_data { ++ struct mutex update_lock; ++ enum driver_type_e driver_type; ++ int port; /* CPLD port index */ ++ oom_driver_port_type_t port_type; ++ u64 present; /* present status, bit0:port0, bit1:port1 and so on */ ++ ++ struct sfp_msa_data *msa; ++ struct sfp_ddm_data *ddm; ++ struct qsfp_data *qsfp; ++ ++ struct i2c_client *client; ++}; ++ ++static ssize_t show_port_number(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ return sprintf(buf, "sfp %d\n", data->port); ++} ++ ++/* Platform dependent +++ */ ++static struct sfp_port_data *sfp_update_present(struct i2c_client *client) ++{ ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int i = 0; ++ int status = -1; ++ u8 regs[] = {0x2, 0x3, 0x21}; ++ ++ DEBUG_PRINT("Starting sfp present status update"); ++ mutex_lock(&data->update_lock); ++ ++ /* Read present status of port 49~54 */ ++ data->present = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ status = accton_i2c_cpld_read(0x30, regs[i]); ++ ++ if (status < 0) { ++ DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); ++ goto exit; ++ } ++ ++ DEBUG_PRINT("Present status = 0x%lx", data->present); ++ switch (i) { ++ case 0: ++ data->present |= (status & BIT_INDEX(6)) >> 6; /* port 25/49 */ ++ data->present |= (status & BIT_INDEX(2)) >> 1; /* port 26/50 */ ++ break; ++ case 1: ++ data->present |= (status & BIT_INDEX(6)) >> 4; /* port 27/51 */ ++ data->present |= (status & BIT_INDEX(2)) << 1; /* port 28/52 */ ++ break; ++ case 2: ++ data->present |= (status & BIT_INDEX(0)) << 4; /* port 29/53 */ ++ data->present |= (status & BIT_INDEX(4)) << 1; /* port 30/54 */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ DEBUG_PRINT("Present status = 0x%lx", data->present); ++exit: ++ mutex_unlock(&data->update_lock); ++ return (status < 0) ? ERR_PTR(status) : data; ++} ++ ++static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int i = 0; ++ int status = -1; ++ u8 regs[] = {0x2, 0x3, 0x21}; ++ ++ if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { ++ return data; ++ } ++ ++ DEBUG_PRINT("Starting as4610 sfp tx rx status update"); ++ mutex_lock(&data->update_lock); ++ data->msa->valid = 0; ++ memset(data->msa->status, 0, sizeof(data->msa->status)); ++ ++ /* Read status of port 49~52(SFP port) */ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ status = accton_i2c_cpld_read(0x30, regs[i]); ++ ++ if (status < 0) { ++ DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); ++ goto exit; ++ } ++ ++ DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", ++ data->msa->status[0], data->msa->status[1], data->msa->status[2]); ++ switch (i) { ++ case 0: ++ /* port 25/49 */ ++ data->msa->status[0] |= (status & BIT_INDEX(5)) >> 5; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(4)) >> 4; /* rx_los */ ++ /* port 26/50 */ ++ data->msa->status[0] |= (status & BIT_INDEX(1)) << 0; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(0)) << 1; /* rx_los */ ++ break; ++ case 1: ++ /* port 27/51 */ ++ data->msa->status[0] |= (status & BIT_INDEX(5)) >> 3; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(4)) >> 2; /* rx_los */ ++ /* port 28/52 */ ++ data->msa->status[0] |= (status & BIT_INDEX(1)) << 1; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(0)) << 2; /* rx_los */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", ++ data->msa->status[0], data->msa->status[1], data->msa->status[2]); ++ data->msa->valid = 1; ++ data->msa->last_updated = jiffies; ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return data; ++} ++/* Platform dependent --- */ ++ ++static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ if (data->driver_type == DRIVER_TYPE_QSFP) { ++ return qsfp_set_tx_disable(dev, da, buf, count); ++ } ++ ++ return 0; ++} ++ ++static int sfp_is_port_present(struct i2c_client *client, int port) ++{ ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ data = sfp_update_present(client); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ return (data->present & BIT_INDEX(data->port)) ? 1 : 0; /* Platform dependent */ ++} ++ ++/* Platform dependent +++ */ ++static ssize_t show_present(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ if (PRESENT_ALL == attr->index) { ++ struct sfp_port_data *data = sfp_update_present(client); ++ ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ /* Return values 25/49 -> 30/54 in order */ ++ return sprintf(buf, "%.2x\n", (u8)(data->present)); ++ } ++ else { ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int present = sfp_is_port_present(client, data->port); ++ ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ /* PRESENT */ ++ return sprintf(buf, "%d\n", present); ++ } ++} ++/* Platform dependent --- */ ++ ++static struct sfp_port_data *sfp_update_port_type(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ u8 buf = 0; ++ int status; ++ ++ mutex_lock(&data->update_lock); ++ ++ switch (data->driver_type) { ++ case DRIVER_TYPE_SFP_MSA: ++ { ++ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ if (buf != SFF8024_DEVICE_ID_SFP) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); ++ data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; ++ break; ++ } ++ case DRIVER_TYPE_QSFP: ++ { ++ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); ++ switch (buf) { ++ case SFF8024_DEVICE_ID_QSFP: ++ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; ++ break; ++ case SFF8024_DEVICE_ID_QSFP_PLUS: ++ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; ++ break; ++ case SFF8024_DEVICE_ID_QSFP28: ++ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; ++ break; ++ default: ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ break; ++ } ++ default: ++ break; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return data; ++} ++ ++static ssize_t show_port_type(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int present = sfp_is_port_present(client, data->port); ++ ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (!present) { ++ return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); ++ } ++ ++ sfp_update_port_type(dev); ++ return sprintf(buf, "%d\n", data->port_type); ++} ++ ++static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int i, status = -1; ++ u8 buf = 0; ++ u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; ++ ++ if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { ++ return data; ++ } ++ ++ DEBUG_PRINT("Starting sfp tx rx status update"); ++ mutex_lock(&data->update_lock); ++ data->qsfp->valid = 0; ++ memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); ++ ++ /* Notify device to update tx fault/ tx disable/ rx los status */ ++ for (i = 0; i < ARRAY_SIZE(reg); i++) { ++ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ goto exit; ++ } ++ } ++ msleep(200); ++ ++ /* Read actual tx fault/ tx disable/ rx los status */ ++ for (i = 0; i < ARRAY_SIZE(reg); i++) { ++ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ goto exit; ++ } ++ ++ DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); ++ data->qsfp->status[i] = (buf & 0xF); ++ } ++ ++ data->qsfp->valid = 1; ++ data->qsfp->last_updated = jiffies; ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return (status < 0) ? ERR_PTR(status) : data; ++} ++ ++static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int present; ++ u8 val = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ present = sfp_is_port_present(client, data->port); ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (present == 0) { ++ /* port is not present */ ++ return -ENXIO; ++ } ++ ++ data = qsfp_update_tx_rx_status(dev); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ switch (attr->index) { ++ case TX_FAULT: ++ val = !!(data->qsfp->status[2] & 0xF); ++ break; ++ case TX_FAULT1: ++ case TX_FAULT2: ++ case TX_FAULT3: ++ case TX_FAULT4: ++ val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); ++ break; ++ case TX_DISABLE: ++ val = data->qsfp->status[1] & 0xF; ++ break; ++ case TX_DISABLE1: ++ case TX_DISABLE2: ++ case TX_DISABLE3: ++ case TX_DISABLE4: ++ val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); ++ break; ++ case RX_LOS: ++ val = !!(data->qsfp->status[0] & 0xF); ++ break; ++ case RX_LOS1: ++ case RX_LOS2: ++ case RX_LOS3: ++ case RX_LOS4: ++ val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); ++ break; ++ default: ++ break; ++ } ++ ++ return sprintf(buf, "%d\n", val); ++} ++ ++static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ long disable; ++ int status; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ status = sfp_is_port_present(client, data->port); ++ if (IS_ERR_VALUE(status)) { ++ return status; ++ } ++ ++ if (!status) { ++ /* port is not present */ ++ return -ENXIO; ++ } ++ ++ status = kstrtol(buf, 10, &disable); ++ if (status) { ++ return status; ++ } ++ ++ data = qsfp_update_tx_rx_status(dev); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ mutex_lock(&data->update_lock); ++ ++ if (attr->index == TX_DISABLE) { ++ data->qsfp->status[1] = disable & 0xF; ++ } ++ else {/* TX_DISABLE1 ~ TX_DISABLE4*/ ++ if (disable) { ++ data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); ++ } ++ else { ++ data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); ++ } ++ } ++ ++ DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); ++ status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); ++ if (unlikely(status < 0)) { ++ count = status; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status; ++ char ddm; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ status = sfp_is_port_present(client, data->port); ++ if (IS_ERR_VALUE(status)) { ++ return status; ++ } ++ ++ if (status == 0) { ++ /* port is not present */ ++ return -ENODEV; ++ } ++ ++ status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); ++ if (unlikely(status < 0)) { ++ return status; ++ } ++ ++ return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); ++} ++ ++/* Platform dependent +++ */ ++static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u8 val = 0, index = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ ++ if (data->driver_type == DRIVER_TYPE_QSFP) { ++ return qsfp_show_tx_rx_status(dev, da, buf); ++ } ++ ++ data = sfp_update_tx_rx_status(dev); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ if(attr->index == RX_LOS_ALL) { ++ /** Return values 25/49 -> 28/52 in order */ ++ return sprintf(buf, "%.2x\n", (u8)(data->msa->status[2])); ++ } ++ ++ switch (attr->index) { ++ case TX_FAULT: ++ index = 0; ++ break; ++ case TX_DISABLE: ++ index = 1; ++ break; ++ case RX_LOS: ++ index = 2; ++ break; ++ default: ++ return 0; ++ } ++ ++ val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; ++ return sprintf(buf, "%d\n", val); ++} ++/* Platform dependent --- */ ++static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, ++ int data_len) ++{ ++#if USE_I2C_BLOCK_READ ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ if (data_len > I2C_SMBUS_BLOCK_MAX) { ++ data_len = I2C_SMBUS_BLOCK_MAX; ++ } ++ ++ while (retry) { ++ status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ return status; ++ } ++ ++ return data_len; ++#else ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ while (retry) { ++ status = i2c_smbus_write_byte_data(client, command, *data); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ return status; ++ } ++ ++ return 1; ++#endif ++ ++ ++} ++ ++static ssize_t sfp_port_write(struct sfp_port_data *data, ++ const char *buf, loff_t off, size_t count) ++{ ++ ssize_t retval = 0; ++ ++ if (unlikely(!count)) { ++ return count; ++ } ++ ++ /* ++ * Write data to chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&data->update_lock); ++ ++ while (count) { ++ ssize_t status; ++ ++ status = sfp_eeprom_write(data->client, off, buf, count); ++ if (status <= 0) { ++ if (retval == 0) { ++ retval = status; ++ } ++ break; ++ } ++ buf += status; ++ off += status; ++ count -= status; ++ retval += status; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return retval; ++} ++ ++ ++static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ int present; ++ struct sfp_port_data *data; ++ DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); ++ data = dev_get_drvdata(container_of(kobj, struct device, kobj)); ++ ++ present = sfp_is_port_present(data->client, data->port); ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (present == 0) { ++ /* port is not present */ ++ return -ENODEV; ++ } ++ ++ return sfp_port_write(data, buf, off, count); ++} ++ ++static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, ++ int data_len) ++{ ++#if USE_I2C_BLOCK_READ ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ if (data_len > I2C_SMBUS_BLOCK_MAX) { ++ data_len = I2C_SMBUS_BLOCK_MAX; ++ } ++ ++ while (retry) { ++ status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ goto abort; ++ } ++ if (unlikely(status != data_len)) { ++ status = -EIO; ++ goto abort; ++ } ++ ++ //result = data_len; ++ ++abort: ++ return status; ++#else ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ while (retry) { ++ status = i2c_smbus_read_byte_data(client, command); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); ++ goto abort; ++ } ++ ++ *data = (u8)status; ++ status = 1; ++ ++abort: ++ return status; ++#endif ++} ++ ++static ssize_t sfp_port_read(struct sfp_port_data *data, ++ char *buf, loff_t off, size_t count) ++{ ++ ssize_t retval = 0; ++ ++ if (unlikely(!count)) { ++ DEBUG_PRINT("Count = 0, return"); ++ return count; ++ } ++ ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&data->update_lock); ++ ++ while (count) { ++ ssize_t status; ++ ++ status = sfp_eeprom_read(data->client, off, buf, count); ++ if (status <= 0) { ++ if (retval == 0) { ++ retval = status; ++ } ++ break; ++ } ++ ++ buf += status; ++ off += status; ++ count -= status; ++ retval += status; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return retval; ++ ++} ++ ++static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ int present; ++ struct sfp_port_data *data; ++ DEBUG_PRINT("offset = (%d), count = (%d)", off, count); ++ data = dev_get_drvdata(container_of(kobj, struct device, kobj)); ++ ++ present = sfp_is_port_present(data->client, data->port); ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (present == 0) { ++ /* port is not present */ ++ return -ENODEV; ++ } ++ ++ return sfp_port_read(data, buf, off, count); ++} ++ ++static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) ++{ ++ int err; ++ ++ sysfs_bin_attr_init(eeprom); ++ eeprom->attr.name = EEPROM_NAME; ++ eeprom->attr.mode = S_IWUSR | S_IRUGO; ++ eeprom->read = sfp_bin_read; ++ eeprom->write = sfp_bin_write; ++ eeprom->size = EEPROM_SIZE; ++ ++ /* Create eeprom file */ ++ err = sysfs_create_bin_file(kobj, eeprom); ++ if (err) { ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) ++{ ++ sysfs_remove_bin_file(kobj, eeprom); ++ return 0; ++} ++ ++static const struct attribute_group sfp_msa_group = { ++ .attrs = sfp_msa_attributes, ++}; ++ ++static int sfp_i2c_check_functionality(struct i2c_client *client) ++{ ++#if USE_I2C_BLOCK_READ ++ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); ++#else ++ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); ++#endif ++} ++ ++static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, ++ struct sfp_msa_data **data) ++{ ++ int status; ++ struct sfp_msa_data *msa; ++ ++ if (!sfp_i2c_check_functionality(client)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); ++ if (!msa) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ /* init eeprom */ ++ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); ++ if (status) { ++ goto exit_remove; ++ } ++ ++ *data = msa; ++ dev_info(&client->dev, "sfp msa '%s'\n", client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); ++exit_free: ++ kfree(msa); ++exit: ++ ++ return status; ++} ++ ++static const struct attribute_group sfp_ddm_group = { ++ .attrs = sfp_ddm_attributes, ++}; ++ ++static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, ++ struct sfp_ddm_data **data) ++{ ++ int status; ++ struct sfp_ddm_data *ddm; ++ ++ if (!sfp_i2c_check_functionality(client)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); ++ if (!ddm) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ /* init eeprom */ ++ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); ++ if (status) { ++ goto exit_remove; ++ } ++ ++ *data = ddm; ++ dev_info(&client->dev, "sfp ddm '%s'\n", client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); ++exit_free: ++ kfree(ddm); ++exit: ++ ++ return status; ++} ++ ++static const struct attribute_group qsfp_group = { ++ .attrs = qsfp_attributes, ++}; ++ ++static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, ++ struct qsfp_data **data) ++{ ++ int status; ++ struct qsfp_data *qsfp; ++ ++ if (!sfp_i2c_check_functionality(client)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); ++ if (!qsfp) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &qsfp_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ /* init eeprom */ ++ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); ++ if (status) { ++ goto exit_remove; ++ } ++ ++ *data = qsfp; ++ dev_info(&client->dev, "qsfp '%s'\n", client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &qsfp_group); ++exit_free: ++ kfree(qsfp); ++exit: ++ ++ return status; ++} ++ ++/* Platform dependent +++ */ ++static int sfp_device_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct sfp_port_data *data = NULL; ++ ++ data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); ++ if (!data) { ++ return -ENOMEM; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ data->port = dev_id->driver_data; ++ data->client = client; ++ ++ if (client->addr != SFP_EEPROM_A0_I2C_ADDR && ++ client->addr != SFP_EEPROM_A2_I2C_ADDR ) { ++ return -ENODEV; ++ } ++ ++ if (dev_id->driver_data >= as4610_sfp1 && dev_id->driver_data <= as4610_sfp4) { ++ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { ++ data->driver_type = DRIVER_TYPE_SFP_MSA; ++ return sfp_msa_probe(client, dev_id, &data->msa); ++ } ++ else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { ++ data->driver_type = DRIVER_TYPE_SFP_DDM; ++ return sfp_ddm_probe(client, dev_id, &data->ddm); ++ } ++ } ++ else if (dev_id->driver_data >= as4610_sfp5 && dev_id->driver_data <= as4610_sfp6) { ++ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { ++ data->driver_type = DRIVER_TYPE_QSFP; ++ return qsfp_probe(client, dev_id, &data->qsfp); ++ } ++ } ++ ++ return -ENODEV; ++} ++/* Platform dependent --- */ ++ ++static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) ++{ ++ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); ++ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); ++ kfree(data); ++ return 0; ++} ++ ++static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) ++{ ++ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); ++ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); ++ kfree(data); ++ return 0; ++} ++ ++static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) ++{ ++ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); ++ sysfs_remove_group(&client->dev.kobj, &qsfp_group); ++ kfree(data); ++ return 0; ++} ++ ++static int sfp_device_remove(struct i2c_client *client) ++{ ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ switch (data->driver_type) { ++ case DRIVER_TYPE_SFP_MSA: ++ return sfp_msa_remove(client, data->msa); ++ case DRIVER_TYPE_SFP_DDM: ++ return sfp_ddm_remove(client, data->ddm); ++ case DRIVER_TYPE_QSFP: ++ return qfp_remove(client, data->qsfp); ++ } ++ ++ return 0; ++} ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; ++ ++static struct i2c_driver sfp_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ }, ++ .probe = sfp_device_probe, ++ .remove = sfp_device_remove, ++ .id_table = sfp_device_id, ++ .address_list = normal_i2c, ++}; ++ ++static int __init sfp_init(void) ++{ ++ return i2c_add_driver(&sfp_driver); ++} ++ ++static void __exit sfp_exit(void) ++{ ++ i2c_del_driver(&sfp_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("accton as4610_sfp driver"); ++MODULE_LICENSE("GPL"); ++ ++late_initcall(sfp_init); ++module_exit(sfp_exit); ++ +diff --git a/include/linux/accton_i2c_cpld.h b/include/linux/accton_i2c_cpld.h +new file mode 100644 +index 0000000..9b75abd +--- /dev/null ++++ b/include/linux/accton_i2c_cpld.h +@@ -0,0 +1,76 @@ ++/* ++ * A hwmon driver for the accton_i2c_cpld ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU 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. ++ */ ++ ++extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++ ++#define AS4610_CPLD_SLAVE_ADDR 0x30 ++#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ ++ ++enum as4610_product_id_e { ++ PID_AS4610_30T, ++ PID_AS4610_30P, ++ PID_AS4610_54T, ++ PID_AS4610_54P, ++ PID_RESERVED, ++ PID_AS4610_54T_B, ++ PID_UNKNOWN ++}; ++ ++static inline int as4610_product_id(void) ++{ ++ int pid = accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); ++ pid &= 0xF; ++ ++ if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) { ++ return PID_UNKNOWN; ++ } ++ ++ return pid; ++} ++ ++static inline int as4610_is_poe_system(void) ++{ ++ int pid = as4610_product_id(); ++ return (pid == PID_AS4610_30P || pid == PID_AS4610_54P); ++} ++ ++static inline int as4610_number_of_system_fan(void) ++{ ++ int nFan = 0; ++ int pid = as4610_product_id(); ++ ++ switch (pid) { ++ case PID_AS4610_30P: ++ case PID_AS4610_54P: ++ nFan = 1; ++ break; ++ case PID_AS4610_54T_B: ++ nFan = 2; ++ break; ++ default: ++ nFan = 0; ++ break; ++ } ++ ++ return nFan; ++} ++ + diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch new file mode 100644 index 00000000..bd9fa7d8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch @@ -0,0 +1,13 @@ +--- a/scripts/Makefile.fwinst ++++ b/scripts/Makefile.fwinst +@@ -13,7 +13,7 @@ src := $(obj) + -include $(objtree)/.config + + include scripts/Kbuild.include +-include $(srctree)/$(obj)/Makefile ++-include $(srctree)/$(obj)/Makefile + + include scripts/Makefile.host + +diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c +index f208f90..78dd083 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch new file mode 100644 index 00000000..05823a6f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch @@ -0,0 +1,121 @@ +--- a/scripts/kconfig/conf.c ++++ b/scripts/kconfig/conf.c +@@ -36,6 +36,7 @@ enum input_mode { + } input_mode = oldaskconfig; + + static int indent = 1; ++static int tty_stdio; + static int valid_stdin = 1; + static int sync_kconfig; + static int conf_cnt; +@@ -108,6 +109,8 @@ static int conf_askvalue(struct symbol *sym, const char *def) + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); ++ if (!tty_stdio) ++ printf("\n"); + return 1; + default: + break; +@@ -364,7 +367,6 @@ static void conf(struct menu *menu) + switch (prop->type) { + case P_MENU: + if ((input_mode == silentoldconfig || +- input_mode == listnewconfig || + input_mode == oldnoconfig) && + rootEntry != menu) { + check_conf(menu); +@@ -425,11 +427,7 @@ static void check_conf(struct menu *menu) + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { +- if (input_mode == listnewconfig) { +- if (sym->name && !sym_is_choice_value(sym)) { +- printf("%s%s\n", CONFIG_, sym->name); +- } +- } else if (input_mode != oldnoconfig) { ++ if (input_mode != oldnoconfig) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); +@@ -442,6 +440,30 @@ static void check_conf(struct menu *menu) + check_conf(child); + } + ++static void report_conf(struct menu *menu, bool verbose) ++{ ++ struct symbol *sym; ++ struct menu *child; ++ ++ if (!menu_is_visible(menu)) ++ return; ++ ++ if (verbose && menu == &rootmenu) { ++ printf("\n#\n" ++ "# Changes:\n" ++ "#\n"); ++ } ++ ++ sym = menu->sym; ++ if (sym && (sym->flags & SYMBOL_NEW) && ++ sym_is_changable(sym) && sym->name && !sym_is_choice_value(sym)) { ++ conf_write_new_symbol(stdout, sym, verbose); ++ } ++ ++ for (child = menu->list; child; child = child->next) ++ report_conf(child, verbose); ++} ++ + static struct option long_opts[] = { + {"oldaskconfig", no_argument, NULL, oldaskconfig}, + {"oldconfig", no_argument, NULL, oldconfig}, +@@ -482,12 +504,15 @@ int main(int ac, char **av) + const char *progname = av[0]; + int opt; + const char *name, *defconfig_file = NULL /* gcc uninit */; ++ const char *value; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + ++ tty_stdio = isatty(0) && isatty(1) && isatty(2); ++ + while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { + input_mode = (enum input_mode)opt; + switch (opt) { +@@ -604,7 +629,7 @@ int main(int ac, char **av) + return 1; + } + } +- valid_stdin = isatty(0) && isatty(1) && isatty(2); ++ valid_stdin = tty_stdio; + } + + switch (input_mode) { +@@ -634,16 +659,18 @@ int main(int ac, char **av) + input_mode = silentoldconfig; + /* fall through */ + case oldconfig: +- case listnewconfig: + case oldnoconfig: + case silentoldconfig: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); +- } while (conf_cnt && +- (input_mode != listnewconfig && +- input_mode != oldnoconfig)); ++ } while (conf_cnt && input_mode != oldnoconfig); ++ break; ++ case listnewconfig: ++ conf_set_all_new_symbols(def_default); ++ value = getenv("KBUILD_VERBOSE"); ++ report_conf(&rootmenu, value && atoi(value)); + break; + } + +diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c +index 5a58965..3e71295 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch new file mode 100644 index 00000000..37a7f3be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch @@ -0,0 +1,27 @@ +--- a/scripts/kconfig/confdata.c ++++ b/scripts/kconfig/confdata.c +@@ -713,6 +713,14 @@ next_menu: + return 0; + } + ++void conf_write_new_symbol(FILE *fp, struct symbol *sym, bool verbose) ++{ ++ if (verbose) ++ conf_write_symbol(fp, sym, &kconfig_printer_cb, NULL); ++ else ++ fprintf(fp, "%s%s\n", CONFIG_, sym->name); ++} ++ + int conf_write(const char *name) + { + FILE *out; +@@ -1102,6 +1110,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) + for_all_symbols(i, sym) { + if (sym_has_value(sym)) + continue; ++ sym->flags |= SYMBOL_NEW; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: +diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h +index 80fce57..0db77f3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch new file mode 100644 index 00000000..6562d9fe --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch @@ -0,0 +1,13 @@ +--- a/scripts/kconfig/expr.h ++++ b/scripts/kconfig/expr.h +@@ -104,6 +104,8 @@ struct symbol { + #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ + #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + ++#define SYMBOL_NEW 0x100000 /* symbol is new (loaded config did not provide a value) */ ++ + #define SYMBOL_MAXLENGTH 256 + #define SYMBOL_HASHSIZE 9973 + +diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h +index 47fe9c3..dd0024a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch new file mode 100644 index 00000000..0b603bbe --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch @@ -0,0 +1,12 @@ +--- a/scripts/kconfig/lkc_proto.h ++++ b/scripts/kconfig/lkc_proto.h +@@ -7,6 +7,7 @@ P(conf_read_simple,int,(const char *name, int)); + P(conf_write_defconfig,int,(const char *name)); + P(conf_write,int,(const char *name)); + P(conf_write_autoconf,int,(void)); ++P(conf_write_new_symbol, void,(FILE*, struct symbol*, bool)); + P(conf_get_changed,bool,(void)); + P(conf_set_changed_callback, void,(void (*fn)(void))); + P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); +diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c +index 98ff331..1c30f8a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch new file mode 100644 index 00000000..a4bcf76e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch @@ -0,0 +1,46 @@ +--- a/scripts/mod/file2alias.c ++++ b/scripts/mod/file2alias.c +@@ -880,6 +880,30 @@ static int do_isapnp_entry(const char *filename, + return 1; + } + ++/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,* ++ * All fields are numbers. It would be nicer to use strings for vendor ++ * and feature, but getting those out of the build system here is too ++ * complicated. ++ */ ++ ++static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id, ++ char *alias) ++{ ++ id->feature = TO_NATIVE(id->feature); ++ id->family = TO_NATIVE(id->family); ++ id->model = TO_NATIVE(id->model); ++ id->vendor = TO_NATIVE(id->vendor); ++ ++ strcpy(alias, "x86cpu:"); ++ ADD(alias, "vendor:", id->vendor != X86_VENDOR_ANY, id->vendor); ++ ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family); ++ ADD(alias, ":model:", id->model != X86_MODEL_ANY, id->model); ++ strcat(alias, ":feature:*"); ++ if (id->feature != X86_FEATURE_ANY) ++ sprintf(alias + strlen(alias), "%04X*", id->feature); ++ return 1; ++} ++ + /* Ignore any prefix, eg. some architectures prepend _ */ + static inline int sym_is(const char *symbol, const char *name) + { +@@ -1051,6 +1075,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + do_table(symval, sym->st_size, + sizeof(struct isapnp_device_id), "isa", + do_isapnp_entry, mod); ++ else if (sym_is(symname, "__mod_x86cpu_device_table")) ++ do_table(symval, sym->st_size, ++ sizeof(struct x86_cpu_id), "x86cpu", ++ do_x86cpu_entry, mod); + free(zeros); + } + +diff --git a/scripts/package/Makefile b/scripts/package/Makefile +index bc6aa00..b0817f9 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch new file mode 100644 index 00000000..3d414ce2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch @@ -0,0 +1,31 @@ +--- a/scripts/package/Makefile ++++ b/scripts/package/Makefile +@@ -77,8 +77,8 @@ clean-files += $(objtree)/binkernel.spec + + # Deb target + # --------------------------------------------------------------------------- +-quiet_cmd_builddeb = BUILDDEB +- cmd_builddeb = set -e; \ ++#quiet_cmd_builddeb = BUILDDEB ++# cmd_builddeb = set -e; \ + test `id -u` = 0 || \ + test -n "$(KBUILD_PKG_ROOTCMD)" || { \ + which fakeroot >/dev/null 2>&1 && \ +@@ -95,11 +95,11 @@ quiet_cmd_builddeb = BUILDDEB + $$KBUILD_PKG_ROOTCMD $(CONFIG_SHELL) \ + $(srctree)/scripts/package/builddeb + +-deb-pkg: FORCE +- $(MAKE) KBUILD_SRC= +- $(call cmd,builddeb) ++#deb-pkg: FORCE ++# $(MAKE) KBUILD_SRC= ++# $(call cmd,builddeb) + +-clean-dirs += $(objtree)/debian/ ++#clean-dirs += $(objtree)/debian/ + + + # tarball targets +diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig +index 9b9013b..51ebf96 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/series b/packages/base/any/kernels/3.2-lts/patches/series new file mode 100644 index 00000000..e2adb686 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/series @@ -0,0 +1,508 @@ +kernel-overlayfs-v11.patch +kernel-fs-overlayfs-inode.patch +overlayfs_notify.patch +Makefile.patch +arch_arm_Kconfig.patch +arch_arm_Makefile.patch +arch_arm_boot_compressed_head.S.patch +arch_arm_boot_dts_accton_as4610_54.dts.patch +arch_arm_boot_dts_dni_3448p.dts.patch +arch_arm_boot_dts_helix4.dtsi.patch +arch_arm_common_gic.c.patch +arch_arm_configs_iproc_defconfig.patch +arch_arm_include_asm_bug.h.patch +arch_arm_include_asm_hardware_gic.h.patch +arch_arm_include_asm_pgtable.h.patch +arch_arm_include_asm_processor.h.patch +arch_arm_kernel_entry-armv.S.patch +arch_arm_kernel_entry-header.S.patch +arch_arm_kernel_head.S.patch +arch_arm_kernel_module.c.patch +arch_arm_kernel_process.c.patch +arch_arm_kernel_smp_scu.c.patch +arch_arm_kernel_smp_twd.c.patch +arch_arm_mach-iproc_Kconfig.patch +arch_arm_mach-iproc_Makefile.patch +arch_arm_mach-iproc_Makefile.boot.patch +arch_arm_mach-iproc_board_bu.c.patch +arch_arm_mach-iproc_common.c.patch +arch_arm_mach-iproc_common.h.patch +arch_arm_mach-iproc_flash.c.patch +arch_arm_mach-iproc_idm.c.patch +arch_arm_mach-iproc_include_mach_io_map.h.patch +arch_arm_mach-iproc_include_mach_iproc_regs.h.patch +arch_arm_mach-iproc_include_mach_nand_iproc.h.patch +arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch +arch_arm_mach-iproc_include_mach_reg_utils.h.patch +arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch +arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch +arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch +arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch +arch_arm_mach-iproc_include_mach_vmalloc.h.patch +arch_arm_mach-iproc_io_map.c.patch +arch_arm_mach-iproc_localtimer.c.patch +arch_arm_mach-iproc_northstar.c.patch +arch_arm_mach-iproc_northstar.h.patch +arch_arm_mach-iproc_northstar_dmu.c.patch +arch_arm_mach-iproc_pm.c.patch +arch_arm_mm_Kconfig.patch +arch_arm_mm_init.c.patch +arch_arm_mm_ioremap.c.patch +arch_arm_mm_mm.h.patch +arch_arm_mm_mmap.c.patch +arch_arm_mm_mmu.c.patch +arch_arm_mm_nommu.c.patch +arch_arm_net_Makefile.patch +arch_arm_net_bpf_jit_32.c.patch +arch_arm_net_bpf_jit_32.h.patch +arch_arm_plat-iproc_Kconfig.patch +arch_arm_plat-iproc_Makefile.patch +arch_arm_plat-iproc_bcm5301x.c.patch +arch_arm_plat-iproc_clock.c.patch +arch_arm_plat-iproc_headsmp.S.patch +arch_arm_plat-iproc_hotplug.c.patch +arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch +arch_arm_plat-iproc_include_mach_bridge-regs.h.patch +arch_arm_plat-iproc_include_mach_clkdev.h.patch +arch_arm_plat-iproc_include_mach_clock.h.patch +arch_arm_plat-iproc_include_mach_common.h.patch +arch_arm_plat-iproc_include_mach_debug-macro.S.patch +arch_arm_plat-iproc_include_mach_entry-macro.S.patch +arch_arm_plat-iproc_include_mach_gpio.h.patch +arch_arm_plat-iproc_include_mach_hardware.h.patch +arch_arm_plat-iproc_include_mach_io.h.patch +arch_arm_plat-iproc_include_mach_iproc.h.patch +arch_arm_plat-iproc_include_mach_iproc_timer.h.patch +arch_arm_plat-iproc_include_mach_irqs.h.patch +arch_arm_plat-iproc_include_mach_lm.h.patch +arch_arm_plat-iproc_include_mach_memory.h.patch +arch_arm_plat-iproc_include_mach_sdio_platform.h.patch +arch_arm_plat-iproc_include_mach_smp.h.patch +arch_arm_plat-iproc_include_mach_system.h.patch +arch_arm_plat-iproc_include_mach_timer.h.patch +arch_arm_plat-iproc_include_mach_timex.h.patch +arch_arm_plat-iproc_include_mach_uncompress.h.patch +arch_arm_plat-iproc_include_plat_dma-pl330.h.patch +arch_arm_plat-iproc_include_plat_dma_drv.h.patch +arch_arm_plat-iproc_include_plat_dmux.h.patch +arch_arm_plat-iproc_include_plat_osdal_os.h.patch +arch_arm_plat-iproc_include_plat_shm.h.patch +arch_arm_plat-iproc_include_plat_spi_iproc.h.patch +arch_arm_plat-iproc_include_plat_swreset_rec.h.patch +arch_arm_plat-iproc_include_plat_timer-sp.h.patch +arch_arm_plat-iproc_include_plat_types.h.patch +arch_arm_plat-iproc_iproc-cache.S.patch +arch_arm_plat-iproc_iproc_cru.c.patch +arch_arm_plat-iproc_irq.c.patch +arch_arm_plat-iproc_lm.c.patch +arch_arm_plat-iproc_localtimer.c.patch +arch_arm_plat-iproc_platsmp.c.patch +arch_arm_plat-iproc_shm.c.patch +arch_arm_plat-iproc_swreset_rec.c.patch +arch_arm_plat-iproc_sysfs.c.patch +arch_arm_plat-iproc_timer-sp.c.patch +arch_arm_plat-iproc_timer.c.patch +arch_arm_tools_mach-types.patch +drivers_Kconfig.patch +drivers_Makefile.patch +drivers_base_Kconfig.patch +drivers_base_Makefile.patch +drivers_base_base.h.patch +drivers_base_bus.c.patch +drivers_base_class.c.patch +drivers_base_core.c.patch +drivers_base_cpu.c.patch +drivers_base_init.c.patch +drivers_base_node.c.patch +drivers_base_sys.c.patch +drivers_base_topology.c.patch +drivers_bcma_host_pci.c.patch +drivers_bcmdrivers_Kconfig.patch +drivers_bcmdrivers_Makefile.patch +drivers_bcmdrivers_dma_.gitignore.patch +drivers_bcmdrivers_dma_Kconfig.patch +drivers_bcmdrivers_dma_Makefile.patch +drivers_bcmdrivers_dma_dma-pl330.h.patch +drivers_bcmdrivers_dma_dma.c.patch +drivers_bcmdrivers_dma_dma_drv.h.patch +drivers_bcmdrivers_dma_pl330-pdata.h.patch +drivers_bcmdrivers_gmac_et_.gitignore.patch +drivers_bcmdrivers_gmac_et_Kconfig.patch +drivers_bcmdrivers_gmac_et_Makefile.patch +drivers_bcmdrivers_gmac_hnd_.gitignore.patch +drivers_bcmdrivers_gmac_hnd_Kconfig.patch +drivers_bcmdrivers_gmac_hnd_Makefile.patch +drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch +drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch +drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch +drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch +drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch +drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch +drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch +drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch +drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch +drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch +drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch +drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch +drivers_bcmdrivers_gmac_src_include_Makefile.patch +drivers_bcmdrivers_gmac_src_include_aidmp.h.patch +drivers_bcmdrivers_gmac_src_include_arminc.h.patch +drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch +drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch +drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch +drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch +drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch +drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch +drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch +drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch +drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch +drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch +drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch +drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch +drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch +drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch +drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch +drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch +drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch +drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch +drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch +drivers_bcmdrivers_gmac_src_include_compvers.sh.patch +drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch +drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch +drivers_bcmdrivers_gmac_src_include_epivers.h.patch +drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch +drivers_bcmdrivers_gmac_src_include_epivers.sh.patch +drivers_bcmdrivers_gmac_src_include_etioctl.h.patch +drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch +drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch +drivers_bcmdrivers_gmac_src_include_hndarm.h.patch +drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch +drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch +drivers_bcmdrivers_gmac_src_include_hnddma.h.patch +drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch +drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch +drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch +drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch +drivers_bcmdrivers_gmac_src_include_linuxver.h.patch +drivers_bcmdrivers_gmac_src_include_osl.h.patch +drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch +drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch +drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch +drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch +drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch +drivers_bcmdrivers_gmac_src_include_proto_BOM.patch +drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch +drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch +drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch +drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch +drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch +drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch +drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch +drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch +drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch +drivers_bcmdrivers_gmac_src_include_siutils.h.patch +drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch +drivers_bcmdrivers_gmac_src_include_typedefs.h.patch +drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch +drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch +drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch +drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch +drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch +drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch +drivers_bcmdrivers_gmac_src_shared_siutils.c.patch +drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch +drivers_bcmdrivers_gmac_src_shared_wl_config.patch +drivers_bcmdrivers_gpio_.gitignore.patch +drivers_bcmdrivers_gpio_Kconfig.patch +drivers_bcmdrivers_gpio_Makefile.patch +drivers_bcmdrivers_gpio_gpio.c.patch +drivers_bcmdrivers_gpio_gpio.h.patch +drivers_bcmdrivers_gpio_gpio_cfg.c.patch +drivers_bcmdrivers_gpio_gpio_cfg.h.patch +drivers_bcmdrivers_gpio_gpiolib.c.patch +drivers_bcmdrivers_include_Readme.txt.patch +drivers_bcmdrivers_mdio_.gitignore.patch +drivers_bcmdrivers_mdio_Kconfig.patch +drivers_bcmdrivers_mdio_Makefile.patch +drivers_bcmdrivers_mdio_iproc_mdio.c.patch +drivers_bcmdrivers_mdio_iproc_mdio.h.patch +drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch +drivers_bcmdrivers_nand_.gitignore.patch +drivers_bcmdrivers_nand_Kconfig.patch +drivers_bcmdrivers_nand_Makefile.patch +drivers_bcmdrivers_nand_nand_iproc.c.patch +drivers_bcmdrivers_pmu_.gitignore.patch +drivers_bcmdrivers_pmu_Kconfig.patch +drivers_bcmdrivers_pmu_Makefile.patch +drivers_bcmdrivers_pmu_iproc-pmu.c.patch +drivers_bcmdrivers_pwm_.gitignore.patch +drivers_bcmdrivers_pwm_Kconfig.patch +drivers_bcmdrivers_pwm_Makefile.patch +drivers_bcmdrivers_pwm_iproc_pwmc.c.patch +drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch +drivers_bcmdrivers_qspi_.gitignore.patch +drivers_bcmdrivers_qspi_Kconfig.patch +drivers_bcmdrivers_qspi_Makefile.patch +drivers_bcmdrivers_qspi_qspi_iproc.c.patch +drivers_bcmdrivers_smbus_.gitignore.patch +drivers_bcmdrivers_smbus_Kconfig.patch +drivers_bcmdrivers_smbus_Makefile.patch +drivers_bcmdrivers_smbus_iproc_smbus.c.patch +drivers_bcmdrivers_smbus_iproc_smbus.h.patch +drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch +drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch +drivers_bcmdrivers_timer_.gitignore.patch +drivers_bcmdrivers_timer_Kconfig.patch +drivers_bcmdrivers_timer_Makefile.patch +drivers_bcmdrivers_timer_iproc_timer.c.patch +drivers_bcmdrivers_timer_iproc_timer.h.patch +drivers_bcmdrivers_usb2h_.gitignore.patch +drivers_bcmdrivers_usb2h_Kconfig.patch +drivers_bcmdrivers_usb2h_Makefile.patch +drivers_bcmdrivers_usb2h_bcm-iproc.c.patch +drivers_bcmdrivers_usb2h_bcm_usbh.h.patch +drivers_bcmdrivers_usb2h_ehci-bcm.c.patch +drivers_bcmdrivers_usb2h_ohci-bcm.c.patch +drivers_bcmdrivers_usb2h_usbh_cfg.h.patch +drivers_bcmdrivers_wdt_.gitignore.patch +drivers_bcmdrivers_wdt_Kconfig.patch +drivers_bcmdrivers_wdt_Makefile.patch +drivers_bcmdrivers_wdt_iproc_wdt.c.patch +drivers_cpuidle_cpuidle.c.patch +drivers_cpuidle_cpuidle.h.patch +drivers_cpuidle_sysfs.c.patch +drivers_crypto_padlock-aes.c.patch +drivers_crypto_padlock-sha.c.patch +drivers_dma_Kconfig.patch +drivers_dma_imx-sdma.c.patch +drivers_gpio_Kconfig.patch +drivers_gpio_gpio-mpc8xxx.c.patch +drivers_gpio_gpio-pca953x.c.patch +drivers_gpio_gpio-sch.c.patch +drivers_hwmon_Kconfig.patch +drivers_hwmon_Makefile.patch +drivers_hwmon_adt7470.c.patch +drivers_hwmon_adt7475.c.patch +drivers_hwmon_coretemp.c.patch +drivers_hwmon_cy8c3245r1.c.patch +drivers_hwmon_cy8cxx.c.patch +drivers_hwmon_emc2305.c.patch +drivers_hwmon_it87.c.patch +drivers_hwmon_max6620.c.patch +drivers_hwmon_max6639.c.patch +drivers_hwmon_max6697.c.patch +drivers_hwmon_pmbus_Kconfig.patch +drivers_hwmon_pmbus_Makefile.patch +drivers_hwmon_pmbus_cpr4011.c.patch +drivers_hwmon_pmbus_dps460.c.patch +drivers_hwmon_pmbus_pmbus.h.patch +drivers_hwmon_pmbus_pmbus_core.c.patch +drivers_hwmon_pmbus_ps2471.c.patch +drivers_hwmon_via-cputemp.c.patch +drivers_i2c_busses_Kconfig.patch +drivers_i2c_busses_Makefile.patch +drivers_i2c_i2c-mux.c.patch +drivers_i2c_muxes_Kconfig.patch +drivers_i2c_muxes_Makefile.patch +drivers_i2c_muxes_gpio-i2cmux.c.patch +drivers_i2c_muxes_pca9541.c.patch +drivers_i2c_muxes_pca954x.c.patch +drivers_misc_Kconfig.patch +drivers_misc_Makefile.patch +drivers_misc_ds100df410.c.patch +drivers_misc_early_dma_alloc.c.patch +drivers_misc_eeprom_Kconfig.patch +drivers_misc_eeprom_Makefile.patch +drivers_misc_eeprom_at24.c.patch +drivers_misc_eeprom_eeprom_class.c.patch +drivers_misc_eeprom_sff_8436_eeprom.c.patch +drivers_misc_iwmc3200top_fw-download.c.patch +drivers_misc_retimer_class.c.patch +drivers_misc_ti-st_st_kim.c.patch +drivers_mtd_chips_Kconfig.patch +drivers_mtd_chips_cfi_cmdset_0020.c.patch +drivers_mtd_devices_Kconfig.patch +drivers_mtd_devices_m25p80.c.patch +drivers_mtd_maps_physmap_of.c.patch +drivers_mtd_mtdoops.c.patch +drivers_mtd_ubi_build.c.patch +drivers_net_Makefile.patch +drivers_net_can_softing_softing_fw.c.patch +drivers_net_ethernet_broadcom_bnx2.c.patch +drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch +drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch +drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch +drivers_net_ethernet_broadcom_tg3.c.patch +drivers_net_phy_mdio_bus.c.patch +drivers_net_phy_phy.c.patch +drivers_net_phy_phy_device.c.patch +drivers_of_of_mdio.c.patch +drivers_of_platform.c.patch +drivers_pci_access.c.patch +drivers_pci_msi.c.patch +drivers_pci_pci.c.patch +drivers_pci_pcie_aspm.c.patch +drivers_pci_probe.c.patch +drivers_pci_quirks.c.patch +drivers_pci_setup-res.c.patch +drivers_rtc_hctosys.c.patch +drivers_rtc_rtc-m41t80.c.patch +drivers_rtc_rtc-mv.c.patch +drivers_rtc_rtc-s35390a.c.patch +drivers_tty_cyclades.c.patch +drivers_tty_moxa.c.patch +drivers_tty_serial_icom.c.patch +drivers_tty_serial_ucc_uart.c.patch +drivers_usb_host_ehci-hcd.c.patch +drivers_usb_host_ehci-hub.c.patch +drivers_usb_host_ohci-hcd.c.patch +drivers_usb_misc_emi26.c.patch +drivers_usb_misc_emi62.c.patch +drivers_usb_serial_io_edgeport.c.patch +drivers_usb_serial_io_ti.c.patch +drivers_usb_serial_keyspan.c.patch +drivers_usb_serial_keyspan_pda.c.patch +drivers_usb_serial_ti_usb_3410_5052.c.patch +drivers_usb_serial_whiteheat.c.patch +drivers_watchdog_Kconfig.patch +drivers_watchdog_Makefile.patch +drivers_watchdog_booke_wdt.c.patch +drivers_watchdog_iTCO_wdt.c.patch +drivers_watchdog_ie6xx_wdt.c.patch +drivers_watchdog_sp5100_tco.c.patch +include_asm-generic_io-64-nonatomic-hi-lo.h.patch +include_asm-generic_io-64-nonatomic-lo-hi.h.patch +include_linux_amba_bus.h.patch +include_linux_audit.h.patch +include_linux_bitops.h.patch +include_linux_ceph_messenger.h.patch +include_linux_connector.h.patch +include_linux_cpu.h.patch +include_linux_dcache.h.patch +include_linux_device-mapper.h.patch +include_linux_device.h.patch +include_linux_dma-mapping.h.patch +include_linux_dmaengine.h.patch +include_linux_dmi.h.patch +include_linux_dynamic_queue_limits.h.patch +include_linux_early_dma_alloc.h.patch +include_linux_eeprom_class.h.patch +include_linux_efi.h.patch +include_linux_ethtool.h.patch +include_linux_ftrace_event.h.patch +include_linux_hashtable.h.patch +include_linux_i2c-mux-gpio.h.patch +include_linux_i2c-mux.h.patch +include_linux_i2c.h.patch +include_linux_i2c_at24.h.patch +include_linux_i2c_pca953x.h.patch +include_linux_i2c_sff-8436.h.patch +include_linux_if_bridge.h.patch +include_linux_if_ether.h.patch +include_linux_if_link.h.patch +include_linux_if_tun.h.patch +include_linux_init.h.patch +include_linux_irqdesc.h.patch +include_linux_jbd2.h.patch +include_linux_jiffies.h.patch +include_linux_kvm_host.h.patch +include_linux_mdio.h.patch +include_linux_mii.h.patch +include_linux_mm_types.h.patch +include_linux_mod_devicetable.h.patch +include_linux_mroute.h.patch +include_linux_msi.h.patch +include_linux_mtd_cfi.h.patch +include_linux_mtd_cfi_endian.h.patch +include_linux_mtd_map.h.patch +include_linux_neighbour.h.patch +include_linux_of_mdio.h.patch +include_linux_pci.h.patch +include_linux_pci_ids.h.patch +include_linux_pci_regs.h.patch +include_linux_percpu.h.patch +include_linux_perf_event.h.patch +include_linux_phy.h.patch +include_linux_pid_namespace.h.patch +include_linux_pkt_sched.h.patch +include_linux_platform_data_max6697.h.patch +include_linux_platform_device.h.patch +include_linux_port.h.patch +include_linux_pps_kernel.h.patch +include_linux_ptrace.h.patch +include_linux_random.h.patch +include_linux_regulator_consumer.h.patch +include_linux_retimer_class.h.patch +include_linux_rmap.h.patch +include_linux_skbuff.h.patch +include_linux_slab_def.h.patch +include_linux_snmp.h.patch +include_linux_swiotlb.h.patch +include_linux_sysctl.h.patch +include_linux_sysfs.h.patch +include_linux_sysrq.h.patch +include_linux_tcp.h.patch +include_linux_u64_stats_sync.h.patch +include_linux_usb.h.patch +include_linux_usb_ehci_def.h.patch +include_linux_usb_hcd.h.patch +include_linux_vmalloc.h.patch +include_linux_watchdog.h.patch +include_trace_syscall.h.patch +init_Kconfig.patch +lib_Kconfig.patch +lib_Kconfig.debug.patch +lib_Makefile.patch +lib_dynamic_queue_limits.c.patch +lib_nlattr.c.patch +lib_swiotlb.c.patch +mm_backing-dev.c.patch +mm_memcontrol.c.patch +mm_rmap.c.patch +mm_slab.c.patch +mm_sparse-vmemmap.c.patch +mm_swap.c.patch +mm_truncate.c.patch +mm_vmalloc.c.patch +mm_vmscan.c.patch +scripts_Makefile.fwinst.patch +scripts_kconfig_conf.c.patch +scripts_kconfig_confdata.c.patch +scripts_kconfig_expr.h.patch +scripts_kconfig_lkc_proto.h.patch +scripts_mod_file2alias.c.patch +scripts_package_Makefile.patch +tools_include_tools_be_byteshift.h.patch +tools_include_tools_le_byteshift.h.patch +platform-accton-as4610-device-drivers.patch diff --git a/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch new file mode 100644 index 00000000..f55db105 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch @@ -0,0 +1,76 @@ +--- /dev/null ++++ b/tools/include/tools/be_byteshift.h +@@ -0,0 +1,70 @@ ++#ifndef _TOOLS_BE_BYTESHIFT_H ++#define _TOOLS_BE_BYTESHIFT_H ++ ++#include ++ ++static inline __u16 __get_unaligned_be16(const __u8 *p) ++{ ++ return p[0] << 8 | p[1]; ++} ++ ++static inline __u32 __get_unaligned_be32(const __u8 *p) ++{ ++ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; ++} ++ ++static inline __u64 __get_unaligned_be64(const __u8 *p) ++{ ++ return (__u64)__get_unaligned_be32(p) << 32 | ++ __get_unaligned_be32(p + 4); ++} ++ ++static inline void __put_unaligned_be16(__u16 val, __u8 *p) ++{ ++ *p++ = val >> 8; ++ *p++ = val; ++} ++ ++static inline void __put_unaligned_be32(__u32 val, __u8 *p) ++{ ++ __put_unaligned_be16(val >> 16, p); ++ __put_unaligned_be16(val, p + 2); ++} ++ ++static inline void __put_unaligned_be64(__u64 val, __u8 *p) ++{ ++ __put_unaligned_be32(val >> 32, p); ++ __put_unaligned_be32(val, p + 4); ++} ++ ++static inline __u16 get_unaligned_be16(const void *p) ++{ ++ return __get_unaligned_be16((const __u8 *)p); ++} ++ ++static inline __u32 get_unaligned_be32(const void *p) ++{ ++ return __get_unaligned_be32((const __u8 *)p); ++} ++ ++static inline __u64 get_unaligned_be64(const void *p) ++{ ++ return __get_unaligned_be64((const __u8 *)p); ++} ++ ++static inline void put_unaligned_be16(__u16 val, void *p) ++{ ++ __put_unaligned_be16(val, p); ++} ++ ++static inline void put_unaligned_be32(__u32 val, void *p) ++{ ++ __put_unaligned_be32(val, p); ++} ++ ++static inline void put_unaligned_be64(__u64 val, void *p) ++{ ++ __put_unaligned_be64(val, p); ++} ++ ++#endif /* _TOOLS_BE_BYTESHIFT_H */ +diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h +new file mode 100644 +index 0000000..c99d45a diff --git a/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch new file mode 100644 index 00000000..d26f3e7f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch @@ -0,0 +1,73 @@ +--- /dev/null ++++ b/tools/include/tools/le_byteshift.h +@@ -0,0 +1,70 @@ ++#ifndef _TOOLS_LE_BYTESHIFT_H ++#define _TOOLS_LE_BYTESHIFT_H ++ ++#include ++ ++static inline __u16 __get_unaligned_le16(const __u8 *p) ++{ ++ return p[0] | p[1] << 8; ++} ++ ++static inline __u32 __get_unaligned_le32(const __u8 *p) ++{ ++ return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; ++} ++ ++static inline __u64 __get_unaligned_le64(const __u8 *p) ++{ ++ return (__u64)__get_unaligned_le32(p + 4) << 32 | ++ __get_unaligned_le32(p); ++} ++ ++static inline void __put_unaligned_le16(__u16 val, __u8 *p) ++{ ++ *p++ = val; ++ *p++ = val >> 8; ++} ++ ++static inline void __put_unaligned_le32(__u32 val, __u8 *p) ++{ ++ __put_unaligned_le16(val >> 16, p + 2); ++ __put_unaligned_le16(val, p); ++} ++ ++static inline void __put_unaligned_le64(__u64 val, __u8 *p) ++{ ++ __put_unaligned_le32(val >> 32, p + 4); ++ __put_unaligned_le32(val, p); ++} ++ ++static inline __u16 get_unaligned_le16(const void *p) ++{ ++ return __get_unaligned_le16((const __u8 *)p); ++} ++ ++static inline __u32 get_unaligned_le32(const void *p) ++{ ++ return __get_unaligned_le32((const __u8 *)p); ++} ++ ++static inline __u64 get_unaligned_le64(const void *p) ++{ ++ return __get_unaligned_le64((const __u8 *)p); ++} ++ ++static inline void put_unaligned_le16(__u16 val, void *p) ++{ ++ __put_unaligned_le16(val, p); ++} ++ ++static inline void put_unaligned_le32(__u32 val, void *p) ++{ ++ __put_unaligned_le32(val, p); ++} ++ ++static inline void put_unaligned_le64(__u64 val, void *p) ++{ ++ __put_unaligned_le64(val, p); ++} ++ ++#endif /* _TOOLS_LE_BYTESHIFT_H */