From: Florian Fainelli Date: Thu, 4 Feb 2010 10:10:45 +0000 (+0000) Subject: move generic config and patches directory to be 2.6.30 specific X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=7b56fb6337756ff7cb07dec09420da7026d7d3e3;p=openwrt%2Fstaging%2Fmkresin.git move generic config and patches directory to be 2.6.30 specific SVN-Revision: 19513 --- diff --git a/target/linux/config-2.6.30 b/target/linux/config-2.6.30 new file mode 100644 index 0000000000..5054d158ac --- /dev/null +++ b/target/linux/config-2.6.30 @@ -0,0 +1,269 @@ +# CONFIG_32BIT is not set +CONFIG_64BIT=y +CONFIG_64BIT_PHYS_ADDR=y +# CONFIG_ALTERA_PCIE_CHDMA is not set +# CONFIG_ANDROID is not set +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_ANDROID_LOGGER is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_ANDROID_RAM_CONSOLE is not set +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_ARCH_SUPPORTS_OPROFILE=y +# CONFIG_ARPD is not set +# CONFIG_B3DFG is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BCM47XX is not set +# CONFIG_BINARY_PRINTF is not set +CONFIG_BINFMT_ELF32=y +CONFIG_BITREVERSE=y +CONFIG_BLOCK_COMPAT=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_CAVIUM_OCTEON_2ND_KERNEL is not set +CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2 +CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED=y +CONFIG_CAVIUM_OCTEON_LOCK_L2=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_MEMCPY=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB=y +CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +CONFIG_CAVIUM_OCTEON_SPECIFIC_OPTIONS=y +CONFIG_CEVT_R4K=y +CONFIG_CEVT_R4K_LIB=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_CMDLINE="console=ttyS0,115200" +# CONFIG_COMEDI is not set +CONFIG_COMPAT=y +CONFIG_COMPAT_BRK=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_CAVIUM_OCTEON=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +CONFIG_CPU_MIPSR2=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_VR41XX is not set +CONFIG_CRAMFS=y +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_DEVKMEM=y +CONFIG_DEVPORT=y +# CONFIG_DM9000 is not set +CONFIG_DMA_COHERENT=y +CONFIG_DNOTIFY=y +# CONFIG_DST is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_ECHO is not set +CONFIG_ELF_CORE=y +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_ET131X is not set +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_FRAME_WARN=2048 +# CONFIG_FW_LOADER is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GROUP_SCHED=y +# CONFIG_HAMRADIO is not set +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_IDE=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_SYSCALL_WRAPPERS=y +# CONFIG_HECI is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_OCTEON=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_CPU_OCTEON=y +CONFIG_IRQ_PER_CPU=y +# CONFIG_ISDN is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KEXEC=y +# CONFIG_KGDB is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_LEMOTE_FULONG is not set +CONFIG_LOCK_KERNEL=y +# CONFIG_LOCK_STAT is not set +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_ME4000 is not set +# CONFIG_MEILHAUS is not set +# CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y +CONFIG_MIPS32_COMPAT=y +CONFIG_MIPS32_N32=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS_COBALT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=7 +# CONFIG_MIPS_MACHINE is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MISC_DEVICES is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_NO_IOPORT is not set +CONFIG_NR_CPUS=16 +CONFIG_NR_CPUS_DEFAULT_16=y +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +CONFIG_OCTEON_ETHERNET=y +CONFIG_OCTEON_MGMT=y +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PAGE_POISONING is not set +# CONFIG_PARTITION_ADVANCED is not set +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_DOMAINS=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PLAN9AUTH is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_POHMELFS is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_PROBE_INITRD_HEADER is not set +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RELAY=y +# CONFIG_RTL8187SE is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_RUNTIME_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SECCOMP=y +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SLOW_WORK is not set +CONFIG_SMP=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_STOP_MACHINE=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SYS_HAS_CPU_CAVIUM_OCTEON=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_SMP=y +# CONFIG_TC35815 is not set +# CONFIG_TIMER_STATS is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_USB_SUPPORT=y +CONFIG_USER_SCHED=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +# CONFIG_VLAN_8021Q is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_WEAK_ORDERING=y +CONFIG_WEAK_REORDERING_BEYOND_LLSC=y +# CONFIG_WLAN_80211 is not set +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/octeon/config-2.6.30 b/target/linux/octeon/config-2.6.30 new file mode 100644 index 0000000000..5054d158ac --- /dev/null +++ b/target/linux/octeon/config-2.6.30 @@ -0,0 +1,269 @@ +# CONFIG_32BIT is not set +CONFIG_64BIT=y +CONFIG_64BIT_PHYS_ADDR=y +# CONFIG_ALTERA_PCIE_CHDMA is not set +# CONFIG_ANDROID is not set +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_ANDROID_LOGGER is not set +# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +# CONFIG_ANDROID_RAM_CONSOLE is not set +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_ARCH_SUPPORTS_OPROFILE=y +# CONFIG_ARPD is not set +# CONFIG_B3DFG is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BCM47XX is not set +# CONFIG_BINARY_PRINTF is not set +CONFIG_BINFMT_ELF32=y +CONFIG_BITREVERSE=y +CONFIG_BLOCK_COMPAT=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_CAVIUM_OCTEON_2ND_KERNEL is not set +CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2 +CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED=y +CONFIG_CAVIUM_OCTEON_LOCK_L2=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_MEMCPY=y +CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB=y +CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +CONFIG_CAVIUM_OCTEON_SPECIFIC_OPTIONS=y +CONFIG_CEVT_R4K=y +CONFIG_CEVT_R4K_LIB=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_CMDLINE="console=ttyS0,115200" +# CONFIG_COMEDI is not set +CONFIG_COMPAT=y +CONFIG_COMPAT_BRK=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_CAVIUM_OCTEON=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +CONFIG_CPU_MIPSR2=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_VR41XX is not set +CONFIG_CRAMFS=y +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_DEVKMEM=y +CONFIG_DEVPORT=y +# CONFIG_DM9000 is not set +CONFIG_DMA_COHERENT=y +CONFIG_DNOTIFY=y +# CONFIG_DST is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_ECHO is not set +CONFIG_ELF_CORE=y +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_ET131X is not set +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_FRAME_WARN=2048 +# CONFIG_FW_LOADER is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GROUP_SCHED=y +# CONFIG_HAMRADIO is not set +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_IDE=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_SYSCALL_WRAPPERS=y +# CONFIG_HECI is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_OCTEON=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_CPU_OCTEON=y +CONFIG_IRQ_PER_CPU=y +# CONFIG_ISDN is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KEXEC=y +# CONFIG_KGDB is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_LEMOTE_FULONG is not set +CONFIG_LOCK_KERNEL=y +# CONFIG_LOCK_STAT is not set +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_ME4000 is not set +# CONFIG_MEILHAUS is not set +# CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y +CONFIG_MIPS32_COMPAT=y +CONFIG_MIPS32_N32=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS_COBALT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=7 +# CONFIG_MIPS_MACHINE is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MISC_DEVICES is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_NO_IOPORT is not set +CONFIG_NR_CPUS=16 +CONFIG_NR_CPUS_DEFAULT_16=y +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +CONFIG_OCTEON_ETHERNET=y +CONFIG_OCTEON_MGMT=y +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PAGE_POISONING is not set +# CONFIG_PARTITION_ADVANCED is not set +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_DOMAINS=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PLAN9AUTH is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_POHMELFS is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_PROBE_INITRD_HEADER is not set +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RELAY=y +# CONFIG_RTL8187SE is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_RUNTIME_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SECCOMP=y +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SLOW_WORK is not set +CONFIG_SMP=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_STOP_MACHINE=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SYS_HAS_CPU_CAVIUM_OCTEON=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_SMP=y +# CONFIG_TC35815 is not set +# CONFIG_TIMER_STATS is not set +CONFIG_TRACING_SUPPORT=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_USB_SUPPORT=y +CONFIG_USER_SCHED=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +# CONFIG_VLAN_8021Q is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_WEAK_ORDERING=y +CONFIG_WEAK_REORDERING_BEYOND_LLSC=y +# CONFIG_WLAN_80211 is not set +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/octeon/config-default b/target/linux/octeon/config-default deleted file mode 100644 index 5054d158ac..0000000000 --- a/target/linux/octeon/config-default +++ /dev/null @@ -1,269 +0,0 @@ -# CONFIG_32BIT is not set -CONFIG_64BIT=y -CONFIG_64BIT_PHYS_ADDR=y -# CONFIG_ALTERA_PCIE_CHDMA is not set -# CONFIG_ANDROID is not set -# CONFIG_ANDROID_BINDER_IPC is not set -# CONFIG_ANDROID_LOGGER is not set -# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set -# CONFIG_ANDROID_RAM_CONSOLE is not set -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUPPORTS_MSI=y -CONFIG_ARCH_SUPPORTS_OPROFILE=y -# CONFIG_ARPD is not set -# CONFIG_B3DFG is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_BCM47XX is not set -# CONFIG_BINARY_PRINTF is not set -CONFIG_BINFMT_ELF32=y -CONFIG_BITREVERSE=y -CONFIG_BLOCK_COMPAT=y -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -# CONFIG_BOOT_PRINTK_DELAY is not set -CONFIG_BSD_PROCESS_ACCT_V3=y -# CONFIG_CAVIUM_OCTEON_2ND_KERNEL is not set -CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2 -CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED=y -CONFIG_CAVIUM_OCTEON_LOCK_L2=y -CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION=y -CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT=y -CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT=y -CONFIG_CAVIUM_OCTEON_LOCK_L2_MEMCPY=y -CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB=y -CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y -# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set -CONFIG_CAVIUM_OCTEON_SPECIFIC_OPTIONS=y -CONFIG_CEVT_R4K=y -CONFIG_CEVT_R4K_LIB=y -# CONFIG_CGROUP_SCHED is not set -CONFIG_CMDLINE="console=ttyS0,115200" -# CONFIG_COMEDI is not set -CONFIG_COMPAT=y -CONFIG_COMPAT_BRK=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_CAVIUM_OCTEON=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -# CONFIG_CPU_LOONGSON2 is not set -# CONFIG_CPU_MIPS32_R1 is not set -# CONFIG_CPU_MIPS32_R2 is not set -# CONFIG_CPU_MIPS64_R1 is not set -# CONFIG_CPU_MIPS64_R2 is not set -CONFIG_CPU_MIPSR2=y -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R5500 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_VR41XX is not set -CONFIG_CRAMFS=y -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_DEBUG_DRIVER is not set -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_SHIRQ is not set -# CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_DEVKMEM=y -CONFIG_DEVPORT=y -# CONFIG_DM9000 is not set -CONFIG_DMA_COHERENT=y -CONFIG_DNOTIFY=y -# CONFIG_DST is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_ECHO is not set -CONFIG_ELF_CORE=y -CONFIG_ENABLE_MUST_CHECK=y -# CONFIG_ET131X is not set -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FLATMEM_MANUAL is not set -CONFIG_FRAME_WARN=2048 -# CONFIG_FW_LOADER is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GROUP_SCHED=y -# CONFIG_HAMRADIO is not set -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set -CONFIG_HAVE_IDE=y -CONFIG_HAVE_MEMORY_PRESENT=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_MLOCKED_PAGE_BIT=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_SYSCALL_WRAPPERS=y -# CONFIG_HECI is not set -# CONFIG_HIGH_RES_TIMERS is not set -CONFIG_HW_HAS_PCI=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_OCTEON=y -CONFIG_HZ=250 -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -CONFIG_IRQ_CPU=y -CONFIG_IRQ_CPU_OCTEON=y -CONFIG_IRQ_PER_CPU=y -# CONFIG_ISDN is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -CONFIG_KEXEC=y -# CONFIG_KGDB is not set -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_LEMOTE_FULONG is not set -CONFIG_LOCK_KERNEL=y -# CONFIG_LOCK_STAT is not set -# CONFIG_MACH_ALCHEMY is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MACH_JAZZ is not set -# CONFIG_MACH_TX39XX is not set -# CONFIG_MACH_TX49XX is not set -# CONFIG_MACH_VR41XX is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_ME4000 is not set -# CONFIG_MEILHAUS is not set -# CONFIG_MIKROTIK_RB532 is not set -CONFIG_MIPS=y -CONFIG_MIPS32_COMPAT=y -CONFIG_MIPS32_N32=y -CONFIG_MIPS32_O32=y -# CONFIG_MIPS_COBALT is not set -CONFIG_MIPS_L1_CACHE_SHIFT=7 -# CONFIG_MIPS_MACHINE is not set -# CONFIG_MIPS_MALTA is not set -CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMP is not set -# CONFIG_MIPS_MT_SMTC is not set -# CONFIG_MIPS_SIM is not set -# CONFIG_MISC_DEVICES is not set -# CONFIG_MTD_CFI_INTELEXT is not set -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -# CONFIG_NETWORK_FILESYSTEMS is not set -# CONFIG_NO_IOPORT is not set -CONFIG_NR_CPUS=16 -CONFIG_NR_CPUS_DEFAULT_16=y -# CONFIG_NXP_STB220 is not set -# CONFIG_NXP_STB225 is not set -CONFIG_OCTEON_ETHERNET=y -CONFIG_OCTEON_MGMT=y -CONFIG_PAGEFLAGS_EXTENDED=y -# CONFIG_PAGE_POISONING is not set -# CONFIG_PARTITION_ADVANCED is not set -# CONFIG_PCI_DEBUG is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PLAN9AUTH is not set -# CONFIG_PMC_MSP is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_PNX8550_JBS is not set -# CONFIG_PNX8550_STB810 is not set -# CONFIG_POHMELFS is not set -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -# CONFIG_PROBE_INITRD_HEADER is not set -CONFIG_PROC_PAGE_MONITOR=y -# CONFIG_PROVE_LOCKING is not set -# CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RELAY=y -# CONFIG_RTL8187SE is not set -# CONFIG_RT_GROUP_SCHED is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_RUNTIME_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -CONFIG_SCHED_DEBUG=y -CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_SCSI_DMA is not set -CONFIG_SECCOMP=y -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SGI_IP28 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SIBYTE_BIGSUR is not set -# CONFIG_SIBYTE_CARMEL is not set -# CONFIG_SIBYTE_CRHINE is not set -# CONFIG_SIBYTE_CRHONE is not set -# CONFIG_SIBYTE_LITTLESUR is not set -# CONFIG_SIBYTE_RHONE is not set -# CONFIG_SIBYTE_SENTOSA is not set -# CONFIG_SIBYTE_SWARM is not set -# CONFIG_SLOW_WORK is not set -CONFIG_SMP=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM_STATIC=y -CONFIG_STAGING=y -# CONFIG_STAGING_EXCLUDE_BUILD is not set -CONFIG_STOP_MACHINE=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_SYSVIPC_COMPAT=y -CONFIG_SYS_HAS_CPU_CAVIUM_OCTEON=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HIGHMEM=y -CONFIG_SYS_SUPPORTS_SMP=y -# CONFIG_TC35815 is not set -# CONFIG_TIMER_STATS is not set -CONFIG_TRACING_SUPPORT=y -CONFIG_UNEVICTABLE_LRU=y -CONFIG_USB_SUPPORT=y -CONFIG_USER_SCHED=y -CONFIG_USE_GENERIC_SMP_HELPERS=y -# CONFIG_VLAN_8021Q is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WEAK_ORDERING=y -CONFIG_WEAK_REORDERING_BEYOND_LLSC=y -# CONFIG_WLAN_80211 is not set -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/octeon/patches-2.6.30/001-handle_removal_h_constraint.patch b/target/linux/octeon/patches-2.6.30/001-handle_removal_h_constraint.patch new file mode 100644 index 0000000000..ea19508ce7 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/001-handle_removal_h_constraint.patch @@ -0,0 +1,25 @@ +This is an incomplete proof of concept that I applied to be able to +build a 64 bit kernel with GCC-4.4. It doesn't handle the 32 bit case +or the R4000_WAR case. + +Comments welcome. + +Signed-off-by: David Daney +--- + arch/mips/include/asm/compiler.h | 7 +++++++ + 2 files changed, 11 insertions(+), 0 deletions(-) + +--- a/arch/mips/include/asm/compiler.h ++++ b/arch/mips/include/asm/compiler.h +@@ -16,4 +16,11 @@ + #define GCC_REG_ACCUM "accum" + #endif + ++#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) ++#define GCC_NO_H_CONSTRAINT ++#ifdef CONFIG_64BIT ++typedef unsigned int uint128_t __attribute__((mode(TI))); ++#endif ++#endif ++ + #endif /* _ASM_COMPILER_H */ diff --git a/target/linux/octeon/patches-2.6.30/002-register_defs_pci.patch b/target/linux/octeon/patches-2.6.30/002-register_defs_pci.patch new file mode 100644 index 0000000000..85a910dd94 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/002-register_defs_pci.patch @@ -0,0 +1,9383 @@ +Here we add the register definitions for the processor blocks used by +the following PCI support patch. + +Signed-off-by: David Daney +--- + arch/mips/include/asm/octeon/cvmx-npei-defs.h | 2560 ++++++++++++++++++++++ + arch/mips/include/asm/octeon/cvmx-npi-defs.h | 1735 +++++++++++++++ + arch/mips/include/asm/octeon/cvmx-pci-defs.h | 1645 ++++++++++++++ + arch/mips/include/asm/octeon/cvmx-pcieep-defs.h | 1365 ++++++++++++ + arch/mips/include/asm/octeon/cvmx-pciercx-defs.h | 1397 ++++++++++++ + arch/mips/include/asm/octeon/cvmx-pescx-defs.h | 410 ++++ + arch/mips/include/asm/octeon/cvmx-pexp-defs.h | 229 ++ + 7 files changed, 9341 insertions(+), 0 deletions(-) + create mode 100644 arch/mips/include/asm/octeon/cvmx-npei-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-npi-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-pci-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-pcieep-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-pciercx-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-pescx-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-pexp-defs.h + +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-npei-defs.h +@@ -0,0 +1,2560 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_NPEI_DEFS_H__ ++#define __CVMX_NPEI_DEFS_H__ ++ ++#define CVMX_NPEI_BAR1_INDEXX(offset) \ ++ (0x0000000000000000ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_BIST_STATUS \ ++ (0x0000000000000580ull) ++#define CVMX_NPEI_BIST_STATUS2 \ ++ (0x0000000000000680ull) ++#define CVMX_NPEI_CTL_PORT0 \ ++ (0x0000000000000250ull) ++#define CVMX_NPEI_CTL_PORT1 \ ++ (0x0000000000000260ull) ++#define CVMX_NPEI_CTL_STATUS \ ++ (0x0000000000000570ull) ++#define CVMX_NPEI_CTL_STATUS2 \ ++ (0x0000000000003C00ull) ++#define CVMX_NPEI_DATA_OUT_CNT \ ++ (0x00000000000005F0ull) ++#define CVMX_NPEI_DBG_DATA \ ++ (0x0000000000000510ull) ++#define CVMX_NPEI_DBG_SELECT \ ++ (0x0000000000000500ull) ++#define CVMX_NPEI_DMA0_INT_LEVEL \ ++ (0x00000000000005C0ull) ++#define CVMX_NPEI_DMA1_INT_LEVEL \ ++ (0x00000000000005D0ull) ++#define CVMX_NPEI_DMAX_COUNTS(offset) \ ++ (0x0000000000000450ull + (((offset) & 7) * 16)) ++#define CVMX_NPEI_DMAX_DBELL(offset) \ ++ (0x00000000000003B0ull + (((offset) & 7) * 16)) ++#define CVMX_NPEI_DMAX_IBUFF_SADDR(offset) \ ++ (0x0000000000000400ull + (((offset) & 7) * 16)) ++#define CVMX_NPEI_DMAX_NADDR(offset) \ ++ (0x00000000000004A0ull + (((offset) & 7) * 16)) ++#define CVMX_NPEI_DMA_CNTS \ ++ (0x00000000000005E0ull) ++#define CVMX_NPEI_DMA_CONTROL \ ++ (0x00000000000003A0ull) ++#define CVMX_NPEI_INT_A_ENB \ ++ (0x0000000000000560ull) ++#define CVMX_NPEI_INT_A_ENB2 \ ++ (0x0000000000003CE0ull) ++#define CVMX_NPEI_INT_A_SUM \ ++ (0x0000000000000550ull) ++#define CVMX_NPEI_INT_ENB \ ++ (0x0000000000000540ull) ++#define CVMX_NPEI_INT_ENB2 \ ++ (0x0000000000003CD0ull) ++#define CVMX_NPEI_INT_INFO \ ++ (0x0000000000000590ull) ++#define CVMX_NPEI_INT_SUM \ ++ (0x0000000000000530ull) ++#define CVMX_NPEI_INT_SUM2 \ ++ (0x0000000000003CC0ull) ++#define CVMX_NPEI_LAST_WIN_RDATA0 \ ++ (0x0000000000000600ull) ++#define CVMX_NPEI_LAST_WIN_RDATA1 \ ++ (0x0000000000000610ull) ++#define CVMX_NPEI_MEM_ACCESS_CTL \ ++ (0x00000000000004F0ull) ++#define CVMX_NPEI_MEM_ACCESS_SUBIDX(offset) \ ++ (0x0000000000000340ull + (((offset) & 31) * 16) - 16 * 12) ++#define CVMX_NPEI_MSI_ENB0 \ ++ (0x0000000000003C50ull) ++#define CVMX_NPEI_MSI_ENB1 \ ++ (0x0000000000003C60ull) ++#define CVMX_NPEI_MSI_ENB2 \ ++ (0x0000000000003C70ull) ++#define CVMX_NPEI_MSI_ENB3 \ ++ (0x0000000000003C80ull) ++#define CVMX_NPEI_MSI_RCV0 \ ++ (0x0000000000003C10ull) ++#define CVMX_NPEI_MSI_RCV1 \ ++ (0x0000000000003C20ull) ++#define CVMX_NPEI_MSI_RCV2 \ ++ (0x0000000000003C30ull) ++#define CVMX_NPEI_MSI_RCV3 \ ++ (0x0000000000003C40ull) ++#define CVMX_NPEI_MSI_RD_MAP \ ++ (0x0000000000003CA0ull) ++#define CVMX_NPEI_MSI_W1C_ENB0 \ ++ (0x0000000000003CF0ull) ++#define CVMX_NPEI_MSI_W1C_ENB1 \ ++ (0x0000000000003D00ull) ++#define CVMX_NPEI_MSI_W1C_ENB2 \ ++ (0x0000000000003D10ull) ++#define CVMX_NPEI_MSI_W1C_ENB3 \ ++ (0x0000000000003D20ull) ++#define CVMX_NPEI_MSI_W1S_ENB0 \ ++ (0x0000000000003D30ull) ++#define CVMX_NPEI_MSI_W1S_ENB1 \ ++ (0x0000000000003D40ull) ++#define CVMX_NPEI_MSI_W1S_ENB2 \ ++ (0x0000000000003D50ull) ++#define CVMX_NPEI_MSI_W1S_ENB3 \ ++ (0x0000000000003D60ull) ++#define CVMX_NPEI_MSI_WR_MAP \ ++ (0x0000000000003C90ull) ++#define CVMX_NPEI_PCIE_CREDIT_CNT \ ++ (0x0000000000003D70ull) ++#define CVMX_NPEI_PCIE_MSI_RCV \ ++ (0x0000000000003CB0ull) ++#define CVMX_NPEI_PCIE_MSI_RCV_B1 \ ++ (0x0000000000000650ull) ++#define CVMX_NPEI_PCIE_MSI_RCV_B2 \ ++ (0x0000000000000660ull) ++#define CVMX_NPEI_PCIE_MSI_RCV_B3 \ ++ (0x0000000000000670ull) ++#define CVMX_NPEI_PKTX_CNTS(offset) \ ++ (0x0000000000002400ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_INSTR_BADDR(offset) \ ++ (0x0000000000002800ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \ ++ (0x0000000000002C00ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \ ++ (0x0000000000003000ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_INSTR_HEADER(offset) \ ++ (0x0000000000003400ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_IN_BP(offset) \ ++ (0x0000000000003800ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_SLIST_BADDR(offset) \ ++ (0x0000000000001400ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \ ++ (0x0000000000001800ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \ ++ (0x0000000000001C00ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKT_CNT_INT \ ++ (0x0000000000001110ull) ++#define CVMX_NPEI_PKT_CNT_INT_ENB \ ++ (0x0000000000001130ull) ++#define CVMX_NPEI_PKT_DATA_OUT_ES \ ++ (0x00000000000010B0ull) ++#define CVMX_NPEI_PKT_DATA_OUT_NS \ ++ (0x00000000000010A0ull) ++#define CVMX_NPEI_PKT_DATA_OUT_ROR \ ++ (0x0000000000001090ull) ++#define CVMX_NPEI_PKT_DPADDR \ ++ (0x0000000000001080ull) ++#define CVMX_NPEI_PKT_INPUT_CONTROL \ ++ (0x0000000000001150ull) ++#define CVMX_NPEI_PKT_INSTR_ENB \ ++ (0x0000000000001000ull) ++#define CVMX_NPEI_PKT_INSTR_RD_SIZE \ ++ (0x0000000000001190ull) ++#define CVMX_NPEI_PKT_INSTR_SIZE \ ++ (0x0000000000001020ull) ++#define CVMX_NPEI_PKT_INT_LEVELS \ ++ (0x0000000000001100ull) ++#define CVMX_NPEI_PKT_IN_BP \ ++ (0x00000000000006B0ull) ++#define CVMX_NPEI_PKT_IN_DONEX_CNTS(offset) \ ++ (0x0000000000002000ull + (((offset) & 31) * 16)) ++#define CVMX_NPEI_PKT_IN_INSTR_COUNTS \ ++ (0x00000000000006A0ull) ++#define CVMX_NPEI_PKT_IN_PCIE_PORT \ ++ (0x00000000000011A0ull) ++#define CVMX_NPEI_PKT_IPTR \ ++ (0x0000000000001070ull) ++#define CVMX_NPEI_PKT_OUTPUT_WMARK \ ++ (0x0000000000001160ull) ++#define CVMX_NPEI_PKT_OUT_BMODE \ ++ (0x00000000000010D0ull) ++#define CVMX_NPEI_PKT_OUT_ENB \ ++ (0x0000000000001010ull) ++#define CVMX_NPEI_PKT_PCIE_PORT \ ++ (0x00000000000010E0ull) ++#define CVMX_NPEI_PKT_PORT_IN_RST \ ++ (0x0000000000000690ull) ++#define CVMX_NPEI_PKT_SLIST_ES \ ++ (0x0000000000001050ull) ++#define CVMX_NPEI_PKT_SLIST_ID_SIZE \ ++ (0x0000000000001180ull) ++#define CVMX_NPEI_PKT_SLIST_NS \ ++ (0x0000000000001040ull) ++#define CVMX_NPEI_PKT_SLIST_ROR \ ++ (0x0000000000001030ull) ++#define CVMX_NPEI_PKT_TIME_INT \ ++ (0x0000000000001120ull) ++#define CVMX_NPEI_PKT_TIME_INT_ENB \ ++ (0x0000000000001140ull) ++#define CVMX_NPEI_RSL_INT_BLOCKS \ ++ (0x0000000000000520ull) ++#define CVMX_NPEI_SCRATCH_1 \ ++ (0x0000000000000270ull) ++#define CVMX_NPEI_STATE1 \ ++ (0x0000000000000620ull) ++#define CVMX_NPEI_STATE2 \ ++ (0x0000000000000630ull) ++#define CVMX_NPEI_STATE3 \ ++ (0x0000000000000640ull) ++#define CVMX_NPEI_WINDOW_CTL \ ++ (0x0000000000000380ull) ++#define CVMX_NPEI_WIN_RD_ADDR \ ++ (0x0000000000000210ull) ++#define CVMX_NPEI_WIN_RD_DATA \ ++ (0x0000000000000240ull) ++#define CVMX_NPEI_WIN_WR_ADDR \ ++ (0x0000000000000200ull) ++#define CVMX_NPEI_WIN_WR_DATA \ ++ (0x0000000000000220ull) ++#define CVMX_NPEI_WIN_WR_MASK \ ++ (0x0000000000000230ull) ++ ++union cvmx_npei_bar1_indexx { ++ uint32_t u32; ++ struct cvmx_npei_bar1_indexx_s { ++ uint32_t reserved_18_31:14; ++ uint32_t addr_idx:14; ++ uint32_t ca:1; ++ uint32_t end_swp:2; ++ uint32_t addr_v:1; ++ } s; ++ struct cvmx_npei_bar1_indexx_s cn52xx; ++ struct cvmx_npei_bar1_indexx_s cn52xxp1; ++ struct cvmx_npei_bar1_indexx_s cn56xx; ++ struct cvmx_npei_bar1_indexx_s cn56xxp1; ++}; ++ ++union cvmx_npei_bist_status { ++ uint64_t u64; ++ struct cvmx_npei_bist_status_s { ++ uint64_t pkt_rdf:1; ++ uint64_t pkt_pmem:1; ++ uint64_t pkt_p1:1; ++ uint64_t reserved_60_60:1; ++ uint64_t pcr_gim:1; ++ uint64_t pkt_pif:1; ++ uint64_t pcsr_int:1; ++ uint64_t pcsr_im:1; ++ uint64_t pcsr_cnt:1; ++ uint64_t pcsr_id:1; ++ uint64_t pcsr_sl:1; ++ uint64_t reserved_50_52:3; ++ uint64_t pkt_ind:1; ++ uint64_t pkt_slm:1; ++ uint64_t reserved_36_47:12; ++ uint64_t d0_pst:1; ++ uint64_t d1_pst:1; ++ uint64_t d2_pst:1; ++ uint64_t d3_pst:1; ++ uint64_t reserved_31_31:1; ++ uint64_t n2p0_c:1; ++ uint64_t n2p0_o:1; ++ uint64_t n2p1_c:1; ++ uint64_t n2p1_o:1; ++ uint64_t cpl_p0:1; ++ uint64_t cpl_p1:1; ++ uint64_t p2n1_po:1; ++ uint64_t p2n1_no:1; ++ uint64_t p2n1_co:1; ++ uint64_t p2n0_po:1; ++ uint64_t p2n0_no:1; ++ uint64_t p2n0_co:1; ++ uint64_t p2n0_c0:1; ++ uint64_t p2n0_c1:1; ++ uint64_t p2n0_n:1; ++ uint64_t p2n0_p0:1; ++ uint64_t p2n0_p1:1; ++ uint64_t p2n1_c0:1; ++ uint64_t p2n1_c1:1; ++ uint64_t p2n1_n:1; ++ uint64_t p2n1_p0:1; ++ uint64_t p2n1_p1:1; ++ uint64_t csm0:1; ++ uint64_t csm1:1; ++ uint64_t dif0:1; ++ uint64_t dif1:1; ++ uint64_t dif2:1; ++ uint64_t dif3:1; ++ uint64_t reserved_2_2:1; ++ uint64_t msi:1; ++ uint64_t ncb_cmd:1; ++ } s; ++ struct cvmx_npei_bist_status_cn52xx { ++ uint64_t pkt_rdf:1; ++ uint64_t pkt_pmem:1; ++ uint64_t pkt_p1:1; ++ uint64_t reserved_60_60:1; ++ uint64_t pcr_gim:1; ++ uint64_t pkt_pif:1; ++ uint64_t pcsr_int:1; ++ uint64_t pcsr_im:1; ++ uint64_t pcsr_cnt:1; ++ uint64_t pcsr_id:1; ++ uint64_t pcsr_sl:1; ++ uint64_t pkt_imem:1; ++ uint64_t pkt_pfm:1; ++ uint64_t pkt_pof:1; ++ uint64_t reserved_48_49:2; ++ uint64_t pkt_pop0:1; ++ uint64_t pkt_pop1:1; ++ uint64_t d0_mem:1; ++ uint64_t d1_mem:1; ++ uint64_t d2_mem:1; ++ uint64_t d3_mem:1; ++ uint64_t d4_mem:1; ++ uint64_t ds_mem:1; ++ uint64_t reserved_36_39:4; ++ uint64_t d0_pst:1; ++ uint64_t d1_pst:1; ++ uint64_t d2_pst:1; ++ uint64_t d3_pst:1; ++ uint64_t d4_pst:1; ++ uint64_t n2p0_c:1; ++ uint64_t n2p0_o:1; ++ uint64_t n2p1_c:1; ++ uint64_t n2p1_o:1; ++ uint64_t cpl_p0:1; ++ uint64_t cpl_p1:1; ++ uint64_t p2n1_po:1; ++ uint64_t p2n1_no:1; ++ uint64_t p2n1_co:1; ++ uint64_t p2n0_po:1; ++ uint64_t p2n0_no:1; ++ uint64_t p2n0_co:1; ++ uint64_t p2n0_c0:1; ++ uint64_t p2n0_c1:1; ++ uint64_t p2n0_n:1; ++ uint64_t p2n0_p0:1; ++ uint64_t p2n0_p1:1; ++ uint64_t p2n1_c0:1; ++ uint64_t p2n1_c1:1; ++ uint64_t p2n1_n:1; ++ uint64_t p2n1_p0:1; ++ uint64_t p2n1_p1:1; ++ uint64_t csm0:1; ++ uint64_t csm1:1; ++ uint64_t dif0:1; ++ uint64_t dif1:1; ++ uint64_t dif2:1; ++ uint64_t dif3:1; ++ uint64_t dif4:1; ++ uint64_t msi:1; ++ uint64_t ncb_cmd:1; ++ } cn52xx; ++ struct cvmx_npei_bist_status_cn52xxp1 { ++ uint64_t reserved_46_63:18; ++ uint64_t d0_mem0:1; ++ uint64_t d1_mem1:1; ++ uint64_t d2_mem2:1; ++ uint64_t d3_mem3:1; ++ uint64_t dr0_mem:1; ++ uint64_t d0_mem:1; ++ uint64_t d1_mem:1; ++ uint64_t d2_mem:1; ++ uint64_t d3_mem:1; ++ uint64_t dr1_mem:1; ++ uint64_t d0_pst:1; ++ uint64_t d1_pst:1; ++ uint64_t d2_pst:1; ++ uint64_t d3_pst:1; ++ uint64_t dr2_mem:1; ++ uint64_t n2p0_c:1; ++ uint64_t n2p0_o:1; ++ uint64_t n2p1_c:1; ++ uint64_t n2p1_o:1; ++ uint64_t cpl_p0:1; ++ uint64_t cpl_p1:1; ++ uint64_t p2n1_po:1; ++ uint64_t p2n1_no:1; ++ uint64_t p2n1_co:1; ++ uint64_t p2n0_po:1; ++ uint64_t p2n0_no:1; ++ uint64_t p2n0_co:1; ++ uint64_t p2n0_c0:1; ++ uint64_t p2n0_c1:1; ++ uint64_t p2n0_n:1; ++ uint64_t p2n0_p0:1; ++ uint64_t p2n0_p1:1; ++ uint64_t p2n1_c0:1; ++ uint64_t p2n1_c1:1; ++ uint64_t p2n1_n:1; ++ uint64_t p2n1_p0:1; ++ uint64_t p2n1_p1:1; ++ uint64_t csm0:1; ++ uint64_t csm1:1; ++ uint64_t dif0:1; ++ uint64_t dif1:1; ++ uint64_t dif2:1; ++ uint64_t dif3:1; ++ uint64_t dr3_mem:1; ++ uint64_t msi:1; ++ uint64_t ncb_cmd:1; ++ } cn52xxp1; ++ struct cvmx_npei_bist_status_cn56xx { ++ uint64_t pkt_rdf:1; ++ uint64_t reserved_60_62:3; ++ uint64_t pcr_gim:1; ++ uint64_t pkt_pif:1; ++ uint64_t pcsr_int:1; ++ uint64_t pcsr_im:1; ++ uint64_t pcsr_cnt:1; ++ uint64_t pcsr_id:1; ++ uint64_t pcsr_sl:1; ++ uint64_t pkt_imem:1; ++ uint64_t pkt_pfm:1; ++ uint64_t pkt_pof:1; ++ uint64_t reserved_48_49:2; ++ uint64_t pkt_pop0:1; ++ uint64_t pkt_pop1:1; ++ uint64_t d0_mem:1; ++ uint64_t d1_mem:1; ++ uint64_t d2_mem:1; ++ uint64_t d3_mem:1; ++ uint64_t d4_mem:1; ++ uint64_t ds_mem:1; ++ uint64_t reserved_36_39:4; ++ uint64_t d0_pst:1; ++ uint64_t d1_pst:1; ++ uint64_t d2_pst:1; ++ uint64_t d3_pst:1; ++ uint64_t d4_pst:1; ++ uint64_t n2p0_c:1; ++ uint64_t n2p0_o:1; ++ uint64_t n2p1_c:1; ++ uint64_t n2p1_o:1; ++ uint64_t cpl_p0:1; ++ uint64_t cpl_p1:1; ++ uint64_t p2n1_po:1; ++ uint64_t p2n1_no:1; ++ uint64_t p2n1_co:1; ++ uint64_t p2n0_po:1; ++ uint64_t p2n0_no:1; ++ uint64_t p2n0_co:1; ++ uint64_t p2n0_c0:1; ++ uint64_t p2n0_c1:1; ++ uint64_t p2n0_n:1; ++ uint64_t p2n0_p0:1; ++ uint64_t p2n0_p1:1; ++ uint64_t p2n1_c0:1; ++ uint64_t p2n1_c1:1; ++ uint64_t p2n1_n:1; ++ uint64_t p2n1_p0:1; ++ uint64_t p2n1_p1:1; ++ uint64_t csm0:1; ++ uint64_t csm1:1; ++ uint64_t dif0:1; ++ uint64_t dif1:1; ++ uint64_t dif2:1; ++ uint64_t dif3:1; ++ uint64_t dif4:1; ++ uint64_t msi:1; ++ uint64_t ncb_cmd:1; ++ } cn56xx; ++ struct cvmx_npei_bist_status_cn56xxp1 { ++ uint64_t reserved_58_63:6; ++ uint64_t pcsr_int:1; ++ uint64_t pcsr_im:1; ++ uint64_t pcsr_cnt:1; ++ uint64_t pcsr_id:1; ++ uint64_t pcsr_sl:1; ++ uint64_t pkt_pout:1; ++ uint64_t pkt_imem:1; ++ uint64_t pkt_cntm:1; ++ uint64_t pkt_ind:1; ++ uint64_t pkt_slm:1; ++ uint64_t pkt_odf:1; ++ uint64_t pkt_oif:1; ++ uint64_t pkt_out:1; ++ uint64_t pkt_i0:1; ++ uint64_t pkt_i1:1; ++ uint64_t pkt_s0:1; ++ uint64_t pkt_s1:1; ++ uint64_t d0_mem:1; ++ uint64_t d1_mem:1; ++ uint64_t d2_mem:1; ++ uint64_t d3_mem:1; ++ uint64_t d4_mem:1; ++ uint64_t d0_pst:1; ++ uint64_t d1_pst:1; ++ uint64_t d2_pst:1; ++ uint64_t d3_pst:1; ++ uint64_t d4_pst:1; ++ uint64_t n2p0_c:1; ++ uint64_t n2p0_o:1; ++ uint64_t n2p1_c:1; ++ uint64_t n2p1_o:1; ++ uint64_t cpl_p0:1; ++ uint64_t cpl_p1:1; ++ uint64_t p2n1_po:1; ++ uint64_t p2n1_no:1; ++ uint64_t p2n1_co:1; ++ uint64_t p2n0_po:1; ++ uint64_t p2n0_no:1; ++ uint64_t p2n0_co:1; ++ uint64_t p2n0_c0:1; ++ uint64_t p2n0_c1:1; ++ uint64_t p2n0_n:1; ++ uint64_t p2n0_p0:1; ++ uint64_t p2n0_p1:1; ++ uint64_t p2n1_c0:1; ++ uint64_t p2n1_c1:1; ++ uint64_t p2n1_n:1; ++ uint64_t p2n1_p0:1; ++ uint64_t p2n1_p1:1; ++ uint64_t csm0:1; ++ uint64_t csm1:1; ++ uint64_t dif0:1; ++ uint64_t dif1:1; ++ uint64_t dif2:1; ++ uint64_t dif3:1; ++ uint64_t dif4:1; ++ uint64_t msi:1; ++ uint64_t ncb_cmd:1; ++ } cn56xxp1; ++}; ++ ++union cvmx_npei_bist_status2 { ++ uint64_t u64; ++ struct cvmx_npei_bist_status2_s { ++ uint64_t reserved_5_63:59; ++ uint64_t psc_p0:1; ++ uint64_t psc_p1:1; ++ uint64_t pkt_gd:1; ++ uint64_t pkt_gl:1; ++ uint64_t pkt_blk:1; ++ } s; ++ struct cvmx_npei_bist_status2_s cn52xx; ++ struct cvmx_npei_bist_status2_s cn56xx; ++}; ++ ++union cvmx_npei_ctl_port0 { ++ uint64_t u64; ++ struct cvmx_npei_ctl_port0_s { ++ uint64_t reserved_21_63:43; ++ uint64_t waitl_com:1; ++ uint64_t intd:1; ++ uint64_t intc:1; ++ uint64_t intb:1; ++ uint64_t inta:1; ++ uint64_t intd_map:2; ++ uint64_t intc_map:2; ++ uint64_t intb_map:2; ++ uint64_t inta_map:2; ++ uint64_t ctlp_ro:1; ++ uint64_t reserved_6_6:1; ++ uint64_t ptlp_ro:1; ++ uint64_t bar2_enb:1; ++ uint64_t bar2_esx:2; ++ uint64_t bar2_cax:1; ++ uint64_t wait_com:1; ++ } s; ++ struct cvmx_npei_ctl_port0_s cn52xx; ++ struct cvmx_npei_ctl_port0_s cn52xxp1; ++ struct cvmx_npei_ctl_port0_s cn56xx; ++ struct cvmx_npei_ctl_port0_s cn56xxp1; ++}; ++ ++union cvmx_npei_ctl_port1 { ++ uint64_t u64; ++ struct cvmx_npei_ctl_port1_s { ++ uint64_t reserved_21_63:43; ++ uint64_t waitl_com:1; ++ uint64_t intd:1; ++ uint64_t intc:1; ++ uint64_t intb:1; ++ uint64_t inta:1; ++ uint64_t intd_map:2; ++ uint64_t intc_map:2; ++ uint64_t intb_map:2; ++ uint64_t inta_map:2; ++ uint64_t ctlp_ro:1; ++ uint64_t reserved_6_6:1; ++ uint64_t ptlp_ro:1; ++ uint64_t bar2_enb:1; ++ uint64_t bar2_esx:2; ++ uint64_t bar2_cax:1; ++ uint64_t wait_com:1; ++ } s; ++ struct cvmx_npei_ctl_port1_s cn52xx; ++ struct cvmx_npei_ctl_port1_s cn52xxp1; ++ struct cvmx_npei_ctl_port1_s cn56xx; ++ struct cvmx_npei_ctl_port1_s cn56xxp1; ++}; ++ ++union cvmx_npei_ctl_status { ++ uint64_t u64; ++ struct cvmx_npei_ctl_status_s { ++ uint64_t reserved_44_63:20; ++ uint64_t p1_ntags:6; ++ uint64_t p0_ntags:6; ++ uint64_t cfg_rtry:16; ++ uint64_t ring_en:1; ++ uint64_t lnk_rst:1; ++ uint64_t arb:1; ++ uint64_t pkt_bp:4; ++ uint64_t host_mode:1; ++ uint64_t chip_rev:8; ++ } s; ++ struct cvmx_npei_ctl_status_s cn52xx; ++ struct cvmx_npei_ctl_status_cn52xxp1 { ++ uint64_t reserved_44_63:20; ++ uint64_t p1_ntags:6; ++ uint64_t p0_ntags:6; ++ uint64_t cfg_rtry:16; ++ uint64_t reserved_15_15:1; ++ uint64_t lnk_rst:1; ++ uint64_t arb:1; ++ uint64_t reserved_9_12:4; ++ uint64_t host_mode:1; ++ uint64_t chip_rev:8; ++ } cn52xxp1; ++ struct cvmx_npei_ctl_status_s cn56xx; ++ struct cvmx_npei_ctl_status_cn56xxp1 { ++ uint64_t reserved_16_63:48; ++ uint64_t ring_en:1; ++ uint64_t lnk_rst:1; ++ uint64_t arb:1; ++ uint64_t pkt_bp:4; ++ uint64_t host_mode:1; ++ uint64_t chip_rev:8; ++ } cn56xxp1; ++}; ++ ++union cvmx_npei_ctl_status2 { ++ uint64_t u64; ++ struct cvmx_npei_ctl_status2_s { ++ uint64_t reserved_16_63:48; ++ uint64_t mps:1; ++ uint64_t mrrs:3; ++ uint64_t c1_w_flt:1; ++ uint64_t c0_w_flt:1; ++ uint64_t c1_b1_s:3; ++ uint64_t c0_b1_s:3; ++ uint64_t c1_wi_d:1; ++ uint64_t c1_b0_d:1; ++ uint64_t c0_wi_d:1; ++ uint64_t c0_b0_d:1; ++ } s; ++ struct cvmx_npei_ctl_status2_s cn52xx; ++ struct cvmx_npei_ctl_status2_s cn52xxp1; ++ struct cvmx_npei_ctl_status2_s cn56xx; ++ struct cvmx_npei_ctl_status2_s cn56xxp1; ++}; ++ ++union cvmx_npei_data_out_cnt { ++ uint64_t u64; ++ struct cvmx_npei_data_out_cnt_s { ++ uint64_t reserved_44_63:20; ++ uint64_t p1_ucnt:16; ++ uint64_t p1_fcnt:6; ++ uint64_t p0_ucnt:16; ++ uint64_t p0_fcnt:6; ++ } s; ++ struct cvmx_npei_data_out_cnt_s cn52xx; ++ struct cvmx_npei_data_out_cnt_s cn52xxp1; ++ struct cvmx_npei_data_out_cnt_s cn56xx; ++ struct cvmx_npei_data_out_cnt_s cn56xxp1; ++}; ++ ++union cvmx_npei_dbg_data { ++ uint64_t u64; ++ struct cvmx_npei_dbg_data_s { ++ uint64_t reserved_28_63:36; ++ uint64_t qlm0_rev_lanes:1; ++ uint64_t reserved_25_26:2; ++ uint64_t qlm1_spd:2; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } s; ++ struct cvmx_npei_dbg_data_cn52xx { ++ uint64_t reserved_29_63:35; ++ uint64_t qlm0_link_width:1; ++ uint64_t qlm0_rev_lanes:1; ++ uint64_t qlm1_mode:2; ++ uint64_t qlm1_spd:2; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } cn52xx; ++ struct cvmx_npei_dbg_data_cn52xx cn52xxp1; ++ struct cvmx_npei_dbg_data_cn56xx { ++ uint64_t reserved_29_63:35; ++ uint64_t qlm2_rev_lanes:1; ++ uint64_t qlm0_rev_lanes:1; ++ uint64_t qlm3_spd:2; ++ uint64_t qlm1_spd:2; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } cn56xx; ++ struct cvmx_npei_dbg_data_cn56xx cn56xxp1; ++}; ++ ++union cvmx_npei_dbg_select { ++ uint64_t u64; ++ struct cvmx_npei_dbg_select_s { ++ uint64_t reserved_16_63:48; ++ uint64_t dbg_sel:16; ++ } s; ++ struct cvmx_npei_dbg_select_s cn52xx; ++ struct cvmx_npei_dbg_select_s cn52xxp1; ++ struct cvmx_npei_dbg_select_s cn56xx; ++ struct cvmx_npei_dbg_select_s cn56xxp1; ++}; ++ ++union cvmx_npei_dmax_counts { ++ uint64_t u64; ++ struct cvmx_npei_dmax_counts_s { ++ uint64_t reserved_39_63:25; ++ uint64_t fcnt:7; ++ uint64_t dbell:32; ++ } s; ++ struct cvmx_npei_dmax_counts_s cn52xx; ++ struct cvmx_npei_dmax_counts_s cn52xxp1; ++ struct cvmx_npei_dmax_counts_s cn56xx; ++ struct cvmx_npei_dmax_counts_s cn56xxp1; ++}; ++ ++union cvmx_npei_dmax_dbell { ++ uint32_t u32; ++ struct cvmx_npei_dmax_dbell_s { ++ uint32_t reserved_16_31:16; ++ uint32_t dbell:16; ++ } s; ++ struct cvmx_npei_dmax_dbell_s cn52xx; ++ struct cvmx_npei_dmax_dbell_s cn52xxp1; ++ struct cvmx_npei_dmax_dbell_s cn56xx; ++ struct cvmx_npei_dmax_dbell_s cn56xxp1; ++}; ++ ++union cvmx_npei_dmax_ibuff_saddr { ++ uint64_t u64; ++ struct cvmx_npei_dmax_ibuff_saddr_s { ++ uint64_t reserved_37_63:27; ++ uint64_t idle:1; ++ uint64_t saddr:29; ++ uint64_t reserved_0_6:7; ++ } s; ++ struct cvmx_npei_dmax_ibuff_saddr_cn52xx { ++ uint64_t reserved_36_63:28; ++ uint64_t saddr:29; ++ uint64_t reserved_0_6:7; ++ } cn52xx; ++ struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn52xxp1; ++ struct cvmx_npei_dmax_ibuff_saddr_s cn56xx; ++ struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn56xxp1; ++}; ++ ++union cvmx_npei_dmax_naddr { ++ uint64_t u64; ++ struct cvmx_npei_dmax_naddr_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_npei_dmax_naddr_s cn52xx; ++ struct cvmx_npei_dmax_naddr_s cn52xxp1; ++ struct cvmx_npei_dmax_naddr_s cn56xx; ++ struct cvmx_npei_dmax_naddr_s cn56xxp1; ++}; ++ ++union cvmx_npei_dma0_int_level { ++ uint64_t u64; ++ struct cvmx_npei_dma0_int_level_s { ++ uint64_t time:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_npei_dma0_int_level_s cn52xx; ++ struct cvmx_npei_dma0_int_level_s cn52xxp1; ++ struct cvmx_npei_dma0_int_level_s cn56xx; ++ struct cvmx_npei_dma0_int_level_s cn56xxp1; ++}; ++ ++union cvmx_npei_dma1_int_level { ++ uint64_t u64; ++ struct cvmx_npei_dma1_int_level_s { ++ uint64_t time:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_npei_dma1_int_level_s cn52xx; ++ struct cvmx_npei_dma1_int_level_s cn52xxp1; ++ struct cvmx_npei_dma1_int_level_s cn56xx; ++ struct cvmx_npei_dma1_int_level_s cn56xxp1; ++}; ++ ++union cvmx_npei_dma_cnts { ++ uint64_t u64; ++ struct cvmx_npei_dma_cnts_s { ++ uint64_t dma1:32; ++ uint64_t dma0:32; ++ } s; ++ struct cvmx_npei_dma_cnts_s cn52xx; ++ struct cvmx_npei_dma_cnts_s cn52xxp1; ++ struct cvmx_npei_dma_cnts_s cn56xx; ++ struct cvmx_npei_dma_cnts_s cn56xxp1; ++}; ++ ++union cvmx_npei_dma_control { ++ uint64_t u64; ++ struct cvmx_npei_dma_control_s { ++ uint64_t reserved_39_63:25; ++ uint64_t dma4_enb:1; ++ uint64_t dma3_enb:1; ++ uint64_t dma2_enb:1; ++ uint64_t dma1_enb:1; ++ uint64_t dma0_enb:1; ++ uint64_t b0_lend:1; ++ uint64_t dwb_denb:1; ++ uint64_t dwb_ichk:9; ++ uint64_t fpa_que:3; ++ uint64_t o_add1:1; ++ uint64_t o_ro:1; ++ uint64_t o_ns:1; ++ uint64_t o_es:2; ++ uint64_t o_mode:1; ++ uint64_t csize:14; ++ } s; ++ struct cvmx_npei_dma_control_s cn52xx; ++ struct cvmx_npei_dma_control_cn52xxp1 { ++ uint64_t reserved_38_63:26; ++ uint64_t dma3_enb:1; ++ uint64_t dma2_enb:1; ++ uint64_t dma1_enb:1; ++ uint64_t dma0_enb:1; ++ uint64_t b0_lend:1; ++ uint64_t dwb_denb:1; ++ uint64_t dwb_ichk:9; ++ uint64_t fpa_que:3; ++ uint64_t o_add1:1; ++ uint64_t o_ro:1; ++ uint64_t o_ns:1; ++ uint64_t o_es:2; ++ uint64_t o_mode:1; ++ uint64_t csize:14; ++ } cn52xxp1; ++ struct cvmx_npei_dma_control_s cn56xx; ++ struct cvmx_npei_dma_control_s cn56xxp1; ++}; ++ ++union cvmx_npei_int_a_enb { ++ uint64_t u64; ++ struct cvmx_npei_int_a_enb_s { ++ uint64_t reserved_10_63:54; ++ uint64_t pout_err:1; ++ uint64_t pin_bp:1; ++ uint64_t p1_rdlk:1; ++ uint64_t p0_rdlk:1; ++ uint64_t pgl_err:1; ++ uint64_t pdi_err:1; ++ uint64_t pop_err:1; ++ uint64_t pins_err:1; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } s; ++ struct cvmx_npei_int_a_enb_cn52xx { ++ uint64_t reserved_8_63:56; ++ uint64_t p1_rdlk:1; ++ uint64_t p0_rdlk:1; ++ uint64_t pgl_err:1; ++ uint64_t pdi_err:1; ++ uint64_t pop_err:1; ++ uint64_t pins_err:1; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } cn52xx; ++ struct cvmx_npei_int_a_enb_cn52xxp1 { ++ uint64_t reserved_2_63:62; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } cn52xxp1; ++ struct cvmx_npei_int_a_enb_s cn56xx; ++}; ++ ++union cvmx_npei_int_a_enb2 { ++ uint64_t u64; ++ struct cvmx_npei_int_a_enb2_s { ++ uint64_t reserved_10_63:54; ++ uint64_t pout_err:1; ++ uint64_t pin_bp:1; ++ uint64_t p1_rdlk:1; ++ uint64_t p0_rdlk:1; ++ uint64_t pgl_err:1; ++ uint64_t pdi_err:1; ++ uint64_t pop_err:1; ++ uint64_t pins_err:1; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } s; ++ struct cvmx_npei_int_a_enb2_cn52xx { ++ uint64_t reserved_8_63:56; ++ uint64_t p1_rdlk:1; ++ uint64_t p0_rdlk:1; ++ uint64_t pgl_err:1; ++ uint64_t pdi_err:1; ++ uint64_t pop_err:1; ++ uint64_t pins_err:1; ++ uint64_t reserved_0_1:2; ++ } cn52xx; ++ struct cvmx_npei_int_a_enb2_cn52xxp1 { ++ uint64_t reserved_2_63:62; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } cn52xxp1; ++ struct cvmx_npei_int_a_enb2_s cn56xx; ++}; ++ ++union cvmx_npei_int_a_sum { ++ uint64_t u64; ++ struct cvmx_npei_int_a_sum_s { ++ uint64_t reserved_10_63:54; ++ uint64_t pout_err:1; ++ uint64_t pin_bp:1; ++ uint64_t p1_rdlk:1; ++ uint64_t p0_rdlk:1; ++ uint64_t pgl_err:1; ++ uint64_t pdi_err:1; ++ uint64_t pop_err:1; ++ uint64_t pins_err:1; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } s; ++ struct cvmx_npei_int_a_sum_cn52xx { ++ uint64_t reserved_8_63:56; ++ uint64_t p1_rdlk:1; ++ uint64_t p0_rdlk:1; ++ uint64_t pgl_err:1; ++ uint64_t pdi_err:1; ++ uint64_t pop_err:1; ++ uint64_t pins_err:1; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } cn52xx; ++ struct cvmx_npei_int_a_sum_cn52xxp1 { ++ uint64_t reserved_2_63:62; ++ uint64_t dma1_cpl:1; ++ uint64_t dma0_cpl:1; ++ } cn52xxp1; ++ struct cvmx_npei_int_a_sum_s cn56xx; ++}; ++ ++union cvmx_npei_int_enb { ++ uint64_t u64; ++ struct cvmx_npei_int_enb_s { ++ uint64_t mio_inta:1; ++ uint64_t reserved_62_62:1; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t dma4dbo:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } s; ++ struct cvmx_npei_int_enb_s cn52xx; ++ struct cvmx_npei_int_enb_cn52xxp1 { ++ uint64_t mio_inta:1; ++ uint64_t reserved_62_62:1; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t reserved_8_8:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn52xxp1; ++ struct cvmx_npei_int_enb_s cn56xx; ++ struct cvmx_npei_int_enb_cn56xxp1 { ++ uint64_t mio_inta:1; ++ uint64_t reserved_61_62:2; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t reserved_29_29:1; ++ uint64_t c1_se:1; ++ uint64_t reserved_27_27:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t reserved_22_22:1; ++ uint64_t c0_se:1; ++ uint64_t reserved_20_20:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t dma4dbo:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn56xxp1; ++}; ++ ++union cvmx_npei_int_enb2 { ++ uint64_t u64; ++ struct cvmx_npei_int_enb2_s { ++ uint64_t reserved_62_63:2; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t dma4dbo:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } s; ++ struct cvmx_npei_int_enb2_s cn52xx; ++ struct cvmx_npei_int_enb2_cn52xxp1 { ++ uint64_t reserved_62_63:2; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t reserved_8_8:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn52xxp1; ++ struct cvmx_npei_int_enb2_s cn56xx; ++ struct cvmx_npei_int_enb2_cn56xxp1 { ++ uint64_t reserved_61_63:3; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t reserved_29_29:1; ++ uint64_t c1_se:1; ++ uint64_t reserved_27_27:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t reserved_22_22:1; ++ uint64_t c0_se:1; ++ uint64_t reserved_20_20:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t dma4dbo:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn56xxp1; ++}; ++ ++union cvmx_npei_int_info { ++ uint64_t u64; ++ struct cvmx_npei_int_info_s { ++ uint64_t reserved_12_63:52; ++ uint64_t pidbof:6; ++ uint64_t psldbof:6; ++ } s; ++ struct cvmx_npei_int_info_s cn52xx; ++ struct cvmx_npei_int_info_s cn56xx; ++ struct cvmx_npei_int_info_s cn56xxp1; ++}; ++ ++union cvmx_npei_int_sum { ++ uint64_t u64; ++ struct cvmx_npei_int_sum_s { ++ uint64_t mio_inta:1; ++ uint64_t reserved_62_62:1; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t dma4dbo:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } s; ++ struct cvmx_npei_int_sum_s cn52xx; ++ struct cvmx_npei_int_sum_cn52xxp1 { ++ uint64_t mio_inta:1; ++ uint64_t reserved_62_62:1; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t reserved_15_18:4; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t reserved_8_8:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn52xxp1; ++ struct cvmx_npei_int_sum_s cn56xx; ++ struct cvmx_npei_int_sum_cn56xxp1 { ++ uint64_t mio_inta:1; ++ uint64_t reserved_61_62:2; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t reserved_29_29:1; ++ uint64_t c1_se:1; ++ uint64_t reserved_27_27:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t reserved_22_22:1; ++ uint64_t c0_se:1; ++ uint64_t reserved_20_20:1; ++ uint64_t c0_aeri:1; ++ uint64_t ptime:1; ++ uint64_t pcnt:1; ++ uint64_t pidbof:1; ++ uint64_t psldbof:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t dma4dbo:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn56xxp1; ++}; ++ ++union cvmx_npei_int_sum2 { ++ uint64_t u64; ++ struct cvmx_npei_int_sum2_s { ++ uint64_t mio_inta:1; ++ uint64_t reserved_62_62:1; ++ uint64_t int_a:1; ++ uint64_t c1_ldwn:1; ++ uint64_t c0_ldwn:1; ++ uint64_t c1_exc:1; ++ uint64_t c0_exc:1; ++ uint64_t c1_up_wf:1; ++ uint64_t c0_up_wf:1; ++ uint64_t c1_un_wf:1; ++ uint64_t c0_un_wf:1; ++ uint64_t c1_un_bx:1; ++ uint64_t c1_un_wi:1; ++ uint64_t c1_un_b2:1; ++ uint64_t c1_un_b1:1; ++ uint64_t c1_un_b0:1; ++ uint64_t c1_up_bx:1; ++ uint64_t c1_up_wi:1; ++ uint64_t c1_up_b2:1; ++ uint64_t c1_up_b1:1; ++ uint64_t c1_up_b0:1; ++ uint64_t c0_un_bx:1; ++ uint64_t c0_un_wi:1; ++ uint64_t c0_un_b2:1; ++ uint64_t c0_un_b1:1; ++ uint64_t c0_un_b0:1; ++ uint64_t c0_up_bx:1; ++ uint64_t c0_up_wi:1; ++ uint64_t c0_up_b2:1; ++ uint64_t c0_up_b1:1; ++ uint64_t c0_up_b0:1; ++ uint64_t c1_hpint:1; ++ uint64_t c1_pmei:1; ++ uint64_t c1_wake:1; ++ uint64_t crs1_dr:1; ++ uint64_t c1_se:1; ++ uint64_t crs1_er:1; ++ uint64_t c1_aeri:1; ++ uint64_t c0_hpint:1; ++ uint64_t c0_pmei:1; ++ uint64_t c0_wake:1; ++ uint64_t crs0_dr:1; ++ uint64_t c0_se:1; ++ uint64_t crs0_er:1; ++ uint64_t c0_aeri:1; ++ uint64_t reserved_15_18:4; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t dma1fi:1; ++ uint64_t dma0fi:1; ++ uint64_t reserved_8_8:1; ++ uint64_t dma3dbo:1; ++ uint64_t dma2dbo:1; ++ uint64_t dma1dbo:1; ++ uint64_t dma0dbo:1; ++ uint64_t iob2big:1; ++ uint64_t bar0_to:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } s; ++ struct cvmx_npei_int_sum2_s cn52xx; ++ struct cvmx_npei_int_sum2_s cn52xxp1; ++ struct cvmx_npei_int_sum2_s cn56xx; ++}; ++ ++union cvmx_npei_last_win_rdata0 { ++ uint64_t u64; ++ struct cvmx_npei_last_win_rdata0_s { ++ uint64_t data:64; ++ } s; ++ struct cvmx_npei_last_win_rdata0_s cn52xx; ++ struct cvmx_npei_last_win_rdata0_s cn52xxp1; ++ struct cvmx_npei_last_win_rdata0_s cn56xx; ++ struct cvmx_npei_last_win_rdata0_s cn56xxp1; ++}; ++ ++union cvmx_npei_last_win_rdata1 { ++ uint64_t u64; ++ struct cvmx_npei_last_win_rdata1_s { ++ uint64_t data:64; ++ } s; ++ struct cvmx_npei_last_win_rdata1_s cn52xx; ++ struct cvmx_npei_last_win_rdata1_s cn52xxp1; ++ struct cvmx_npei_last_win_rdata1_s cn56xx; ++ struct cvmx_npei_last_win_rdata1_s cn56xxp1; ++}; ++ ++union cvmx_npei_mem_access_ctl { ++ uint64_t u64; ++ struct cvmx_npei_mem_access_ctl_s { ++ uint64_t reserved_14_63:50; ++ uint64_t max_word:4; ++ uint64_t timer:10; ++ } s; ++ struct cvmx_npei_mem_access_ctl_s cn52xx; ++ struct cvmx_npei_mem_access_ctl_s cn52xxp1; ++ struct cvmx_npei_mem_access_ctl_s cn56xx; ++ struct cvmx_npei_mem_access_ctl_s cn56xxp1; ++}; ++ ++union cvmx_npei_mem_access_subidx { ++ uint64_t u64; ++ struct cvmx_npei_mem_access_subidx_s { ++ uint64_t reserved_42_63:22; ++ uint64_t zero:1; ++ uint64_t port:2; ++ uint64_t nmerge:1; ++ uint64_t esr:2; ++ uint64_t esw:2; ++ uint64_t nsr:1; ++ uint64_t nsw:1; ++ uint64_t ror:1; ++ uint64_t row:1; ++ uint64_t ba:30; ++ } s; ++ struct cvmx_npei_mem_access_subidx_s cn52xx; ++ struct cvmx_npei_mem_access_subidx_s cn52xxp1; ++ struct cvmx_npei_mem_access_subidx_s cn56xx; ++ struct cvmx_npei_mem_access_subidx_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_enb0 { ++ uint64_t u64; ++ struct cvmx_npei_msi_enb0_s { ++ uint64_t enb:64; ++ } s; ++ struct cvmx_npei_msi_enb0_s cn52xx; ++ struct cvmx_npei_msi_enb0_s cn52xxp1; ++ struct cvmx_npei_msi_enb0_s cn56xx; ++ struct cvmx_npei_msi_enb0_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_enb1 { ++ uint64_t u64; ++ struct cvmx_npei_msi_enb1_s { ++ uint64_t enb:64; ++ } s; ++ struct cvmx_npei_msi_enb1_s cn52xx; ++ struct cvmx_npei_msi_enb1_s cn52xxp1; ++ struct cvmx_npei_msi_enb1_s cn56xx; ++ struct cvmx_npei_msi_enb1_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_enb2 { ++ uint64_t u64; ++ struct cvmx_npei_msi_enb2_s { ++ uint64_t enb:64; ++ } s; ++ struct cvmx_npei_msi_enb2_s cn52xx; ++ struct cvmx_npei_msi_enb2_s cn52xxp1; ++ struct cvmx_npei_msi_enb2_s cn56xx; ++ struct cvmx_npei_msi_enb2_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_enb3 { ++ uint64_t u64; ++ struct cvmx_npei_msi_enb3_s { ++ uint64_t enb:64; ++ } s; ++ struct cvmx_npei_msi_enb3_s cn52xx; ++ struct cvmx_npei_msi_enb3_s cn52xxp1; ++ struct cvmx_npei_msi_enb3_s cn56xx; ++ struct cvmx_npei_msi_enb3_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_rcv0 { ++ uint64_t u64; ++ struct cvmx_npei_msi_rcv0_s { ++ uint64_t intr:64; ++ } s; ++ struct cvmx_npei_msi_rcv0_s cn52xx; ++ struct cvmx_npei_msi_rcv0_s cn52xxp1; ++ struct cvmx_npei_msi_rcv0_s cn56xx; ++ struct cvmx_npei_msi_rcv0_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_rcv1 { ++ uint64_t u64; ++ struct cvmx_npei_msi_rcv1_s { ++ uint64_t intr:64; ++ } s; ++ struct cvmx_npei_msi_rcv1_s cn52xx; ++ struct cvmx_npei_msi_rcv1_s cn52xxp1; ++ struct cvmx_npei_msi_rcv1_s cn56xx; ++ struct cvmx_npei_msi_rcv1_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_rcv2 { ++ uint64_t u64; ++ struct cvmx_npei_msi_rcv2_s { ++ uint64_t intr:64; ++ } s; ++ struct cvmx_npei_msi_rcv2_s cn52xx; ++ struct cvmx_npei_msi_rcv2_s cn52xxp1; ++ struct cvmx_npei_msi_rcv2_s cn56xx; ++ struct cvmx_npei_msi_rcv2_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_rcv3 { ++ uint64_t u64; ++ struct cvmx_npei_msi_rcv3_s { ++ uint64_t intr:64; ++ } s; ++ struct cvmx_npei_msi_rcv3_s cn52xx; ++ struct cvmx_npei_msi_rcv3_s cn52xxp1; ++ struct cvmx_npei_msi_rcv3_s cn56xx; ++ struct cvmx_npei_msi_rcv3_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_rd_map { ++ uint64_t u64; ++ struct cvmx_npei_msi_rd_map_s { ++ uint64_t reserved_16_63:48; ++ uint64_t rd_int:8; ++ uint64_t msi_int:8; ++ } s; ++ struct cvmx_npei_msi_rd_map_s cn52xx; ++ struct cvmx_npei_msi_rd_map_s cn52xxp1; ++ struct cvmx_npei_msi_rd_map_s cn56xx; ++ struct cvmx_npei_msi_rd_map_s cn56xxp1; ++}; ++ ++union cvmx_npei_msi_w1c_enb0 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1c_enb0_s { ++ uint64_t clr:64; ++ } s; ++ struct cvmx_npei_msi_w1c_enb0_s cn52xx; ++ struct cvmx_npei_msi_w1c_enb0_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1c_enb1 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1c_enb1_s { ++ uint64_t clr:64; ++ } s; ++ struct cvmx_npei_msi_w1c_enb1_s cn52xx; ++ struct cvmx_npei_msi_w1c_enb1_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1c_enb2 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1c_enb2_s { ++ uint64_t clr:64; ++ } s; ++ struct cvmx_npei_msi_w1c_enb2_s cn52xx; ++ struct cvmx_npei_msi_w1c_enb2_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1c_enb3 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1c_enb3_s { ++ uint64_t clr:64; ++ } s; ++ struct cvmx_npei_msi_w1c_enb3_s cn52xx; ++ struct cvmx_npei_msi_w1c_enb3_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1s_enb0 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1s_enb0_s { ++ uint64_t set:64; ++ } s; ++ struct cvmx_npei_msi_w1s_enb0_s cn52xx; ++ struct cvmx_npei_msi_w1s_enb0_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1s_enb1 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1s_enb1_s { ++ uint64_t set:64; ++ } s; ++ struct cvmx_npei_msi_w1s_enb1_s cn52xx; ++ struct cvmx_npei_msi_w1s_enb1_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1s_enb2 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1s_enb2_s { ++ uint64_t set:64; ++ } s; ++ struct cvmx_npei_msi_w1s_enb2_s cn52xx; ++ struct cvmx_npei_msi_w1s_enb2_s cn56xx; ++}; ++ ++union cvmx_npei_msi_w1s_enb3 { ++ uint64_t u64; ++ struct cvmx_npei_msi_w1s_enb3_s { ++ uint64_t set:64; ++ } s; ++ struct cvmx_npei_msi_w1s_enb3_s cn52xx; ++ struct cvmx_npei_msi_w1s_enb3_s cn56xx; ++}; ++ ++union cvmx_npei_msi_wr_map { ++ uint64_t u64; ++ struct cvmx_npei_msi_wr_map_s { ++ uint64_t reserved_16_63:48; ++ uint64_t ciu_int:8; ++ uint64_t msi_int:8; ++ } s; ++ struct cvmx_npei_msi_wr_map_s cn52xx; ++ struct cvmx_npei_msi_wr_map_s cn52xxp1; ++ struct cvmx_npei_msi_wr_map_s cn56xx; ++ struct cvmx_npei_msi_wr_map_s cn56xxp1; ++}; ++ ++union cvmx_npei_pcie_credit_cnt { ++ uint64_t u64; ++ struct cvmx_npei_pcie_credit_cnt_s { ++ uint64_t reserved_48_63:16; ++ uint64_t p1_ccnt:8; ++ uint64_t p1_ncnt:8; ++ uint64_t p1_pcnt:8; ++ uint64_t p0_ccnt:8; ++ uint64_t p0_ncnt:8; ++ uint64_t p0_pcnt:8; ++ } s; ++ struct cvmx_npei_pcie_credit_cnt_s cn52xx; ++ struct cvmx_npei_pcie_credit_cnt_s cn56xx; ++}; ++ ++union cvmx_npei_pcie_msi_rcv { ++ uint64_t u64; ++ struct cvmx_npei_pcie_msi_rcv_s { ++ uint64_t reserved_8_63:56; ++ uint64_t intr:8; ++ } s; ++ struct cvmx_npei_pcie_msi_rcv_s cn52xx; ++ struct cvmx_npei_pcie_msi_rcv_s cn52xxp1; ++ struct cvmx_npei_pcie_msi_rcv_s cn56xx; ++ struct cvmx_npei_pcie_msi_rcv_s cn56xxp1; ++}; ++ ++union cvmx_npei_pcie_msi_rcv_b1 { ++ uint64_t u64; ++ struct cvmx_npei_pcie_msi_rcv_b1_s { ++ uint64_t reserved_16_63:48; ++ uint64_t intr:8; ++ uint64_t reserved_0_7:8; ++ } s; ++ struct cvmx_npei_pcie_msi_rcv_b1_s cn52xx; ++ struct cvmx_npei_pcie_msi_rcv_b1_s cn52xxp1; ++ struct cvmx_npei_pcie_msi_rcv_b1_s cn56xx; ++ struct cvmx_npei_pcie_msi_rcv_b1_s cn56xxp1; ++}; ++ ++union cvmx_npei_pcie_msi_rcv_b2 { ++ uint64_t u64; ++ struct cvmx_npei_pcie_msi_rcv_b2_s { ++ uint64_t reserved_24_63:40; ++ uint64_t intr:8; ++ uint64_t reserved_0_15:16; ++ } s; ++ struct cvmx_npei_pcie_msi_rcv_b2_s cn52xx; ++ struct cvmx_npei_pcie_msi_rcv_b2_s cn52xxp1; ++ struct cvmx_npei_pcie_msi_rcv_b2_s cn56xx; ++ struct cvmx_npei_pcie_msi_rcv_b2_s cn56xxp1; ++}; ++ ++union cvmx_npei_pcie_msi_rcv_b3 { ++ uint64_t u64; ++ struct cvmx_npei_pcie_msi_rcv_b3_s { ++ uint64_t reserved_32_63:32; ++ uint64_t intr:8; ++ uint64_t reserved_0_23:24; ++ } s; ++ struct cvmx_npei_pcie_msi_rcv_b3_s cn52xx; ++ struct cvmx_npei_pcie_msi_rcv_b3_s cn52xxp1; ++ struct cvmx_npei_pcie_msi_rcv_b3_s cn56xx; ++ struct cvmx_npei_pcie_msi_rcv_b3_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_cnts { ++ uint64_t u64; ++ struct cvmx_npei_pktx_cnts_s { ++ uint64_t reserved_54_63:10; ++ uint64_t timer:22; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_npei_pktx_cnts_s cn52xx; ++ struct cvmx_npei_pktx_cnts_s cn56xx; ++ struct cvmx_npei_pktx_cnts_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_in_bp { ++ uint64_t u64; ++ struct cvmx_npei_pktx_in_bp_s { ++ uint64_t wmark:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_npei_pktx_in_bp_s cn52xx; ++ struct cvmx_npei_pktx_in_bp_s cn56xx; ++ struct cvmx_npei_pktx_in_bp_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_instr_baddr { ++ uint64_t u64; ++ struct cvmx_npei_pktx_instr_baddr_s { ++ uint64_t addr:61; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_npei_pktx_instr_baddr_s cn52xx; ++ struct cvmx_npei_pktx_instr_baddr_s cn56xx; ++ struct cvmx_npei_pktx_instr_baddr_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_instr_baoff_dbell { ++ uint64_t u64; ++ struct cvmx_npei_pktx_instr_baoff_dbell_s { ++ uint64_t aoff:32; ++ uint64_t dbell:32; ++ } s; ++ struct cvmx_npei_pktx_instr_baoff_dbell_s cn52xx; ++ struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xx; ++ struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_instr_fifo_rsize { ++ uint64_t u64; ++ struct cvmx_npei_pktx_instr_fifo_rsize_s { ++ uint64_t max:9; ++ uint64_t rrp:9; ++ uint64_t wrp:9; ++ uint64_t fcnt:5; ++ uint64_t rsize:32; ++ } s; ++ struct cvmx_npei_pktx_instr_fifo_rsize_s cn52xx; ++ struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xx; ++ struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_instr_header { ++ uint64_t u64; ++ struct cvmx_npei_pktx_instr_header_s { ++ uint64_t reserved_44_63:20; ++ uint64_t pbp:1; ++ uint64_t rsv_f:5; ++ uint64_t rparmode:2; ++ uint64_t rsv_e:1; ++ uint64_t rskp_len:7; ++ uint64_t rsv_d:6; ++ uint64_t use_ihdr:1; ++ uint64_t rsv_c:5; ++ uint64_t par_mode:2; ++ uint64_t rsv_b:1; ++ uint64_t skp_len:7; ++ uint64_t rsv_a:6; ++ } s; ++ struct cvmx_npei_pktx_instr_header_s cn52xx; ++ struct cvmx_npei_pktx_instr_header_s cn56xx; ++ struct cvmx_npei_pktx_instr_header_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_slist_baddr { ++ uint64_t u64; ++ struct cvmx_npei_pktx_slist_baddr_s { ++ uint64_t addr:60; ++ uint64_t reserved_0_3:4; ++ } s; ++ struct cvmx_npei_pktx_slist_baddr_s cn52xx; ++ struct cvmx_npei_pktx_slist_baddr_s cn56xx; ++ struct cvmx_npei_pktx_slist_baddr_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_slist_baoff_dbell { ++ uint64_t u64; ++ struct cvmx_npei_pktx_slist_baoff_dbell_s { ++ uint64_t aoff:32; ++ uint64_t dbell:32; ++ } s; ++ struct cvmx_npei_pktx_slist_baoff_dbell_s cn52xx; ++ struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xx; ++ struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xxp1; ++}; ++ ++union cvmx_npei_pktx_slist_fifo_rsize { ++ uint64_t u64; ++ struct cvmx_npei_pktx_slist_fifo_rsize_s { ++ uint64_t reserved_32_63:32; ++ uint64_t rsize:32; ++ } s; ++ struct cvmx_npei_pktx_slist_fifo_rsize_s cn52xx; ++ struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xx; ++ struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_cnt_int { ++ uint64_t u64; ++ struct cvmx_npei_pkt_cnt_int_s { ++ uint64_t reserved_32_63:32; ++ uint64_t port:32; ++ } s; ++ struct cvmx_npei_pkt_cnt_int_s cn52xx; ++ struct cvmx_npei_pkt_cnt_int_s cn56xx; ++ struct cvmx_npei_pkt_cnt_int_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_cnt_int_enb { ++ uint64_t u64; ++ struct cvmx_npei_pkt_cnt_int_enb_s { ++ uint64_t reserved_32_63:32; ++ uint64_t port:32; ++ } s; ++ struct cvmx_npei_pkt_cnt_int_enb_s cn52xx; ++ struct cvmx_npei_pkt_cnt_int_enb_s cn56xx; ++ struct cvmx_npei_pkt_cnt_int_enb_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_data_out_es { ++ uint64_t u64; ++ struct cvmx_npei_pkt_data_out_es_s { ++ uint64_t es:64; ++ } s; ++ struct cvmx_npei_pkt_data_out_es_s cn52xx; ++ struct cvmx_npei_pkt_data_out_es_s cn56xx; ++ struct cvmx_npei_pkt_data_out_es_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_data_out_ns { ++ uint64_t u64; ++ struct cvmx_npei_pkt_data_out_ns_s { ++ uint64_t reserved_32_63:32; ++ uint64_t nsr:32; ++ } s; ++ struct cvmx_npei_pkt_data_out_ns_s cn52xx; ++ struct cvmx_npei_pkt_data_out_ns_s cn56xx; ++ struct cvmx_npei_pkt_data_out_ns_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_data_out_ror { ++ uint64_t u64; ++ struct cvmx_npei_pkt_data_out_ror_s { ++ uint64_t reserved_32_63:32; ++ uint64_t ror:32; ++ } s; ++ struct cvmx_npei_pkt_data_out_ror_s cn52xx; ++ struct cvmx_npei_pkt_data_out_ror_s cn56xx; ++ struct cvmx_npei_pkt_data_out_ror_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_dpaddr { ++ uint64_t u64; ++ struct cvmx_npei_pkt_dpaddr_s { ++ uint64_t reserved_32_63:32; ++ uint64_t dptr:32; ++ } s; ++ struct cvmx_npei_pkt_dpaddr_s cn52xx; ++ struct cvmx_npei_pkt_dpaddr_s cn56xx; ++ struct cvmx_npei_pkt_dpaddr_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_in_bp { ++ uint64_t u64; ++ struct cvmx_npei_pkt_in_bp_s { ++ uint64_t reserved_32_63:32; ++ uint64_t bp:32; ++ } s; ++ struct cvmx_npei_pkt_in_bp_s cn56xx; ++}; ++ ++union cvmx_npei_pkt_in_donex_cnts { ++ uint64_t u64; ++ struct cvmx_npei_pkt_in_donex_cnts_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_npei_pkt_in_donex_cnts_s cn52xx; ++ struct cvmx_npei_pkt_in_donex_cnts_s cn56xx; ++ struct cvmx_npei_pkt_in_donex_cnts_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_in_instr_counts { ++ uint64_t u64; ++ struct cvmx_npei_pkt_in_instr_counts_s { ++ uint64_t wr_cnt:32; ++ uint64_t rd_cnt:32; ++ } s; ++ struct cvmx_npei_pkt_in_instr_counts_s cn52xx; ++ struct cvmx_npei_pkt_in_instr_counts_s cn56xx; ++}; ++ ++union cvmx_npei_pkt_in_pcie_port { ++ uint64_t u64; ++ struct cvmx_npei_pkt_in_pcie_port_s { ++ uint64_t pp:64; ++ } s; ++ struct cvmx_npei_pkt_in_pcie_port_s cn52xx; ++ struct cvmx_npei_pkt_in_pcie_port_s cn56xx; ++}; ++ ++union cvmx_npei_pkt_input_control { ++ uint64_t u64; ++ struct cvmx_npei_pkt_input_control_s { ++ uint64_t reserved_23_63:41; ++ uint64_t pkt_rr:1; ++ uint64_t pbp_dhi:13; ++ uint64_t d_nsr:1; ++ uint64_t d_esr:2; ++ uint64_t d_ror:1; ++ uint64_t use_csr:1; ++ uint64_t nsr:1; ++ uint64_t esr:2; ++ uint64_t ror:1; ++ } s; ++ struct cvmx_npei_pkt_input_control_s cn52xx; ++ struct cvmx_npei_pkt_input_control_s cn56xx; ++ struct cvmx_npei_pkt_input_control_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_instr_enb { ++ uint64_t u64; ++ struct cvmx_npei_pkt_instr_enb_s { ++ uint64_t reserved_32_63:32; ++ uint64_t enb:32; ++ } s; ++ struct cvmx_npei_pkt_instr_enb_s cn52xx; ++ struct cvmx_npei_pkt_instr_enb_s cn56xx; ++ struct cvmx_npei_pkt_instr_enb_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_instr_rd_size { ++ uint64_t u64; ++ struct cvmx_npei_pkt_instr_rd_size_s { ++ uint64_t rdsize:64; ++ } s; ++ struct cvmx_npei_pkt_instr_rd_size_s cn52xx; ++ struct cvmx_npei_pkt_instr_rd_size_s cn56xx; ++}; ++ ++union cvmx_npei_pkt_instr_size { ++ uint64_t u64; ++ struct cvmx_npei_pkt_instr_size_s { ++ uint64_t reserved_32_63:32; ++ uint64_t is_64b:32; ++ } s; ++ struct cvmx_npei_pkt_instr_size_s cn52xx; ++ struct cvmx_npei_pkt_instr_size_s cn56xx; ++ struct cvmx_npei_pkt_instr_size_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_int_levels { ++ uint64_t u64; ++ struct cvmx_npei_pkt_int_levels_s { ++ uint64_t reserved_54_63:10; ++ uint64_t time:22; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_npei_pkt_int_levels_s cn52xx; ++ struct cvmx_npei_pkt_int_levels_s cn56xx; ++ struct cvmx_npei_pkt_int_levels_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_iptr { ++ uint64_t u64; ++ struct cvmx_npei_pkt_iptr_s { ++ uint64_t reserved_32_63:32; ++ uint64_t iptr:32; ++ } s; ++ struct cvmx_npei_pkt_iptr_s cn52xx; ++ struct cvmx_npei_pkt_iptr_s cn56xx; ++ struct cvmx_npei_pkt_iptr_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_out_bmode { ++ uint64_t u64; ++ struct cvmx_npei_pkt_out_bmode_s { ++ uint64_t reserved_32_63:32; ++ uint64_t bmode:32; ++ } s; ++ struct cvmx_npei_pkt_out_bmode_s cn52xx; ++ struct cvmx_npei_pkt_out_bmode_s cn56xx; ++ struct cvmx_npei_pkt_out_bmode_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_out_enb { ++ uint64_t u64; ++ struct cvmx_npei_pkt_out_enb_s { ++ uint64_t reserved_32_63:32; ++ uint64_t enb:32; ++ } s; ++ struct cvmx_npei_pkt_out_enb_s cn52xx; ++ struct cvmx_npei_pkt_out_enb_s cn56xx; ++ struct cvmx_npei_pkt_out_enb_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_output_wmark { ++ uint64_t u64; ++ struct cvmx_npei_pkt_output_wmark_s { ++ uint64_t reserved_32_63:32; ++ uint64_t wmark:32; ++ } s; ++ struct cvmx_npei_pkt_output_wmark_s cn52xx; ++ struct cvmx_npei_pkt_output_wmark_s cn56xx; ++}; ++ ++union cvmx_npei_pkt_pcie_port { ++ uint64_t u64; ++ struct cvmx_npei_pkt_pcie_port_s { ++ uint64_t pp:64; ++ } s; ++ struct cvmx_npei_pkt_pcie_port_s cn52xx; ++ struct cvmx_npei_pkt_pcie_port_s cn56xx; ++ struct cvmx_npei_pkt_pcie_port_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_port_in_rst { ++ uint64_t u64; ++ struct cvmx_npei_pkt_port_in_rst_s { ++ uint64_t in_rst:32; ++ uint64_t out_rst:32; ++ } s; ++ struct cvmx_npei_pkt_port_in_rst_s cn52xx; ++ struct cvmx_npei_pkt_port_in_rst_s cn56xx; ++}; ++ ++union cvmx_npei_pkt_slist_es { ++ uint64_t u64; ++ struct cvmx_npei_pkt_slist_es_s { ++ uint64_t es:64; ++ } s; ++ struct cvmx_npei_pkt_slist_es_s cn52xx; ++ struct cvmx_npei_pkt_slist_es_s cn56xx; ++ struct cvmx_npei_pkt_slist_es_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_slist_id_size { ++ uint64_t u64; ++ struct cvmx_npei_pkt_slist_id_size_s { ++ uint64_t reserved_23_63:41; ++ uint64_t isize:7; ++ uint64_t bsize:16; ++ } s; ++ struct cvmx_npei_pkt_slist_id_size_s cn52xx; ++ struct cvmx_npei_pkt_slist_id_size_s cn56xx; ++ struct cvmx_npei_pkt_slist_id_size_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_slist_ns { ++ uint64_t u64; ++ struct cvmx_npei_pkt_slist_ns_s { ++ uint64_t reserved_32_63:32; ++ uint64_t nsr:32; ++ } s; ++ struct cvmx_npei_pkt_slist_ns_s cn52xx; ++ struct cvmx_npei_pkt_slist_ns_s cn56xx; ++ struct cvmx_npei_pkt_slist_ns_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_slist_ror { ++ uint64_t u64; ++ struct cvmx_npei_pkt_slist_ror_s { ++ uint64_t reserved_32_63:32; ++ uint64_t ror:32; ++ } s; ++ struct cvmx_npei_pkt_slist_ror_s cn52xx; ++ struct cvmx_npei_pkt_slist_ror_s cn56xx; ++ struct cvmx_npei_pkt_slist_ror_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_time_int { ++ uint64_t u64; ++ struct cvmx_npei_pkt_time_int_s { ++ uint64_t reserved_32_63:32; ++ uint64_t port:32; ++ } s; ++ struct cvmx_npei_pkt_time_int_s cn52xx; ++ struct cvmx_npei_pkt_time_int_s cn56xx; ++ struct cvmx_npei_pkt_time_int_s cn56xxp1; ++}; ++ ++union cvmx_npei_pkt_time_int_enb { ++ uint64_t u64; ++ struct cvmx_npei_pkt_time_int_enb_s { ++ uint64_t reserved_32_63:32; ++ uint64_t port:32; ++ } s; ++ struct cvmx_npei_pkt_time_int_enb_s cn52xx; ++ struct cvmx_npei_pkt_time_int_enb_s cn56xx; ++ struct cvmx_npei_pkt_time_int_enb_s cn56xxp1; ++}; ++ ++union cvmx_npei_rsl_int_blocks { ++ uint64_t u64; ++ struct cvmx_npei_rsl_int_blocks_s { ++ uint64_t reserved_31_63:33; ++ uint64_t iob:1; ++ uint64_t lmc1:1; ++ uint64_t agl:1; ++ uint64_t reserved_24_27:4; ++ uint64_t asxpcs1:1; ++ uint64_t asxpcs0:1; ++ uint64_t reserved_21_21:1; ++ uint64_t pip:1; ++ uint64_t reserved_18_19:2; ++ uint64_t lmc0:1; ++ uint64_t l2c:1; ++ uint64_t usb1:1; ++ uint64_t rad:1; ++ uint64_t usb:1; ++ uint64_t pow:1; ++ uint64_t tim:1; ++ uint64_t pko:1; ++ uint64_t ipd:1; ++ uint64_t reserved_8_8:1; ++ uint64_t zip:1; ++ uint64_t reserved_6_6:1; ++ uint64_t fpa:1; ++ uint64_t key:1; ++ uint64_t npei:1; ++ uint64_t gmx1:1; ++ uint64_t gmx0:1; ++ uint64_t mio:1; ++ } s; ++ struct cvmx_npei_rsl_int_blocks_s cn52xx; ++ struct cvmx_npei_rsl_int_blocks_s cn52xxp1; ++ struct cvmx_npei_rsl_int_blocks_cn56xx { ++ uint64_t reserved_31_63:33; ++ uint64_t iob:1; ++ uint64_t lmc1:1; ++ uint64_t agl:1; ++ uint64_t reserved_24_27:4; ++ uint64_t asxpcs1:1; ++ uint64_t asxpcs0:1; ++ uint64_t reserved_21_21:1; ++ uint64_t pip:1; ++ uint64_t reserved_18_19:2; ++ uint64_t lmc0:1; ++ uint64_t l2c:1; ++ uint64_t reserved_15_15:1; ++ uint64_t rad:1; ++ uint64_t usb:1; ++ uint64_t pow:1; ++ uint64_t tim:1; ++ uint64_t pko:1; ++ uint64_t ipd:1; ++ uint64_t reserved_8_8:1; ++ uint64_t zip:1; ++ uint64_t reserved_6_6:1; ++ uint64_t fpa:1; ++ uint64_t key:1; ++ uint64_t npei:1; ++ uint64_t gmx1:1; ++ uint64_t gmx0:1; ++ uint64_t mio:1; ++ } cn56xx; ++ struct cvmx_npei_rsl_int_blocks_cn56xx cn56xxp1; ++}; ++ ++union cvmx_npei_scratch_1 { ++ uint64_t u64; ++ struct cvmx_npei_scratch_1_s { ++ uint64_t data:64; ++ } s; ++ struct cvmx_npei_scratch_1_s cn52xx; ++ struct cvmx_npei_scratch_1_s cn52xxp1; ++ struct cvmx_npei_scratch_1_s cn56xx; ++ struct cvmx_npei_scratch_1_s cn56xxp1; ++}; ++ ++union cvmx_npei_state1 { ++ uint64_t u64; ++ struct cvmx_npei_state1_s { ++ uint64_t cpl1:12; ++ uint64_t cpl0:12; ++ uint64_t arb:1; ++ uint64_t csr:39; ++ } s; ++ struct cvmx_npei_state1_s cn52xx; ++ struct cvmx_npei_state1_s cn52xxp1; ++ struct cvmx_npei_state1_s cn56xx; ++ struct cvmx_npei_state1_s cn56xxp1; ++}; ++ ++union cvmx_npei_state2 { ++ uint64_t u64; ++ struct cvmx_npei_state2_s { ++ uint64_t reserved_48_63:16; ++ uint64_t npei:1; ++ uint64_t rac:1; ++ uint64_t csm1:15; ++ uint64_t csm0:15; ++ uint64_t nnp0:8; ++ uint64_t nnd:8; ++ } s; ++ struct cvmx_npei_state2_s cn52xx; ++ struct cvmx_npei_state2_s cn52xxp1; ++ struct cvmx_npei_state2_s cn56xx; ++ struct cvmx_npei_state2_s cn56xxp1; ++}; ++ ++union cvmx_npei_state3 { ++ uint64_t u64; ++ struct cvmx_npei_state3_s { ++ uint64_t reserved_56_63:8; ++ uint64_t psm1:15; ++ uint64_t psm0:15; ++ uint64_t nsm1:13; ++ uint64_t nsm0:13; ++ } s; ++ struct cvmx_npei_state3_s cn52xx; ++ struct cvmx_npei_state3_s cn52xxp1; ++ struct cvmx_npei_state3_s cn56xx; ++ struct cvmx_npei_state3_s cn56xxp1; ++}; ++ ++union cvmx_npei_win_rd_addr { ++ uint64_t u64; ++ struct cvmx_npei_win_rd_addr_s { ++ uint64_t reserved_51_63:13; ++ uint64_t ld_cmd:2; ++ uint64_t iobit:1; ++ uint64_t rd_addr:48; ++ } s; ++ struct cvmx_npei_win_rd_addr_s cn52xx; ++ struct cvmx_npei_win_rd_addr_s cn52xxp1; ++ struct cvmx_npei_win_rd_addr_s cn56xx; ++ struct cvmx_npei_win_rd_addr_s cn56xxp1; ++}; ++ ++union cvmx_npei_win_rd_data { ++ uint64_t u64; ++ struct cvmx_npei_win_rd_data_s { ++ uint64_t rd_data:64; ++ } s; ++ struct cvmx_npei_win_rd_data_s cn52xx; ++ struct cvmx_npei_win_rd_data_s cn52xxp1; ++ struct cvmx_npei_win_rd_data_s cn56xx; ++ struct cvmx_npei_win_rd_data_s cn56xxp1; ++}; ++ ++union cvmx_npei_win_wr_addr { ++ uint64_t u64; ++ struct cvmx_npei_win_wr_addr_s { ++ uint64_t reserved_49_63:15; ++ uint64_t iobit:1; ++ uint64_t wr_addr:46; ++ uint64_t reserved_0_1:2; ++ } s; ++ struct cvmx_npei_win_wr_addr_s cn52xx; ++ struct cvmx_npei_win_wr_addr_s cn52xxp1; ++ struct cvmx_npei_win_wr_addr_s cn56xx; ++ struct cvmx_npei_win_wr_addr_s cn56xxp1; ++}; ++ ++union cvmx_npei_win_wr_data { ++ uint64_t u64; ++ struct cvmx_npei_win_wr_data_s { ++ uint64_t wr_data:64; ++ } s; ++ struct cvmx_npei_win_wr_data_s cn52xx; ++ struct cvmx_npei_win_wr_data_s cn52xxp1; ++ struct cvmx_npei_win_wr_data_s cn56xx; ++ struct cvmx_npei_win_wr_data_s cn56xxp1; ++}; ++ ++union cvmx_npei_win_wr_mask { ++ uint64_t u64; ++ struct cvmx_npei_win_wr_mask_s { ++ uint64_t reserved_8_63:56; ++ uint64_t wr_mask:8; ++ } s; ++ struct cvmx_npei_win_wr_mask_s cn52xx; ++ struct cvmx_npei_win_wr_mask_s cn52xxp1; ++ struct cvmx_npei_win_wr_mask_s cn56xx; ++ struct cvmx_npei_win_wr_mask_s cn56xxp1; ++}; ++ ++union cvmx_npei_window_ctl { ++ uint64_t u64; ++ struct cvmx_npei_window_ctl_s { ++ uint64_t reserved_32_63:32; ++ uint64_t time:32; ++ } s; ++ struct cvmx_npei_window_ctl_s cn52xx; ++ struct cvmx_npei_window_ctl_s cn52xxp1; ++ struct cvmx_npei_window_ctl_s cn56xx; ++ struct cvmx_npei_window_ctl_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-npi-defs.h +@@ -0,0 +1,1735 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_NPI_DEFS_H__ ++#define __CVMX_NPI_DEFS_H__ ++ ++#define CVMX_NPI_BASE_ADDR_INPUT0 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000070ull) ++#define CVMX_NPI_BASE_ADDR_INPUT1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000080ull) ++#define CVMX_NPI_BASE_ADDR_INPUT2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000090ull) ++#define CVMX_NPI_BASE_ADDR_INPUT3 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000A0ull) ++#define CVMX_NPI_BASE_ADDR_INPUTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000000070ull + (((offset) & 3) * 16)) ++#define CVMX_NPI_BASE_ADDR_OUTPUT0 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000B8ull) ++#define CVMX_NPI_BASE_ADDR_OUTPUT1 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000C0ull) ++#define CVMX_NPI_BASE_ADDR_OUTPUT2 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000C8ull) ++#define CVMX_NPI_BASE_ADDR_OUTPUT3 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000D0ull) ++#define CVMX_NPI_BASE_ADDR_OUTPUTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F00000000B8ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_BIST_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011F00000003F8ull) ++#define CVMX_NPI_BUFF_SIZE_OUTPUT0 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000E0ull) ++#define CVMX_NPI_BUFF_SIZE_OUTPUT1 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000E8ull) ++#define CVMX_NPI_BUFF_SIZE_OUTPUT2 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000F0ull) ++#define CVMX_NPI_BUFF_SIZE_OUTPUT3 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000F8ull) ++#define CVMX_NPI_BUFF_SIZE_OUTPUTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F00000000E0ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_COMP_CTL \ ++ CVMX_ADD_IO_SEG(0x00011F0000000218ull) ++#define CVMX_NPI_CTL_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000010ull) ++#define CVMX_NPI_DBG_SELECT \ ++ CVMX_ADD_IO_SEG(0x00011F0000000008ull) ++#define CVMX_NPI_DMA_CONTROL \ ++ CVMX_ADD_IO_SEG(0x00011F0000000128ull) ++#define CVMX_NPI_DMA_HIGHP_COUNTS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000148ull) ++#define CVMX_NPI_DMA_HIGHP_NADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000158ull) ++#define CVMX_NPI_DMA_LOWP_COUNTS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000140ull) ++#define CVMX_NPI_DMA_LOWP_NADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000150ull) ++#define CVMX_NPI_HIGHP_DBELL \ ++ CVMX_ADD_IO_SEG(0x00011F0000000120ull) ++#define CVMX_NPI_HIGHP_IBUFF_SADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000110ull) ++#define CVMX_NPI_INPUT_CONTROL \ ++ CVMX_ADD_IO_SEG(0x00011F0000000138ull) ++#define CVMX_NPI_INT_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000000020ull) ++#define CVMX_NPI_INT_SUM \ ++ CVMX_ADD_IO_SEG(0x00011F0000000018ull) ++#define CVMX_NPI_LOWP_DBELL \ ++ CVMX_ADD_IO_SEG(0x00011F0000000118ull) ++#define CVMX_NPI_LOWP_IBUFF_SADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000108ull) ++#define CVMX_NPI_MEM_ACCESS_SUBID3 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000028ull) ++#define CVMX_NPI_MEM_ACCESS_SUBID4 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000030ull) ++#define CVMX_NPI_MEM_ACCESS_SUBID5 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000038ull) ++#define CVMX_NPI_MEM_ACCESS_SUBID6 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000040ull) ++#define CVMX_NPI_MEM_ACCESS_SUBIDX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000000028ull + (((offset) & 7) * 8) - 8 * 3) ++#define CVMX_NPI_MSI_RCV \ ++ (0x0000000000000190ull) ++#define CVMX_NPI_NPI_MSI_RCV \ ++ CVMX_ADD_IO_SEG(0x00011F0000001190ull) ++#define CVMX_NPI_NUM_DESC_OUTPUT0 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000050ull) ++#define CVMX_NPI_NUM_DESC_OUTPUT1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000058ull) ++#define CVMX_NPI_NUM_DESC_OUTPUT2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000060ull) ++#define CVMX_NPI_NUM_DESC_OUTPUT3 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000068ull) ++#define CVMX_NPI_NUM_DESC_OUTPUTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000000050ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_OUTPUT_CONTROL \ ++ CVMX_ADD_IO_SEG(0x00011F0000000100ull) ++#define CVMX_NPI_P0_DBPAIR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000180ull) ++#define CVMX_NPI_P0_INSTR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F00000001C0ull) ++#define CVMX_NPI_P0_INSTR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F00000001A0ull) ++#define CVMX_NPI_P0_PAIR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000160ull) ++#define CVMX_NPI_P1_DBPAIR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000188ull) ++#define CVMX_NPI_P1_INSTR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F00000001C8ull) ++#define CVMX_NPI_P1_INSTR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F00000001A8ull) ++#define CVMX_NPI_P1_PAIR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000168ull) ++#define CVMX_NPI_P2_DBPAIR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000190ull) ++#define CVMX_NPI_P2_INSTR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F00000001D0ull) ++#define CVMX_NPI_P2_INSTR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F00000001B0ull) ++#define CVMX_NPI_P2_PAIR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000170ull) ++#define CVMX_NPI_P3_DBPAIR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000198ull) ++#define CVMX_NPI_P3_INSTR_ADDR \ ++ CVMX_ADD_IO_SEG(0x00011F00000001D8ull) ++#define CVMX_NPI_P3_INSTR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F00000001B8ull) ++#define CVMX_NPI_P3_PAIR_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000178ull) ++#define CVMX_NPI_PCI_BAR1_INDEXX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000001100ull + (((offset) & 31) * 4)) ++#define CVMX_NPI_PCI_BIST_REG \ ++ CVMX_ADD_IO_SEG(0x00011F00000011C0ull) ++#define CVMX_NPI_PCI_BURST_SIZE \ ++ CVMX_ADD_IO_SEG(0x00011F00000000D8ull) ++#define CVMX_NPI_PCI_CFG00 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001800ull) ++#define CVMX_NPI_PCI_CFG01 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001804ull) ++#define CVMX_NPI_PCI_CFG02 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001808ull) ++#define CVMX_NPI_PCI_CFG03 \ ++ CVMX_ADD_IO_SEG(0x00011F000000180Cull) ++#define CVMX_NPI_PCI_CFG04 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001810ull) ++#define CVMX_NPI_PCI_CFG05 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001814ull) ++#define CVMX_NPI_PCI_CFG06 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001818ull) ++#define CVMX_NPI_PCI_CFG07 \ ++ CVMX_ADD_IO_SEG(0x00011F000000181Cull) ++#define CVMX_NPI_PCI_CFG08 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001820ull) ++#define CVMX_NPI_PCI_CFG09 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001824ull) ++#define CVMX_NPI_PCI_CFG10 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001828ull) ++#define CVMX_NPI_PCI_CFG11 \ ++ CVMX_ADD_IO_SEG(0x00011F000000182Cull) ++#define CVMX_NPI_PCI_CFG12 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001830ull) ++#define CVMX_NPI_PCI_CFG13 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001834ull) ++#define CVMX_NPI_PCI_CFG15 \ ++ CVMX_ADD_IO_SEG(0x00011F000000183Cull) ++#define CVMX_NPI_PCI_CFG16 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001840ull) ++#define CVMX_NPI_PCI_CFG17 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001844ull) ++#define CVMX_NPI_PCI_CFG18 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001848ull) ++#define CVMX_NPI_PCI_CFG19 \ ++ CVMX_ADD_IO_SEG(0x00011F000000184Cull) ++#define CVMX_NPI_PCI_CFG20 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001850ull) ++#define CVMX_NPI_PCI_CFG21 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001854ull) ++#define CVMX_NPI_PCI_CFG22 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001858ull) ++#define CVMX_NPI_PCI_CFG56 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018E0ull) ++#define CVMX_NPI_PCI_CFG57 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018E4ull) ++#define CVMX_NPI_PCI_CFG58 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018E8ull) ++#define CVMX_NPI_PCI_CFG59 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018ECull) ++#define CVMX_NPI_PCI_CFG60 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018F0ull) ++#define CVMX_NPI_PCI_CFG61 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018F4ull) ++#define CVMX_NPI_PCI_CFG62 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018F8ull) ++#define CVMX_NPI_PCI_CFG63 \ ++ CVMX_ADD_IO_SEG(0x00011F00000018FCull) ++#define CVMX_NPI_PCI_CNT_REG \ ++ CVMX_ADD_IO_SEG(0x00011F00000011B8ull) ++#define CVMX_NPI_PCI_CTL_STATUS_2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000118Cull) ++#define CVMX_NPI_PCI_INT_ARB_CFG \ ++ CVMX_ADD_IO_SEG(0x00011F0000000130ull) ++#define CVMX_NPI_PCI_INT_ENB2 \ ++ CVMX_ADD_IO_SEG(0x00011F00000011A0ull) ++#define CVMX_NPI_PCI_INT_SUM2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001198ull) ++#define CVMX_NPI_PCI_READ_CMD \ ++ CVMX_ADD_IO_SEG(0x00011F0000000048ull) ++#define CVMX_NPI_PCI_READ_CMD_6 \ ++ CVMX_ADD_IO_SEG(0x00011F0000001180ull) ++#define CVMX_NPI_PCI_READ_CMD_C \ ++ CVMX_ADD_IO_SEG(0x00011F0000001184ull) ++#define CVMX_NPI_PCI_READ_CMD_E \ ++ CVMX_ADD_IO_SEG(0x00011F0000001188ull) ++#define CVMX_NPI_PCI_SCM_REG \ ++ CVMX_ADD_IO_SEG(0x00011F00000011A8ull) ++#define CVMX_NPI_PCI_TSR_REG \ ++ CVMX_ADD_IO_SEG(0x00011F00000011B0ull) ++#define CVMX_NPI_PORT32_INSTR_HDR \ ++ CVMX_ADD_IO_SEG(0x00011F00000001F8ull) ++#define CVMX_NPI_PORT33_INSTR_HDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000200ull) ++#define CVMX_NPI_PORT34_INSTR_HDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000208ull) ++#define CVMX_NPI_PORT35_INSTR_HDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000000210ull) ++#define CVMX_NPI_PORT_BP_CONTROL \ ++ CVMX_ADD_IO_SEG(0x00011F00000001F0ull) ++#define CVMX_NPI_PX_DBPAIR_ADDR(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000000180ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_PX_INSTR_ADDR(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F00000001C0ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_PX_INSTR_CNTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F00000001A0ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_PX_PAIR_CNTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000000160ull + (((offset) & 3) * 8)) ++#define CVMX_NPI_RSL_INT_BLOCKS \ ++ CVMX_ADD_IO_SEG(0x00011F0000000000ull) ++#define CVMX_NPI_SIZE_INPUT0 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000078ull) ++#define CVMX_NPI_SIZE_INPUT1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000088ull) ++#define CVMX_NPI_SIZE_INPUT2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000000098ull) ++#define CVMX_NPI_SIZE_INPUT3 \ ++ CVMX_ADD_IO_SEG(0x00011F00000000A8ull) ++#define CVMX_NPI_SIZE_INPUTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000000078ull + (((offset) & 3) * 16)) ++#define CVMX_NPI_WIN_READ_TO \ ++ CVMX_ADD_IO_SEG(0x00011F00000001E0ull) ++ ++union cvmx_npi_base_addr_inputx { ++ uint64_t u64; ++ struct cvmx_npi_base_addr_inputx_s { ++ uint64_t baddr:61; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_npi_base_addr_inputx_s cn30xx; ++ struct cvmx_npi_base_addr_inputx_s cn31xx; ++ struct cvmx_npi_base_addr_inputx_s cn38xx; ++ struct cvmx_npi_base_addr_inputx_s cn38xxp2; ++ struct cvmx_npi_base_addr_inputx_s cn50xx; ++ struct cvmx_npi_base_addr_inputx_s cn58xx; ++ struct cvmx_npi_base_addr_inputx_s cn58xxp1; ++}; ++ ++union cvmx_npi_base_addr_outputx { ++ uint64_t u64; ++ struct cvmx_npi_base_addr_outputx_s { ++ uint64_t baddr:61; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_npi_base_addr_outputx_s cn30xx; ++ struct cvmx_npi_base_addr_outputx_s cn31xx; ++ struct cvmx_npi_base_addr_outputx_s cn38xx; ++ struct cvmx_npi_base_addr_outputx_s cn38xxp2; ++ struct cvmx_npi_base_addr_outputx_s cn50xx; ++ struct cvmx_npi_base_addr_outputx_s cn58xx; ++ struct cvmx_npi_base_addr_outputx_s cn58xxp1; ++}; ++ ++union cvmx_npi_bist_status { ++ uint64_t u64; ++ struct cvmx_npi_bist_status_s { ++ uint64_t reserved_20_63:44; ++ uint64_t csr_bs:1; ++ uint64_t dif_bs:1; ++ uint64_t rdp_bs:1; ++ uint64_t pcnc_bs:1; ++ uint64_t pcn_bs:1; ++ uint64_t rdn_bs:1; ++ uint64_t pcac_bs:1; ++ uint64_t pcad_bs:1; ++ uint64_t rdnl_bs:1; ++ uint64_t pgf_bs:1; ++ uint64_t pig_bs:1; ++ uint64_t pof0_bs:1; ++ uint64_t pof1_bs:1; ++ uint64_t pof2_bs:1; ++ uint64_t pof3_bs:1; ++ uint64_t pos_bs:1; ++ uint64_t nus_bs:1; ++ uint64_t dob_bs:1; ++ uint64_t pdf_bs:1; ++ uint64_t dpi_bs:1; ++ } s; ++ struct cvmx_npi_bist_status_cn30xx { ++ uint64_t reserved_20_63:44; ++ uint64_t csr_bs:1; ++ uint64_t dif_bs:1; ++ uint64_t rdp_bs:1; ++ uint64_t pcnc_bs:1; ++ uint64_t pcn_bs:1; ++ uint64_t rdn_bs:1; ++ uint64_t pcac_bs:1; ++ uint64_t pcad_bs:1; ++ uint64_t rdnl_bs:1; ++ uint64_t pgf_bs:1; ++ uint64_t pig_bs:1; ++ uint64_t pof0_bs:1; ++ uint64_t reserved_5_7:3; ++ uint64_t pos_bs:1; ++ uint64_t nus_bs:1; ++ uint64_t dob_bs:1; ++ uint64_t pdf_bs:1; ++ uint64_t dpi_bs:1; ++ } cn30xx; ++ struct cvmx_npi_bist_status_s cn31xx; ++ struct cvmx_npi_bist_status_s cn38xx; ++ struct cvmx_npi_bist_status_s cn38xxp2; ++ struct cvmx_npi_bist_status_cn50xx { ++ uint64_t reserved_20_63:44; ++ uint64_t csr_bs:1; ++ uint64_t dif_bs:1; ++ uint64_t rdp_bs:1; ++ uint64_t pcnc_bs:1; ++ uint64_t pcn_bs:1; ++ uint64_t rdn_bs:1; ++ uint64_t pcac_bs:1; ++ uint64_t pcad_bs:1; ++ uint64_t rdnl_bs:1; ++ uint64_t pgf_bs:1; ++ uint64_t pig_bs:1; ++ uint64_t pof0_bs:1; ++ uint64_t pof1_bs:1; ++ uint64_t reserved_5_6:2; ++ uint64_t pos_bs:1; ++ uint64_t nus_bs:1; ++ uint64_t dob_bs:1; ++ uint64_t pdf_bs:1; ++ uint64_t dpi_bs:1; ++ } cn50xx; ++ struct cvmx_npi_bist_status_s cn58xx; ++ struct cvmx_npi_bist_status_s cn58xxp1; ++}; ++ ++union cvmx_npi_buff_size_outputx { ++ uint64_t u64; ++ struct cvmx_npi_buff_size_outputx_s { ++ uint64_t reserved_23_63:41; ++ uint64_t isize:7; ++ uint64_t bsize:16; ++ } s; ++ struct cvmx_npi_buff_size_outputx_s cn30xx; ++ struct cvmx_npi_buff_size_outputx_s cn31xx; ++ struct cvmx_npi_buff_size_outputx_s cn38xx; ++ struct cvmx_npi_buff_size_outputx_s cn38xxp2; ++ struct cvmx_npi_buff_size_outputx_s cn50xx; ++ struct cvmx_npi_buff_size_outputx_s cn58xx; ++ struct cvmx_npi_buff_size_outputx_s cn58xxp1; ++}; ++ ++union cvmx_npi_comp_ctl { ++ uint64_t u64; ++ struct cvmx_npi_comp_ctl_s { ++ uint64_t reserved_10_63:54; ++ uint64_t pctl:5; ++ uint64_t nctl:5; ++ } s; ++ struct cvmx_npi_comp_ctl_s cn50xx; ++ struct cvmx_npi_comp_ctl_s cn58xx; ++ struct cvmx_npi_comp_ctl_s cn58xxp1; ++}; ++ ++union cvmx_npi_ctl_status { ++ uint64_t u64; ++ struct cvmx_npi_ctl_status_s { ++ uint64_t reserved_63_63:1; ++ uint64_t chip_rev:8; ++ uint64_t dis_pniw:1; ++ uint64_t out3_enb:1; ++ uint64_t out2_enb:1; ++ uint64_t out1_enb:1; ++ uint64_t out0_enb:1; ++ uint64_t ins3_enb:1; ++ uint64_t ins2_enb:1; ++ uint64_t ins1_enb:1; ++ uint64_t ins0_enb:1; ++ uint64_t ins3_64b:1; ++ uint64_t ins2_64b:1; ++ uint64_t ins1_64b:1; ++ uint64_t ins0_64b:1; ++ uint64_t pci_wdis:1; ++ uint64_t wait_com:1; ++ uint64_t reserved_37_39:3; ++ uint64_t max_word:5; ++ uint64_t reserved_10_31:22; ++ uint64_t timer:10; ++ } s; ++ struct cvmx_npi_ctl_status_cn30xx { ++ uint64_t reserved_63_63:1; ++ uint64_t chip_rev:8; ++ uint64_t dis_pniw:1; ++ uint64_t reserved_51_53:3; ++ uint64_t out0_enb:1; ++ uint64_t reserved_47_49:3; ++ uint64_t ins0_enb:1; ++ uint64_t reserved_43_45:3; ++ uint64_t ins0_64b:1; ++ uint64_t pci_wdis:1; ++ uint64_t wait_com:1; ++ uint64_t reserved_37_39:3; ++ uint64_t max_word:5; ++ uint64_t reserved_10_31:22; ++ uint64_t timer:10; ++ } cn30xx; ++ struct cvmx_npi_ctl_status_cn31xx { ++ uint64_t reserved_63_63:1; ++ uint64_t chip_rev:8; ++ uint64_t dis_pniw:1; ++ uint64_t reserved_52_53:2; ++ uint64_t out1_enb:1; ++ uint64_t out0_enb:1; ++ uint64_t reserved_48_49:2; ++ uint64_t ins1_enb:1; ++ uint64_t ins0_enb:1; ++ uint64_t reserved_44_45:2; ++ uint64_t ins1_64b:1; ++ uint64_t ins0_64b:1; ++ uint64_t pci_wdis:1; ++ uint64_t wait_com:1; ++ uint64_t reserved_37_39:3; ++ uint64_t max_word:5; ++ uint64_t reserved_10_31:22; ++ uint64_t timer:10; ++ } cn31xx; ++ struct cvmx_npi_ctl_status_s cn38xx; ++ struct cvmx_npi_ctl_status_s cn38xxp2; ++ struct cvmx_npi_ctl_status_cn31xx cn50xx; ++ struct cvmx_npi_ctl_status_s cn58xx; ++ struct cvmx_npi_ctl_status_s cn58xxp1; ++}; ++ ++union cvmx_npi_dbg_select { ++ uint64_t u64; ++ struct cvmx_npi_dbg_select_s { ++ uint64_t reserved_16_63:48; ++ uint64_t dbg_sel:16; ++ } s; ++ struct cvmx_npi_dbg_select_s cn30xx; ++ struct cvmx_npi_dbg_select_s cn31xx; ++ struct cvmx_npi_dbg_select_s cn38xx; ++ struct cvmx_npi_dbg_select_s cn38xxp2; ++ struct cvmx_npi_dbg_select_s cn50xx; ++ struct cvmx_npi_dbg_select_s cn58xx; ++ struct cvmx_npi_dbg_select_s cn58xxp1; ++}; ++ ++union cvmx_npi_dma_control { ++ uint64_t u64; ++ struct cvmx_npi_dma_control_s { ++ uint64_t reserved_36_63:28; ++ uint64_t b0_lend:1; ++ uint64_t dwb_denb:1; ++ uint64_t dwb_ichk:9; ++ uint64_t fpa_que:3; ++ uint64_t o_add1:1; ++ uint64_t o_ro:1; ++ uint64_t o_ns:1; ++ uint64_t o_es:2; ++ uint64_t o_mode:1; ++ uint64_t hp_enb:1; ++ uint64_t lp_enb:1; ++ uint64_t csize:14; ++ } s; ++ struct cvmx_npi_dma_control_s cn30xx; ++ struct cvmx_npi_dma_control_s cn31xx; ++ struct cvmx_npi_dma_control_s cn38xx; ++ struct cvmx_npi_dma_control_s cn38xxp2; ++ struct cvmx_npi_dma_control_s cn50xx; ++ struct cvmx_npi_dma_control_s cn58xx; ++ struct cvmx_npi_dma_control_s cn58xxp1; ++}; ++ ++union cvmx_npi_dma_highp_counts { ++ uint64_t u64; ++ struct cvmx_npi_dma_highp_counts_s { ++ uint64_t reserved_39_63:25; ++ uint64_t fcnt:7; ++ uint64_t dbell:32; ++ } s; ++ struct cvmx_npi_dma_highp_counts_s cn30xx; ++ struct cvmx_npi_dma_highp_counts_s cn31xx; ++ struct cvmx_npi_dma_highp_counts_s cn38xx; ++ struct cvmx_npi_dma_highp_counts_s cn38xxp2; ++ struct cvmx_npi_dma_highp_counts_s cn50xx; ++ struct cvmx_npi_dma_highp_counts_s cn58xx; ++ struct cvmx_npi_dma_highp_counts_s cn58xxp1; ++}; ++ ++union cvmx_npi_dma_highp_naddr { ++ uint64_t u64; ++ struct cvmx_npi_dma_highp_naddr_s { ++ uint64_t reserved_40_63:24; ++ uint64_t state:4; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_npi_dma_highp_naddr_s cn30xx; ++ struct cvmx_npi_dma_highp_naddr_s cn31xx; ++ struct cvmx_npi_dma_highp_naddr_s cn38xx; ++ struct cvmx_npi_dma_highp_naddr_s cn38xxp2; ++ struct cvmx_npi_dma_highp_naddr_s cn50xx; ++ struct cvmx_npi_dma_highp_naddr_s cn58xx; ++ struct cvmx_npi_dma_highp_naddr_s cn58xxp1; ++}; ++ ++union cvmx_npi_dma_lowp_counts { ++ uint64_t u64; ++ struct cvmx_npi_dma_lowp_counts_s { ++ uint64_t reserved_39_63:25; ++ uint64_t fcnt:7; ++ uint64_t dbell:32; ++ } s; ++ struct cvmx_npi_dma_lowp_counts_s cn30xx; ++ struct cvmx_npi_dma_lowp_counts_s cn31xx; ++ struct cvmx_npi_dma_lowp_counts_s cn38xx; ++ struct cvmx_npi_dma_lowp_counts_s cn38xxp2; ++ struct cvmx_npi_dma_lowp_counts_s cn50xx; ++ struct cvmx_npi_dma_lowp_counts_s cn58xx; ++ struct cvmx_npi_dma_lowp_counts_s cn58xxp1; ++}; ++ ++union cvmx_npi_dma_lowp_naddr { ++ uint64_t u64; ++ struct cvmx_npi_dma_lowp_naddr_s { ++ uint64_t reserved_40_63:24; ++ uint64_t state:4; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_npi_dma_lowp_naddr_s cn30xx; ++ struct cvmx_npi_dma_lowp_naddr_s cn31xx; ++ struct cvmx_npi_dma_lowp_naddr_s cn38xx; ++ struct cvmx_npi_dma_lowp_naddr_s cn38xxp2; ++ struct cvmx_npi_dma_lowp_naddr_s cn50xx; ++ struct cvmx_npi_dma_lowp_naddr_s cn58xx; ++ struct cvmx_npi_dma_lowp_naddr_s cn58xxp1; ++}; ++ ++union cvmx_npi_highp_dbell { ++ uint64_t u64; ++ struct cvmx_npi_highp_dbell_s { ++ uint64_t reserved_16_63:48; ++ uint64_t dbell:16; ++ } s; ++ struct cvmx_npi_highp_dbell_s cn30xx; ++ struct cvmx_npi_highp_dbell_s cn31xx; ++ struct cvmx_npi_highp_dbell_s cn38xx; ++ struct cvmx_npi_highp_dbell_s cn38xxp2; ++ struct cvmx_npi_highp_dbell_s cn50xx; ++ struct cvmx_npi_highp_dbell_s cn58xx; ++ struct cvmx_npi_highp_dbell_s cn58xxp1; ++}; ++ ++union cvmx_npi_highp_ibuff_saddr { ++ uint64_t u64; ++ struct cvmx_npi_highp_ibuff_saddr_s { ++ uint64_t reserved_36_63:28; ++ uint64_t saddr:36; ++ } s; ++ struct cvmx_npi_highp_ibuff_saddr_s cn30xx; ++ struct cvmx_npi_highp_ibuff_saddr_s cn31xx; ++ struct cvmx_npi_highp_ibuff_saddr_s cn38xx; ++ struct cvmx_npi_highp_ibuff_saddr_s cn38xxp2; ++ struct cvmx_npi_highp_ibuff_saddr_s cn50xx; ++ struct cvmx_npi_highp_ibuff_saddr_s cn58xx; ++ struct cvmx_npi_highp_ibuff_saddr_s cn58xxp1; ++}; ++ ++union cvmx_npi_input_control { ++ uint64_t u64; ++ struct cvmx_npi_input_control_s { ++ uint64_t reserved_23_63:41; ++ uint64_t pkt_rr:1; ++ uint64_t pbp_dhi:13; ++ uint64_t d_nsr:1; ++ uint64_t d_esr:2; ++ uint64_t d_ror:1; ++ uint64_t use_csr:1; ++ uint64_t nsr:1; ++ uint64_t esr:2; ++ uint64_t ror:1; ++ } s; ++ struct cvmx_npi_input_control_cn30xx { ++ uint64_t reserved_22_63:42; ++ uint64_t pbp_dhi:13; ++ uint64_t d_nsr:1; ++ uint64_t d_esr:2; ++ uint64_t d_ror:1; ++ uint64_t use_csr:1; ++ uint64_t nsr:1; ++ uint64_t esr:2; ++ uint64_t ror:1; ++ } cn30xx; ++ struct cvmx_npi_input_control_cn30xx cn31xx; ++ struct cvmx_npi_input_control_s cn38xx; ++ struct cvmx_npi_input_control_cn30xx cn38xxp2; ++ struct cvmx_npi_input_control_s cn50xx; ++ struct cvmx_npi_input_control_s cn58xx; ++ struct cvmx_npi_input_control_s cn58xxp1; ++}; ++ ++union cvmx_npi_int_enb { ++ uint64_t u64; ++ struct cvmx_npi_int_enb_s { ++ uint64_t reserved_62_63:2; ++ uint64_t q1_a_f:1; ++ uint64_t q1_s_e:1; ++ uint64_t pdf_p_f:1; ++ uint64_t pdf_p_e:1; ++ uint64_t pcf_p_f:1; ++ uint64_t pcf_p_e:1; ++ uint64_t rdx_s_e:1; ++ uint64_t rwx_s_e:1; ++ uint64_t pnc_a_f:1; ++ uint64_t pnc_s_e:1; ++ uint64_t com_a_f:1; ++ uint64_t com_s_e:1; ++ uint64_t q3_a_f:1; ++ uint64_t q3_s_e:1; ++ uint64_t q2_a_f:1; ++ uint64_t q2_s_e:1; ++ uint64_t pcr_a_f:1; ++ uint64_t pcr_s_e:1; ++ uint64_t fcr_a_f:1; ++ uint64_t fcr_s_e:1; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t i3_pperr:1; ++ uint64_t i2_pperr:1; ++ uint64_t i1_pperr:1; ++ uint64_t i0_pperr:1; ++ uint64_t p3_ptout:1; ++ uint64_t p2_ptout:1; ++ uint64_t p1_ptout:1; ++ uint64_t p0_ptout:1; ++ uint64_t p3_pperr:1; ++ uint64_t p2_pperr:1; ++ uint64_t p1_pperr:1; ++ uint64_t p0_pperr:1; ++ uint64_t g3_rtout:1; ++ uint64_t g2_rtout:1; ++ uint64_t g1_rtout:1; ++ uint64_t g0_rtout:1; ++ uint64_t p3_perr:1; ++ uint64_t p2_perr:1; ++ uint64_t p1_perr:1; ++ uint64_t p0_perr:1; ++ uint64_t p3_rtout:1; ++ uint64_t p2_rtout:1; ++ uint64_t p1_rtout:1; ++ uint64_t p0_rtout:1; ++ uint64_t i3_overf:1; ++ uint64_t i2_overf:1; ++ uint64_t i1_overf:1; ++ uint64_t i0_overf:1; ++ uint64_t i3_rtout:1; ++ uint64_t i2_rtout:1; ++ uint64_t i1_rtout:1; ++ uint64_t i0_rtout:1; ++ uint64_t po3_2sml:1; ++ uint64_t po2_2sml:1; ++ uint64_t po1_2sml:1; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } s; ++ struct cvmx_npi_int_enb_cn30xx { ++ uint64_t reserved_62_63:2; ++ uint64_t q1_a_f:1; ++ uint64_t q1_s_e:1; ++ uint64_t pdf_p_f:1; ++ uint64_t pdf_p_e:1; ++ uint64_t pcf_p_f:1; ++ uint64_t pcf_p_e:1; ++ uint64_t rdx_s_e:1; ++ uint64_t rwx_s_e:1; ++ uint64_t pnc_a_f:1; ++ uint64_t pnc_s_e:1; ++ uint64_t com_a_f:1; ++ uint64_t com_s_e:1; ++ uint64_t q3_a_f:1; ++ uint64_t q3_s_e:1; ++ uint64_t q2_a_f:1; ++ uint64_t q2_s_e:1; ++ uint64_t pcr_a_f:1; ++ uint64_t pcr_s_e:1; ++ uint64_t fcr_a_f:1; ++ uint64_t fcr_s_e:1; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t reserved_36_38:3; ++ uint64_t i0_pperr:1; ++ uint64_t reserved_32_34:3; ++ uint64_t p0_ptout:1; ++ uint64_t reserved_28_30:3; ++ uint64_t p0_pperr:1; ++ uint64_t reserved_24_26:3; ++ uint64_t g0_rtout:1; ++ uint64_t reserved_20_22:3; ++ uint64_t p0_perr:1; ++ uint64_t reserved_16_18:3; ++ uint64_t p0_rtout:1; ++ uint64_t reserved_12_14:3; ++ uint64_t i0_overf:1; ++ uint64_t reserved_8_10:3; ++ uint64_t i0_rtout:1; ++ uint64_t reserved_4_6:3; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn30xx; ++ struct cvmx_npi_int_enb_cn31xx { ++ uint64_t reserved_62_63:2; ++ uint64_t q1_a_f:1; ++ uint64_t q1_s_e:1; ++ uint64_t pdf_p_f:1; ++ uint64_t pdf_p_e:1; ++ uint64_t pcf_p_f:1; ++ uint64_t pcf_p_e:1; ++ uint64_t rdx_s_e:1; ++ uint64_t rwx_s_e:1; ++ uint64_t pnc_a_f:1; ++ uint64_t pnc_s_e:1; ++ uint64_t com_a_f:1; ++ uint64_t com_s_e:1; ++ uint64_t q3_a_f:1; ++ uint64_t q3_s_e:1; ++ uint64_t q2_a_f:1; ++ uint64_t q2_s_e:1; ++ uint64_t pcr_a_f:1; ++ uint64_t pcr_s_e:1; ++ uint64_t fcr_a_f:1; ++ uint64_t fcr_s_e:1; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t reserved_37_38:2; ++ uint64_t i1_pperr:1; ++ uint64_t i0_pperr:1; ++ uint64_t reserved_33_34:2; ++ uint64_t p1_ptout:1; ++ uint64_t p0_ptout:1; ++ uint64_t reserved_29_30:2; ++ uint64_t p1_pperr:1; ++ uint64_t p0_pperr:1; ++ uint64_t reserved_25_26:2; ++ uint64_t g1_rtout:1; ++ uint64_t g0_rtout:1; ++ uint64_t reserved_21_22:2; ++ uint64_t p1_perr:1; ++ uint64_t p0_perr:1; ++ uint64_t reserved_17_18:2; ++ uint64_t p1_rtout:1; ++ uint64_t p0_rtout:1; ++ uint64_t reserved_13_14:2; ++ uint64_t i1_overf:1; ++ uint64_t i0_overf:1; ++ uint64_t reserved_9_10:2; ++ uint64_t i1_rtout:1; ++ uint64_t i0_rtout:1; ++ uint64_t reserved_5_6:2; ++ uint64_t po1_2sml:1; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn31xx; ++ struct cvmx_npi_int_enb_s cn38xx; ++ struct cvmx_npi_int_enb_cn38xxp2 { ++ uint64_t reserved_42_63:22; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t i3_pperr:1; ++ uint64_t i2_pperr:1; ++ uint64_t i1_pperr:1; ++ uint64_t i0_pperr:1; ++ uint64_t p3_ptout:1; ++ uint64_t p2_ptout:1; ++ uint64_t p1_ptout:1; ++ uint64_t p0_ptout:1; ++ uint64_t p3_pperr:1; ++ uint64_t p2_pperr:1; ++ uint64_t p1_pperr:1; ++ uint64_t p0_pperr:1; ++ uint64_t g3_rtout:1; ++ uint64_t g2_rtout:1; ++ uint64_t g1_rtout:1; ++ uint64_t g0_rtout:1; ++ uint64_t p3_perr:1; ++ uint64_t p2_perr:1; ++ uint64_t p1_perr:1; ++ uint64_t p0_perr:1; ++ uint64_t p3_rtout:1; ++ uint64_t p2_rtout:1; ++ uint64_t p1_rtout:1; ++ uint64_t p0_rtout:1; ++ uint64_t i3_overf:1; ++ uint64_t i2_overf:1; ++ uint64_t i1_overf:1; ++ uint64_t i0_overf:1; ++ uint64_t i3_rtout:1; ++ uint64_t i2_rtout:1; ++ uint64_t i1_rtout:1; ++ uint64_t i0_rtout:1; ++ uint64_t po3_2sml:1; ++ uint64_t po2_2sml:1; ++ uint64_t po1_2sml:1; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn38xxp2; ++ struct cvmx_npi_int_enb_cn31xx cn50xx; ++ struct cvmx_npi_int_enb_s cn58xx; ++ struct cvmx_npi_int_enb_s cn58xxp1; ++}; ++ ++union cvmx_npi_int_sum { ++ uint64_t u64; ++ struct cvmx_npi_int_sum_s { ++ uint64_t reserved_62_63:2; ++ uint64_t q1_a_f:1; ++ uint64_t q1_s_e:1; ++ uint64_t pdf_p_f:1; ++ uint64_t pdf_p_e:1; ++ uint64_t pcf_p_f:1; ++ uint64_t pcf_p_e:1; ++ uint64_t rdx_s_e:1; ++ uint64_t rwx_s_e:1; ++ uint64_t pnc_a_f:1; ++ uint64_t pnc_s_e:1; ++ uint64_t com_a_f:1; ++ uint64_t com_s_e:1; ++ uint64_t q3_a_f:1; ++ uint64_t q3_s_e:1; ++ uint64_t q2_a_f:1; ++ uint64_t q2_s_e:1; ++ uint64_t pcr_a_f:1; ++ uint64_t pcr_s_e:1; ++ uint64_t fcr_a_f:1; ++ uint64_t fcr_s_e:1; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t i3_pperr:1; ++ uint64_t i2_pperr:1; ++ uint64_t i1_pperr:1; ++ uint64_t i0_pperr:1; ++ uint64_t p3_ptout:1; ++ uint64_t p2_ptout:1; ++ uint64_t p1_ptout:1; ++ uint64_t p0_ptout:1; ++ uint64_t p3_pperr:1; ++ uint64_t p2_pperr:1; ++ uint64_t p1_pperr:1; ++ uint64_t p0_pperr:1; ++ uint64_t g3_rtout:1; ++ uint64_t g2_rtout:1; ++ uint64_t g1_rtout:1; ++ uint64_t g0_rtout:1; ++ uint64_t p3_perr:1; ++ uint64_t p2_perr:1; ++ uint64_t p1_perr:1; ++ uint64_t p0_perr:1; ++ uint64_t p3_rtout:1; ++ uint64_t p2_rtout:1; ++ uint64_t p1_rtout:1; ++ uint64_t p0_rtout:1; ++ uint64_t i3_overf:1; ++ uint64_t i2_overf:1; ++ uint64_t i1_overf:1; ++ uint64_t i0_overf:1; ++ uint64_t i3_rtout:1; ++ uint64_t i2_rtout:1; ++ uint64_t i1_rtout:1; ++ uint64_t i0_rtout:1; ++ uint64_t po3_2sml:1; ++ uint64_t po2_2sml:1; ++ uint64_t po1_2sml:1; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } s; ++ struct cvmx_npi_int_sum_cn30xx { ++ uint64_t reserved_62_63:2; ++ uint64_t q1_a_f:1; ++ uint64_t q1_s_e:1; ++ uint64_t pdf_p_f:1; ++ uint64_t pdf_p_e:1; ++ uint64_t pcf_p_f:1; ++ uint64_t pcf_p_e:1; ++ uint64_t rdx_s_e:1; ++ uint64_t rwx_s_e:1; ++ uint64_t pnc_a_f:1; ++ uint64_t pnc_s_e:1; ++ uint64_t com_a_f:1; ++ uint64_t com_s_e:1; ++ uint64_t q3_a_f:1; ++ uint64_t q3_s_e:1; ++ uint64_t q2_a_f:1; ++ uint64_t q2_s_e:1; ++ uint64_t pcr_a_f:1; ++ uint64_t pcr_s_e:1; ++ uint64_t fcr_a_f:1; ++ uint64_t fcr_s_e:1; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t reserved_36_38:3; ++ uint64_t i0_pperr:1; ++ uint64_t reserved_32_34:3; ++ uint64_t p0_ptout:1; ++ uint64_t reserved_28_30:3; ++ uint64_t p0_pperr:1; ++ uint64_t reserved_24_26:3; ++ uint64_t g0_rtout:1; ++ uint64_t reserved_20_22:3; ++ uint64_t p0_perr:1; ++ uint64_t reserved_16_18:3; ++ uint64_t p0_rtout:1; ++ uint64_t reserved_12_14:3; ++ uint64_t i0_overf:1; ++ uint64_t reserved_8_10:3; ++ uint64_t i0_rtout:1; ++ uint64_t reserved_4_6:3; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn30xx; ++ struct cvmx_npi_int_sum_cn31xx { ++ uint64_t reserved_62_63:2; ++ uint64_t q1_a_f:1; ++ uint64_t q1_s_e:1; ++ uint64_t pdf_p_f:1; ++ uint64_t pdf_p_e:1; ++ uint64_t pcf_p_f:1; ++ uint64_t pcf_p_e:1; ++ uint64_t rdx_s_e:1; ++ uint64_t rwx_s_e:1; ++ uint64_t pnc_a_f:1; ++ uint64_t pnc_s_e:1; ++ uint64_t com_a_f:1; ++ uint64_t com_s_e:1; ++ uint64_t q3_a_f:1; ++ uint64_t q3_s_e:1; ++ uint64_t q2_a_f:1; ++ uint64_t q2_s_e:1; ++ uint64_t pcr_a_f:1; ++ uint64_t pcr_s_e:1; ++ uint64_t fcr_a_f:1; ++ uint64_t fcr_s_e:1; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t reserved_37_38:2; ++ uint64_t i1_pperr:1; ++ uint64_t i0_pperr:1; ++ uint64_t reserved_33_34:2; ++ uint64_t p1_ptout:1; ++ uint64_t p0_ptout:1; ++ uint64_t reserved_29_30:2; ++ uint64_t p1_pperr:1; ++ uint64_t p0_pperr:1; ++ uint64_t reserved_25_26:2; ++ uint64_t g1_rtout:1; ++ uint64_t g0_rtout:1; ++ uint64_t reserved_21_22:2; ++ uint64_t p1_perr:1; ++ uint64_t p0_perr:1; ++ uint64_t reserved_17_18:2; ++ uint64_t p1_rtout:1; ++ uint64_t p0_rtout:1; ++ uint64_t reserved_13_14:2; ++ uint64_t i1_overf:1; ++ uint64_t i0_overf:1; ++ uint64_t reserved_9_10:2; ++ uint64_t i1_rtout:1; ++ uint64_t i0_rtout:1; ++ uint64_t reserved_5_6:2; ++ uint64_t po1_2sml:1; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn31xx; ++ struct cvmx_npi_int_sum_s cn38xx; ++ struct cvmx_npi_int_sum_cn38xxp2 { ++ uint64_t reserved_42_63:22; ++ uint64_t iobdma:1; ++ uint64_t p_dperr:1; ++ uint64_t win_rto:1; ++ uint64_t i3_pperr:1; ++ uint64_t i2_pperr:1; ++ uint64_t i1_pperr:1; ++ uint64_t i0_pperr:1; ++ uint64_t p3_ptout:1; ++ uint64_t p2_ptout:1; ++ uint64_t p1_ptout:1; ++ uint64_t p0_ptout:1; ++ uint64_t p3_pperr:1; ++ uint64_t p2_pperr:1; ++ uint64_t p1_pperr:1; ++ uint64_t p0_pperr:1; ++ uint64_t g3_rtout:1; ++ uint64_t g2_rtout:1; ++ uint64_t g1_rtout:1; ++ uint64_t g0_rtout:1; ++ uint64_t p3_perr:1; ++ uint64_t p2_perr:1; ++ uint64_t p1_perr:1; ++ uint64_t p0_perr:1; ++ uint64_t p3_rtout:1; ++ uint64_t p2_rtout:1; ++ uint64_t p1_rtout:1; ++ uint64_t p0_rtout:1; ++ uint64_t i3_overf:1; ++ uint64_t i2_overf:1; ++ uint64_t i1_overf:1; ++ uint64_t i0_overf:1; ++ uint64_t i3_rtout:1; ++ uint64_t i2_rtout:1; ++ uint64_t i1_rtout:1; ++ uint64_t i0_rtout:1; ++ uint64_t po3_2sml:1; ++ uint64_t po2_2sml:1; ++ uint64_t po1_2sml:1; ++ uint64_t po0_2sml:1; ++ uint64_t pci_rsl:1; ++ uint64_t rml_wto:1; ++ uint64_t rml_rto:1; ++ } cn38xxp2; ++ struct cvmx_npi_int_sum_cn31xx cn50xx; ++ struct cvmx_npi_int_sum_s cn58xx; ++ struct cvmx_npi_int_sum_s cn58xxp1; ++}; ++ ++union cvmx_npi_lowp_dbell { ++ uint64_t u64; ++ struct cvmx_npi_lowp_dbell_s { ++ uint64_t reserved_16_63:48; ++ uint64_t dbell:16; ++ } s; ++ struct cvmx_npi_lowp_dbell_s cn30xx; ++ struct cvmx_npi_lowp_dbell_s cn31xx; ++ struct cvmx_npi_lowp_dbell_s cn38xx; ++ struct cvmx_npi_lowp_dbell_s cn38xxp2; ++ struct cvmx_npi_lowp_dbell_s cn50xx; ++ struct cvmx_npi_lowp_dbell_s cn58xx; ++ struct cvmx_npi_lowp_dbell_s cn58xxp1; ++}; ++ ++union cvmx_npi_lowp_ibuff_saddr { ++ uint64_t u64; ++ struct cvmx_npi_lowp_ibuff_saddr_s { ++ uint64_t reserved_36_63:28; ++ uint64_t saddr:36; ++ } s; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn30xx; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn31xx; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn38xx; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn38xxp2; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn50xx; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn58xx; ++ struct cvmx_npi_lowp_ibuff_saddr_s cn58xxp1; ++}; ++ ++union cvmx_npi_mem_access_subidx { ++ uint64_t u64; ++ struct cvmx_npi_mem_access_subidx_s { ++ uint64_t reserved_38_63:26; ++ uint64_t shortl:1; ++ uint64_t nmerge:1; ++ uint64_t esr:2; ++ uint64_t esw:2; ++ uint64_t nsr:1; ++ uint64_t nsw:1; ++ uint64_t ror:1; ++ uint64_t row:1; ++ uint64_t ba:28; ++ } s; ++ struct cvmx_npi_mem_access_subidx_s cn30xx; ++ struct cvmx_npi_mem_access_subidx_cn31xx { ++ uint64_t reserved_36_63:28; ++ uint64_t esr:2; ++ uint64_t esw:2; ++ uint64_t nsr:1; ++ uint64_t nsw:1; ++ uint64_t ror:1; ++ uint64_t row:1; ++ uint64_t ba:28; ++ } cn31xx; ++ struct cvmx_npi_mem_access_subidx_s cn38xx; ++ struct cvmx_npi_mem_access_subidx_cn31xx cn38xxp2; ++ struct cvmx_npi_mem_access_subidx_s cn50xx; ++ struct cvmx_npi_mem_access_subidx_s cn58xx; ++ struct cvmx_npi_mem_access_subidx_s cn58xxp1; ++}; ++ ++union cvmx_npi_msi_rcv { ++ uint64_t u64; ++ struct cvmx_npi_msi_rcv_s { ++ uint64_t int_vec:64; ++ } s; ++ struct cvmx_npi_msi_rcv_s cn30xx; ++ struct cvmx_npi_msi_rcv_s cn31xx; ++ struct cvmx_npi_msi_rcv_s cn38xx; ++ struct cvmx_npi_msi_rcv_s cn38xxp2; ++ struct cvmx_npi_msi_rcv_s cn50xx; ++ struct cvmx_npi_msi_rcv_s cn58xx; ++ struct cvmx_npi_msi_rcv_s cn58xxp1; ++}; ++ ++union cvmx_npi_num_desc_outputx { ++ uint64_t u64; ++ struct cvmx_npi_num_desc_outputx_s { ++ uint64_t reserved_32_63:32; ++ uint64_t size:32; ++ } s; ++ struct cvmx_npi_num_desc_outputx_s cn30xx; ++ struct cvmx_npi_num_desc_outputx_s cn31xx; ++ struct cvmx_npi_num_desc_outputx_s cn38xx; ++ struct cvmx_npi_num_desc_outputx_s cn38xxp2; ++ struct cvmx_npi_num_desc_outputx_s cn50xx; ++ struct cvmx_npi_num_desc_outputx_s cn58xx; ++ struct cvmx_npi_num_desc_outputx_s cn58xxp1; ++}; ++ ++union cvmx_npi_output_control { ++ uint64_t u64; ++ struct cvmx_npi_output_control_s { ++ uint64_t reserved_49_63:15; ++ uint64_t pkt_rr:1; ++ uint64_t p3_bmode:1; ++ uint64_t p2_bmode:1; ++ uint64_t p1_bmode:1; ++ uint64_t p0_bmode:1; ++ uint64_t o3_es:2; ++ uint64_t o3_ns:1; ++ uint64_t o3_ro:1; ++ uint64_t o2_es:2; ++ uint64_t o2_ns:1; ++ uint64_t o2_ro:1; ++ uint64_t o1_es:2; ++ uint64_t o1_ns:1; ++ uint64_t o1_ro:1; ++ uint64_t o0_es:2; ++ uint64_t o0_ns:1; ++ uint64_t o0_ro:1; ++ uint64_t o3_csrm:1; ++ uint64_t o2_csrm:1; ++ uint64_t o1_csrm:1; ++ uint64_t o0_csrm:1; ++ uint64_t reserved_20_23:4; ++ uint64_t iptr_o3:1; ++ uint64_t iptr_o2:1; ++ uint64_t iptr_o1:1; ++ uint64_t iptr_o0:1; ++ uint64_t esr_sl3:2; ++ uint64_t nsr_sl3:1; ++ uint64_t ror_sl3:1; ++ uint64_t esr_sl2:2; ++ uint64_t nsr_sl2:1; ++ uint64_t ror_sl2:1; ++ uint64_t esr_sl1:2; ++ uint64_t nsr_sl1:1; ++ uint64_t ror_sl1:1; ++ uint64_t esr_sl0:2; ++ uint64_t nsr_sl0:1; ++ uint64_t ror_sl0:1; ++ } s; ++ struct cvmx_npi_output_control_cn30xx { ++ uint64_t reserved_45_63:19; ++ uint64_t p0_bmode:1; ++ uint64_t reserved_32_43:12; ++ uint64_t o0_es:2; ++ uint64_t o0_ns:1; ++ uint64_t o0_ro:1; ++ uint64_t reserved_25_27:3; ++ uint64_t o0_csrm:1; ++ uint64_t reserved_17_23:7; ++ uint64_t iptr_o0:1; ++ uint64_t reserved_4_15:12; ++ uint64_t esr_sl0:2; ++ uint64_t nsr_sl0:1; ++ uint64_t ror_sl0:1; ++ } cn30xx; ++ struct cvmx_npi_output_control_cn31xx { ++ uint64_t reserved_46_63:18; ++ uint64_t p1_bmode:1; ++ uint64_t p0_bmode:1; ++ uint64_t reserved_36_43:8; ++ uint64_t o1_es:2; ++ uint64_t o1_ns:1; ++ uint64_t o1_ro:1; ++ uint64_t o0_es:2; ++ uint64_t o0_ns:1; ++ uint64_t o0_ro:1; ++ uint64_t reserved_26_27:2; ++ uint64_t o1_csrm:1; ++ uint64_t o0_csrm:1; ++ uint64_t reserved_18_23:6; ++ uint64_t iptr_o1:1; ++ uint64_t iptr_o0:1; ++ uint64_t reserved_8_15:8; ++ uint64_t esr_sl1:2; ++ uint64_t nsr_sl1:1; ++ uint64_t ror_sl1:1; ++ uint64_t esr_sl0:2; ++ uint64_t nsr_sl0:1; ++ uint64_t ror_sl0:1; ++ } cn31xx; ++ struct cvmx_npi_output_control_s cn38xx; ++ struct cvmx_npi_output_control_cn38xxp2 { ++ uint64_t reserved_48_63:16; ++ uint64_t p3_bmode:1; ++ uint64_t p2_bmode:1; ++ uint64_t p1_bmode:1; ++ uint64_t p0_bmode:1; ++ uint64_t o3_es:2; ++ uint64_t o3_ns:1; ++ uint64_t o3_ro:1; ++ uint64_t o2_es:2; ++ uint64_t o2_ns:1; ++ uint64_t o2_ro:1; ++ uint64_t o1_es:2; ++ uint64_t o1_ns:1; ++ uint64_t o1_ro:1; ++ uint64_t o0_es:2; ++ uint64_t o0_ns:1; ++ uint64_t o0_ro:1; ++ uint64_t o3_csrm:1; ++ uint64_t o2_csrm:1; ++ uint64_t o1_csrm:1; ++ uint64_t o0_csrm:1; ++ uint64_t reserved_20_23:4; ++ uint64_t iptr_o3:1; ++ uint64_t iptr_o2:1; ++ uint64_t iptr_o1:1; ++ uint64_t iptr_o0:1; ++ uint64_t esr_sl3:2; ++ uint64_t nsr_sl3:1; ++ uint64_t ror_sl3:1; ++ uint64_t esr_sl2:2; ++ uint64_t nsr_sl2:1; ++ uint64_t ror_sl2:1; ++ uint64_t esr_sl1:2; ++ uint64_t nsr_sl1:1; ++ uint64_t ror_sl1:1; ++ uint64_t esr_sl0:2; ++ uint64_t nsr_sl0:1; ++ uint64_t ror_sl0:1; ++ } cn38xxp2; ++ struct cvmx_npi_output_control_cn50xx { ++ uint64_t reserved_49_63:15; ++ uint64_t pkt_rr:1; ++ uint64_t reserved_46_47:2; ++ uint64_t p1_bmode:1; ++ uint64_t p0_bmode:1; ++ uint64_t reserved_36_43:8; ++ uint64_t o1_es:2; ++ uint64_t o1_ns:1; ++ uint64_t o1_ro:1; ++ uint64_t o0_es:2; ++ uint64_t o0_ns:1; ++ uint64_t o0_ro:1; ++ uint64_t reserved_26_27:2; ++ uint64_t o1_csrm:1; ++ uint64_t o0_csrm:1; ++ uint64_t reserved_18_23:6; ++ uint64_t iptr_o1:1; ++ uint64_t iptr_o0:1; ++ uint64_t reserved_8_15:8; ++ uint64_t esr_sl1:2; ++ uint64_t nsr_sl1:1; ++ uint64_t ror_sl1:1; ++ uint64_t esr_sl0:2; ++ uint64_t nsr_sl0:1; ++ uint64_t ror_sl0:1; ++ } cn50xx; ++ struct cvmx_npi_output_control_s cn58xx; ++ struct cvmx_npi_output_control_s cn58xxp1; ++}; ++ ++union cvmx_npi_px_dbpair_addr { ++ uint64_t u64; ++ struct cvmx_npi_px_dbpair_addr_s { ++ uint64_t reserved_63_63:1; ++ uint64_t state:2; ++ uint64_t naddr:61; ++ } s; ++ struct cvmx_npi_px_dbpair_addr_s cn30xx; ++ struct cvmx_npi_px_dbpair_addr_s cn31xx; ++ struct cvmx_npi_px_dbpair_addr_s cn38xx; ++ struct cvmx_npi_px_dbpair_addr_s cn38xxp2; ++ struct cvmx_npi_px_dbpair_addr_s cn50xx; ++ struct cvmx_npi_px_dbpair_addr_s cn58xx; ++ struct cvmx_npi_px_dbpair_addr_s cn58xxp1; ++}; ++ ++union cvmx_npi_px_instr_addr { ++ uint64_t u64; ++ struct cvmx_npi_px_instr_addr_s { ++ uint64_t state:3; ++ uint64_t naddr:61; ++ } s; ++ struct cvmx_npi_px_instr_addr_s cn30xx; ++ struct cvmx_npi_px_instr_addr_s cn31xx; ++ struct cvmx_npi_px_instr_addr_s cn38xx; ++ struct cvmx_npi_px_instr_addr_s cn38xxp2; ++ struct cvmx_npi_px_instr_addr_s cn50xx; ++ struct cvmx_npi_px_instr_addr_s cn58xx; ++ struct cvmx_npi_px_instr_addr_s cn58xxp1; ++}; ++ ++union cvmx_npi_px_instr_cnts { ++ uint64_t u64; ++ struct cvmx_npi_px_instr_cnts_s { ++ uint64_t reserved_38_63:26; ++ uint64_t fcnt:6; ++ uint64_t avail:32; ++ } s; ++ struct cvmx_npi_px_instr_cnts_s cn30xx; ++ struct cvmx_npi_px_instr_cnts_s cn31xx; ++ struct cvmx_npi_px_instr_cnts_s cn38xx; ++ struct cvmx_npi_px_instr_cnts_s cn38xxp2; ++ struct cvmx_npi_px_instr_cnts_s cn50xx; ++ struct cvmx_npi_px_instr_cnts_s cn58xx; ++ struct cvmx_npi_px_instr_cnts_s cn58xxp1; ++}; ++ ++union cvmx_npi_px_pair_cnts { ++ uint64_t u64; ++ struct cvmx_npi_px_pair_cnts_s { ++ uint64_t reserved_37_63:27; ++ uint64_t fcnt:5; ++ uint64_t avail:32; ++ } s; ++ struct cvmx_npi_px_pair_cnts_s cn30xx; ++ struct cvmx_npi_px_pair_cnts_s cn31xx; ++ struct cvmx_npi_px_pair_cnts_s cn38xx; ++ struct cvmx_npi_px_pair_cnts_s cn38xxp2; ++ struct cvmx_npi_px_pair_cnts_s cn50xx; ++ struct cvmx_npi_px_pair_cnts_s cn58xx; ++ struct cvmx_npi_px_pair_cnts_s cn58xxp1; ++}; ++ ++union cvmx_npi_pci_burst_size { ++ uint64_t u64; ++ struct cvmx_npi_pci_burst_size_s { ++ uint64_t reserved_14_63:50; ++ uint64_t wr_brst:7; ++ uint64_t rd_brst:7; ++ } s; ++ struct cvmx_npi_pci_burst_size_s cn30xx; ++ struct cvmx_npi_pci_burst_size_s cn31xx; ++ struct cvmx_npi_pci_burst_size_s cn38xx; ++ struct cvmx_npi_pci_burst_size_s cn38xxp2; ++ struct cvmx_npi_pci_burst_size_s cn50xx; ++ struct cvmx_npi_pci_burst_size_s cn58xx; ++ struct cvmx_npi_pci_burst_size_s cn58xxp1; ++}; ++ ++union cvmx_npi_pci_int_arb_cfg { ++ uint64_t u64; ++ struct cvmx_npi_pci_int_arb_cfg_s { ++ uint64_t reserved_13_63:51; ++ uint64_t hostmode:1; ++ uint64_t pci_ovr:4; ++ uint64_t reserved_5_7:3; ++ uint64_t en:1; ++ uint64_t park_mod:1; ++ uint64_t park_dev:3; ++ } s; ++ struct cvmx_npi_pci_int_arb_cfg_cn30xx { ++ uint64_t reserved_5_63:59; ++ uint64_t en:1; ++ uint64_t park_mod:1; ++ uint64_t park_dev:3; ++ } cn30xx; ++ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn31xx; ++ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xx; ++ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xxp2; ++ struct cvmx_npi_pci_int_arb_cfg_s cn50xx; ++ struct cvmx_npi_pci_int_arb_cfg_s cn58xx; ++ struct cvmx_npi_pci_int_arb_cfg_s cn58xxp1; ++}; ++ ++union cvmx_npi_pci_read_cmd { ++ uint64_t u64; ++ struct cvmx_npi_pci_read_cmd_s { ++ uint64_t reserved_11_63:53; ++ uint64_t cmd_size:11; ++ } s; ++ struct cvmx_npi_pci_read_cmd_s cn30xx; ++ struct cvmx_npi_pci_read_cmd_s cn31xx; ++ struct cvmx_npi_pci_read_cmd_s cn38xx; ++ struct cvmx_npi_pci_read_cmd_s cn38xxp2; ++ struct cvmx_npi_pci_read_cmd_s cn50xx; ++ struct cvmx_npi_pci_read_cmd_s cn58xx; ++ struct cvmx_npi_pci_read_cmd_s cn58xxp1; ++}; ++ ++union cvmx_npi_port32_instr_hdr { ++ uint64_t u64; ++ struct cvmx_npi_port32_instr_hdr_s { ++ uint64_t reserved_44_63:20; ++ uint64_t pbp:1; ++ uint64_t rsv_f:5; ++ uint64_t rparmode:2; ++ uint64_t rsv_e:1; ++ uint64_t rskp_len:7; ++ uint64_t rsv_d:6; ++ uint64_t use_ihdr:1; ++ uint64_t rsv_c:5; ++ uint64_t par_mode:2; ++ uint64_t rsv_b:1; ++ uint64_t skp_len:7; ++ uint64_t rsv_a:6; ++ } s; ++ struct cvmx_npi_port32_instr_hdr_s cn30xx; ++ struct cvmx_npi_port32_instr_hdr_s cn31xx; ++ struct cvmx_npi_port32_instr_hdr_s cn38xx; ++ struct cvmx_npi_port32_instr_hdr_s cn38xxp2; ++ struct cvmx_npi_port32_instr_hdr_s cn50xx; ++ struct cvmx_npi_port32_instr_hdr_s cn58xx; ++ struct cvmx_npi_port32_instr_hdr_s cn58xxp1; ++}; ++ ++union cvmx_npi_port33_instr_hdr { ++ uint64_t u64; ++ struct cvmx_npi_port33_instr_hdr_s { ++ uint64_t reserved_44_63:20; ++ uint64_t pbp:1; ++ uint64_t rsv_f:5; ++ uint64_t rparmode:2; ++ uint64_t rsv_e:1; ++ uint64_t rskp_len:7; ++ uint64_t rsv_d:6; ++ uint64_t use_ihdr:1; ++ uint64_t rsv_c:5; ++ uint64_t par_mode:2; ++ uint64_t rsv_b:1; ++ uint64_t skp_len:7; ++ uint64_t rsv_a:6; ++ } s; ++ struct cvmx_npi_port33_instr_hdr_s cn31xx; ++ struct cvmx_npi_port33_instr_hdr_s cn38xx; ++ struct cvmx_npi_port33_instr_hdr_s cn38xxp2; ++ struct cvmx_npi_port33_instr_hdr_s cn50xx; ++ struct cvmx_npi_port33_instr_hdr_s cn58xx; ++ struct cvmx_npi_port33_instr_hdr_s cn58xxp1; ++}; ++ ++union cvmx_npi_port34_instr_hdr { ++ uint64_t u64; ++ struct cvmx_npi_port34_instr_hdr_s { ++ uint64_t reserved_44_63:20; ++ uint64_t pbp:1; ++ uint64_t rsv_f:5; ++ uint64_t rparmode:2; ++ uint64_t rsv_e:1; ++ uint64_t rskp_len:7; ++ uint64_t rsv_d:6; ++ uint64_t use_ihdr:1; ++ uint64_t rsv_c:5; ++ uint64_t par_mode:2; ++ uint64_t rsv_b:1; ++ uint64_t skp_len:7; ++ uint64_t rsv_a:6; ++ } s; ++ struct cvmx_npi_port34_instr_hdr_s cn38xx; ++ struct cvmx_npi_port34_instr_hdr_s cn38xxp2; ++ struct cvmx_npi_port34_instr_hdr_s cn58xx; ++ struct cvmx_npi_port34_instr_hdr_s cn58xxp1; ++}; ++ ++union cvmx_npi_port35_instr_hdr { ++ uint64_t u64; ++ struct cvmx_npi_port35_instr_hdr_s { ++ uint64_t reserved_44_63:20; ++ uint64_t pbp:1; ++ uint64_t rsv_f:5; ++ uint64_t rparmode:2; ++ uint64_t rsv_e:1; ++ uint64_t rskp_len:7; ++ uint64_t rsv_d:6; ++ uint64_t use_ihdr:1; ++ uint64_t rsv_c:5; ++ uint64_t par_mode:2; ++ uint64_t rsv_b:1; ++ uint64_t skp_len:7; ++ uint64_t rsv_a:6; ++ } s; ++ struct cvmx_npi_port35_instr_hdr_s cn38xx; ++ struct cvmx_npi_port35_instr_hdr_s cn38xxp2; ++ struct cvmx_npi_port35_instr_hdr_s cn58xx; ++ struct cvmx_npi_port35_instr_hdr_s cn58xxp1; ++}; ++ ++union cvmx_npi_port_bp_control { ++ uint64_t u64; ++ struct cvmx_npi_port_bp_control_s { ++ uint64_t reserved_8_63:56; ++ uint64_t bp_on:4; ++ uint64_t enb:4; ++ } s; ++ struct cvmx_npi_port_bp_control_s cn30xx; ++ struct cvmx_npi_port_bp_control_s cn31xx; ++ struct cvmx_npi_port_bp_control_s cn38xx; ++ struct cvmx_npi_port_bp_control_s cn38xxp2; ++ struct cvmx_npi_port_bp_control_s cn50xx; ++ struct cvmx_npi_port_bp_control_s cn58xx; ++ struct cvmx_npi_port_bp_control_s cn58xxp1; ++}; ++ ++union cvmx_npi_rsl_int_blocks { ++ uint64_t u64; ++ struct cvmx_npi_rsl_int_blocks_s { ++ uint64_t reserved_32_63:32; ++ uint64_t rint_31:1; ++ uint64_t iob:1; ++ uint64_t reserved_28_29:2; ++ uint64_t rint_27:1; ++ uint64_t rint_26:1; ++ uint64_t rint_25:1; ++ uint64_t rint_24:1; ++ uint64_t asx1:1; ++ uint64_t asx0:1; ++ uint64_t rint_21:1; ++ uint64_t pip:1; ++ uint64_t spx1:1; ++ uint64_t spx0:1; ++ uint64_t lmc:1; ++ uint64_t l2c:1; ++ uint64_t rint_15:1; ++ uint64_t reserved_13_14:2; ++ uint64_t pow:1; ++ uint64_t tim:1; ++ uint64_t pko:1; ++ uint64_t ipd:1; ++ uint64_t rint_8:1; ++ uint64_t zip:1; ++ uint64_t dfa:1; ++ uint64_t fpa:1; ++ uint64_t key:1; ++ uint64_t npi:1; ++ uint64_t gmx1:1; ++ uint64_t gmx0:1; ++ uint64_t mio:1; ++ } s; ++ struct cvmx_npi_rsl_int_blocks_cn30xx { ++ uint64_t reserved_32_63:32; ++ uint64_t rint_31:1; ++ uint64_t iob:1; ++ uint64_t rint_29:1; ++ uint64_t rint_28:1; ++ uint64_t rint_27:1; ++ uint64_t rint_26:1; ++ uint64_t rint_25:1; ++ uint64_t rint_24:1; ++ uint64_t asx1:1; ++ uint64_t asx0:1; ++ uint64_t rint_21:1; ++ uint64_t pip:1; ++ uint64_t spx1:1; ++ uint64_t spx0:1; ++ uint64_t lmc:1; ++ uint64_t l2c:1; ++ uint64_t rint_15:1; ++ uint64_t rint_14:1; ++ uint64_t usb:1; ++ uint64_t pow:1; ++ uint64_t tim:1; ++ uint64_t pko:1; ++ uint64_t ipd:1; ++ uint64_t rint_8:1; ++ uint64_t zip:1; ++ uint64_t dfa:1; ++ uint64_t fpa:1; ++ uint64_t key:1; ++ uint64_t npi:1; ++ uint64_t gmx1:1; ++ uint64_t gmx0:1; ++ uint64_t mio:1; ++ } cn30xx; ++ struct cvmx_npi_rsl_int_blocks_cn30xx cn31xx; ++ struct cvmx_npi_rsl_int_blocks_cn38xx { ++ uint64_t reserved_32_63:32; ++ uint64_t rint_31:1; ++ uint64_t iob:1; ++ uint64_t rint_29:1; ++ uint64_t rint_28:1; ++ uint64_t rint_27:1; ++ uint64_t rint_26:1; ++ uint64_t rint_25:1; ++ uint64_t rint_24:1; ++ uint64_t asx1:1; ++ uint64_t asx0:1; ++ uint64_t rint_21:1; ++ uint64_t pip:1; ++ uint64_t spx1:1; ++ uint64_t spx0:1; ++ uint64_t lmc:1; ++ uint64_t l2c:1; ++ uint64_t rint_15:1; ++ uint64_t rint_14:1; ++ uint64_t rint_13:1; ++ uint64_t pow:1; ++ uint64_t tim:1; ++ uint64_t pko:1; ++ uint64_t ipd:1; ++ uint64_t rint_8:1; ++ uint64_t zip:1; ++ uint64_t dfa:1; ++ uint64_t fpa:1; ++ uint64_t key:1; ++ uint64_t npi:1; ++ uint64_t gmx1:1; ++ uint64_t gmx0:1; ++ uint64_t mio:1; ++ } cn38xx; ++ struct cvmx_npi_rsl_int_blocks_cn38xx cn38xxp2; ++ struct cvmx_npi_rsl_int_blocks_cn50xx { ++ uint64_t reserved_31_63:33; ++ uint64_t iob:1; ++ uint64_t lmc1:1; ++ uint64_t agl:1; ++ uint64_t reserved_24_27:4; ++ uint64_t asx1:1; ++ uint64_t asx0:1; ++ uint64_t reserved_21_21:1; ++ uint64_t pip:1; ++ uint64_t spx1:1; ++ uint64_t spx0:1; ++ uint64_t lmc:1; ++ uint64_t l2c:1; ++ uint64_t reserved_15_15:1; ++ uint64_t rad:1; ++ uint64_t usb:1; ++ uint64_t pow:1; ++ uint64_t tim:1; ++ uint64_t pko:1; ++ uint64_t ipd:1; ++ uint64_t reserved_8_8:1; ++ uint64_t zip:1; ++ uint64_t dfa:1; ++ uint64_t fpa:1; ++ uint64_t key:1; ++ uint64_t npi:1; ++ uint64_t gmx1:1; ++ uint64_t gmx0:1; ++ uint64_t mio:1; ++ } cn50xx; ++ struct cvmx_npi_rsl_int_blocks_cn38xx cn58xx; ++ struct cvmx_npi_rsl_int_blocks_cn38xx cn58xxp1; ++}; ++ ++union cvmx_npi_size_inputx { ++ uint64_t u64; ++ struct cvmx_npi_size_inputx_s { ++ uint64_t reserved_32_63:32; ++ uint64_t size:32; ++ } s; ++ struct cvmx_npi_size_inputx_s cn30xx; ++ struct cvmx_npi_size_inputx_s cn31xx; ++ struct cvmx_npi_size_inputx_s cn38xx; ++ struct cvmx_npi_size_inputx_s cn38xxp2; ++ struct cvmx_npi_size_inputx_s cn50xx; ++ struct cvmx_npi_size_inputx_s cn58xx; ++ struct cvmx_npi_size_inputx_s cn58xxp1; ++}; ++ ++union cvmx_npi_win_read_to { ++ uint64_t u64; ++ struct cvmx_npi_win_read_to_s { ++ uint64_t reserved_32_63:32; ++ uint64_t time:32; ++ } s; ++ struct cvmx_npi_win_read_to_s cn30xx; ++ struct cvmx_npi_win_read_to_s cn31xx; ++ struct cvmx_npi_win_read_to_s cn38xx; ++ struct cvmx_npi_win_read_to_s cn38xxp2; ++ struct cvmx_npi_win_read_to_s cn50xx; ++ struct cvmx_npi_win_read_to_s cn58xx; ++ struct cvmx_npi_win_read_to_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-pci-defs.h +@@ -0,0 +1,1645 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PCI_DEFS_H__ ++#define __CVMX_PCI_DEFS_H__ ++ ++#define CVMX_PCI_BAR1_INDEXX(offset) \ ++ (0x0000000000000100ull + (((offset) & 31) * 4)) ++#define CVMX_PCI_BIST_REG \ ++ (0x00000000000001C0ull) ++#define CVMX_PCI_CFG00 \ ++ (0x0000000000000000ull) ++#define CVMX_PCI_CFG01 \ ++ (0x0000000000000004ull) ++#define CVMX_PCI_CFG02 \ ++ (0x0000000000000008ull) ++#define CVMX_PCI_CFG03 \ ++ (0x000000000000000Cull) ++#define CVMX_PCI_CFG04 \ ++ (0x0000000000000010ull) ++#define CVMX_PCI_CFG05 \ ++ (0x0000000000000014ull) ++#define CVMX_PCI_CFG06 \ ++ (0x0000000000000018ull) ++#define CVMX_PCI_CFG07 \ ++ (0x000000000000001Cull) ++#define CVMX_PCI_CFG08 \ ++ (0x0000000000000020ull) ++#define CVMX_PCI_CFG09 \ ++ (0x0000000000000024ull) ++#define CVMX_PCI_CFG10 \ ++ (0x0000000000000028ull) ++#define CVMX_PCI_CFG11 \ ++ (0x000000000000002Cull) ++#define CVMX_PCI_CFG12 \ ++ (0x0000000000000030ull) ++#define CVMX_PCI_CFG13 \ ++ (0x0000000000000034ull) ++#define CVMX_PCI_CFG15 \ ++ (0x000000000000003Cull) ++#define CVMX_PCI_CFG16 \ ++ (0x0000000000000040ull) ++#define CVMX_PCI_CFG17 \ ++ (0x0000000000000044ull) ++#define CVMX_PCI_CFG18 \ ++ (0x0000000000000048ull) ++#define CVMX_PCI_CFG19 \ ++ (0x000000000000004Cull) ++#define CVMX_PCI_CFG20 \ ++ (0x0000000000000050ull) ++#define CVMX_PCI_CFG21 \ ++ (0x0000000000000054ull) ++#define CVMX_PCI_CFG22 \ ++ (0x0000000000000058ull) ++#define CVMX_PCI_CFG56 \ ++ (0x00000000000000E0ull) ++#define CVMX_PCI_CFG57 \ ++ (0x00000000000000E4ull) ++#define CVMX_PCI_CFG58 \ ++ (0x00000000000000E8ull) ++#define CVMX_PCI_CFG59 \ ++ (0x00000000000000ECull) ++#define CVMX_PCI_CFG60 \ ++ (0x00000000000000F0ull) ++#define CVMX_PCI_CFG61 \ ++ (0x00000000000000F4ull) ++#define CVMX_PCI_CFG62 \ ++ (0x00000000000000F8ull) ++#define CVMX_PCI_CFG63 \ ++ (0x00000000000000FCull) ++#define CVMX_PCI_CNT_REG \ ++ (0x00000000000001B8ull) ++#define CVMX_PCI_CTL_STATUS_2 \ ++ (0x000000000000018Cull) ++#define CVMX_PCI_DBELL_0 \ ++ (0x0000000000000080ull) ++#define CVMX_PCI_DBELL_1 \ ++ (0x0000000000000088ull) ++#define CVMX_PCI_DBELL_2 \ ++ (0x0000000000000090ull) ++#define CVMX_PCI_DBELL_3 \ ++ (0x0000000000000098ull) ++#define CVMX_PCI_DBELL_X(offset) \ ++ (0x0000000000000080ull + (((offset) & 3) * 8)) ++#define CVMX_PCI_DMA_CNT0 \ ++ (0x00000000000000A0ull) ++#define CVMX_PCI_DMA_CNT1 \ ++ (0x00000000000000A8ull) ++#define CVMX_PCI_DMA_CNTX(offset) \ ++ (0x00000000000000A0ull + (((offset) & 1) * 8)) ++#define CVMX_PCI_DMA_INT_LEV0 \ ++ (0x00000000000000A4ull) ++#define CVMX_PCI_DMA_INT_LEV1 \ ++ (0x00000000000000ACull) ++#define CVMX_PCI_DMA_INT_LEVX(offset) \ ++ (0x00000000000000A4ull + (((offset) & 1) * 8)) ++#define CVMX_PCI_DMA_TIME0 \ ++ (0x00000000000000B0ull) ++#define CVMX_PCI_DMA_TIME1 \ ++ (0x00000000000000B4ull) ++#define CVMX_PCI_DMA_TIMEX(offset) \ ++ (0x00000000000000B0ull + (((offset) & 1) * 4)) ++#define CVMX_PCI_INSTR_COUNT0 \ ++ (0x0000000000000084ull) ++#define CVMX_PCI_INSTR_COUNT1 \ ++ (0x000000000000008Cull) ++#define CVMX_PCI_INSTR_COUNT2 \ ++ (0x0000000000000094ull) ++#define CVMX_PCI_INSTR_COUNT3 \ ++ (0x000000000000009Cull) ++#define CVMX_PCI_INSTR_COUNTX(offset) \ ++ (0x0000000000000084ull + (((offset) & 3) * 8)) ++#define CVMX_PCI_INT_ENB \ ++ (0x0000000000000038ull) ++#define CVMX_PCI_INT_ENB2 \ ++ (0x00000000000001A0ull) ++#define CVMX_PCI_INT_SUM \ ++ (0x0000000000000030ull) ++#define CVMX_PCI_INT_SUM2 \ ++ (0x0000000000000198ull) ++#define CVMX_PCI_MSI_RCV \ ++ (0x00000000000000F0ull) ++#define CVMX_PCI_PKTS_SENT0 \ ++ (0x0000000000000040ull) ++#define CVMX_PCI_PKTS_SENT1 \ ++ (0x0000000000000050ull) ++#define CVMX_PCI_PKTS_SENT2 \ ++ (0x0000000000000060ull) ++#define CVMX_PCI_PKTS_SENT3 \ ++ (0x0000000000000070ull) ++#define CVMX_PCI_PKTS_SENTX(offset) \ ++ (0x0000000000000040ull + (((offset) & 3) * 16)) ++#define CVMX_PCI_PKTS_SENT_INT_LEV0 \ ++ (0x0000000000000048ull) ++#define CVMX_PCI_PKTS_SENT_INT_LEV1 \ ++ (0x0000000000000058ull) ++#define CVMX_PCI_PKTS_SENT_INT_LEV2 \ ++ (0x0000000000000068ull) ++#define CVMX_PCI_PKTS_SENT_INT_LEV3 \ ++ (0x0000000000000078ull) ++#define CVMX_PCI_PKTS_SENT_INT_LEVX(offset) \ ++ (0x0000000000000048ull + (((offset) & 3) * 16)) ++#define CVMX_PCI_PKTS_SENT_TIME0 \ ++ (0x000000000000004Cull) ++#define CVMX_PCI_PKTS_SENT_TIME1 \ ++ (0x000000000000005Cull) ++#define CVMX_PCI_PKTS_SENT_TIME2 \ ++ (0x000000000000006Cull) ++#define CVMX_PCI_PKTS_SENT_TIME3 \ ++ (0x000000000000007Cull) ++#define CVMX_PCI_PKTS_SENT_TIMEX(offset) \ ++ (0x000000000000004Cull + (((offset) & 3) * 16)) ++#define CVMX_PCI_PKT_CREDITS0 \ ++ (0x0000000000000044ull) ++#define CVMX_PCI_PKT_CREDITS1 \ ++ (0x0000000000000054ull) ++#define CVMX_PCI_PKT_CREDITS2 \ ++ (0x0000000000000064ull) ++#define CVMX_PCI_PKT_CREDITS3 \ ++ (0x0000000000000074ull) ++#define CVMX_PCI_PKT_CREDITSX(offset) \ ++ (0x0000000000000044ull + (((offset) & 3) * 16)) ++#define CVMX_PCI_READ_CMD_6 \ ++ (0x0000000000000180ull) ++#define CVMX_PCI_READ_CMD_C \ ++ (0x0000000000000184ull) ++#define CVMX_PCI_READ_CMD_E \ ++ (0x0000000000000188ull) ++#define CVMX_PCI_READ_TIMEOUT \ ++ CVMX_ADD_IO_SEG(0x00011F00000000B0ull) ++#define CVMX_PCI_SCM_REG \ ++ (0x00000000000001A8ull) ++#define CVMX_PCI_TSR_REG \ ++ (0x00000000000001B0ull) ++#define CVMX_PCI_WIN_RD_ADDR \ ++ (0x0000000000000008ull) ++#define CVMX_PCI_WIN_RD_DATA \ ++ (0x0000000000000020ull) ++#define CVMX_PCI_WIN_WR_ADDR \ ++ (0x0000000000000000ull) ++#define CVMX_PCI_WIN_WR_DATA \ ++ (0x0000000000000010ull) ++#define CVMX_PCI_WIN_WR_MASK \ ++ (0x0000000000000018ull) ++ ++union cvmx_pci_bar1_indexx { ++ uint32_t u32; ++ struct cvmx_pci_bar1_indexx_s { ++ uint32_t reserved_18_31:14; ++ uint32_t addr_idx:14; ++ uint32_t ca:1; ++ uint32_t end_swp:2; ++ uint32_t addr_v:1; ++ } s; ++ struct cvmx_pci_bar1_indexx_s cn30xx; ++ struct cvmx_pci_bar1_indexx_s cn31xx; ++ struct cvmx_pci_bar1_indexx_s cn38xx; ++ struct cvmx_pci_bar1_indexx_s cn38xxp2; ++ struct cvmx_pci_bar1_indexx_s cn50xx; ++ struct cvmx_pci_bar1_indexx_s cn58xx; ++ struct cvmx_pci_bar1_indexx_s cn58xxp1; ++}; ++ ++union cvmx_pci_bist_reg { ++ uint64_t u64; ++ struct cvmx_pci_bist_reg_s { ++ uint64_t reserved_10_63:54; ++ uint64_t rsp_bs:1; ++ uint64_t dma0_bs:1; ++ uint64_t cmd0_bs:1; ++ uint64_t cmd_bs:1; ++ uint64_t csr2p_bs:1; ++ uint64_t csrr_bs:1; ++ uint64_t rsp2p_bs:1; ++ uint64_t csr2n_bs:1; ++ uint64_t dat2n_bs:1; ++ uint64_t dbg2n_bs:1; ++ } s; ++ struct cvmx_pci_bist_reg_s cn50xx; ++}; ++ ++union cvmx_pci_cfg00 { ++ uint32_t u32; ++ struct cvmx_pci_cfg00_s { ++ uint32_t devid:16; ++ uint32_t vendid:16; ++ } s; ++ struct cvmx_pci_cfg00_s cn30xx; ++ struct cvmx_pci_cfg00_s cn31xx; ++ struct cvmx_pci_cfg00_s cn38xx; ++ struct cvmx_pci_cfg00_s cn38xxp2; ++ struct cvmx_pci_cfg00_s cn50xx; ++ struct cvmx_pci_cfg00_s cn58xx; ++ struct cvmx_pci_cfg00_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg01 { ++ uint32_t u32; ++ struct cvmx_pci_cfg01_s { ++ uint32_t dpe:1; ++ uint32_t sse:1; ++ uint32_t rma:1; ++ uint32_t rta:1; ++ uint32_t sta:1; ++ uint32_t devt:2; ++ uint32_t mdpe:1; ++ uint32_t fbb:1; ++ uint32_t reserved_22_22:1; ++ uint32_t m66:1; ++ uint32_t cle:1; ++ uint32_t i_stat:1; ++ uint32_t reserved_11_18:8; ++ uint32_t i_dis:1; ++ uint32_t fbbe:1; ++ uint32_t see:1; ++ uint32_t ads:1; ++ uint32_t pee:1; ++ uint32_t vps:1; ++ uint32_t mwice:1; ++ uint32_t scse:1; ++ uint32_t me:1; ++ uint32_t msae:1; ++ uint32_t isae:1; ++ } s; ++ struct cvmx_pci_cfg01_s cn30xx; ++ struct cvmx_pci_cfg01_s cn31xx; ++ struct cvmx_pci_cfg01_s cn38xx; ++ struct cvmx_pci_cfg01_s cn38xxp2; ++ struct cvmx_pci_cfg01_s cn50xx; ++ struct cvmx_pci_cfg01_s cn58xx; ++ struct cvmx_pci_cfg01_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg02 { ++ uint32_t u32; ++ struct cvmx_pci_cfg02_s { ++ uint32_t cc:24; ++ uint32_t rid:8; ++ } s; ++ struct cvmx_pci_cfg02_s cn30xx; ++ struct cvmx_pci_cfg02_s cn31xx; ++ struct cvmx_pci_cfg02_s cn38xx; ++ struct cvmx_pci_cfg02_s cn38xxp2; ++ struct cvmx_pci_cfg02_s cn50xx; ++ struct cvmx_pci_cfg02_s cn58xx; ++ struct cvmx_pci_cfg02_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg03 { ++ uint32_t u32; ++ struct cvmx_pci_cfg03_s { ++ uint32_t bcap:1; ++ uint32_t brb:1; ++ uint32_t reserved_28_29:2; ++ uint32_t bcod:4; ++ uint32_t ht:8; ++ uint32_t lt:8; ++ uint32_t cls:8; ++ } s; ++ struct cvmx_pci_cfg03_s cn30xx; ++ struct cvmx_pci_cfg03_s cn31xx; ++ struct cvmx_pci_cfg03_s cn38xx; ++ struct cvmx_pci_cfg03_s cn38xxp2; ++ struct cvmx_pci_cfg03_s cn50xx; ++ struct cvmx_pci_cfg03_s cn58xx; ++ struct cvmx_pci_cfg03_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg04 { ++ uint32_t u32; ++ struct cvmx_pci_cfg04_s { ++ uint32_t lbase:20; ++ uint32_t lbasez:8; ++ uint32_t pf:1; ++ uint32_t typ:2; ++ uint32_t mspc:1; ++ } s; ++ struct cvmx_pci_cfg04_s cn30xx; ++ struct cvmx_pci_cfg04_s cn31xx; ++ struct cvmx_pci_cfg04_s cn38xx; ++ struct cvmx_pci_cfg04_s cn38xxp2; ++ struct cvmx_pci_cfg04_s cn50xx; ++ struct cvmx_pci_cfg04_s cn58xx; ++ struct cvmx_pci_cfg04_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg05 { ++ uint32_t u32; ++ struct cvmx_pci_cfg05_s { ++ uint32_t hbase:32; ++ } s; ++ struct cvmx_pci_cfg05_s cn30xx; ++ struct cvmx_pci_cfg05_s cn31xx; ++ struct cvmx_pci_cfg05_s cn38xx; ++ struct cvmx_pci_cfg05_s cn38xxp2; ++ struct cvmx_pci_cfg05_s cn50xx; ++ struct cvmx_pci_cfg05_s cn58xx; ++ struct cvmx_pci_cfg05_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg06 { ++ uint32_t u32; ++ struct cvmx_pci_cfg06_s { ++ uint32_t lbase:5; ++ uint32_t lbasez:23; ++ uint32_t pf:1; ++ uint32_t typ:2; ++ uint32_t mspc:1; ++ } s; ++ struct cvmx_pci_cfg06_s cn30xx; ++ struct cvmx_pci_cfg06_s cn31xx; ++ struct cvmx_pci_cfg06_s cn38xx; ++ struct cvmx_pci_cfg06_s cn38xxp2; ++ struct cvmx_pci_cfg06_s cn50xx; ++ struct cvmx_pci_cfg06_s cn58xx; ++ struct cvmx_pci_cfg06_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg07 { ++ uint32_t u32; ++ struct cvmx_pci_cfg07_s { ++ uint32_t hbase:32; ++ } s; ++ struct cvmx_pci_cfg07_s cn30xx; ++ struct cvmx_pci_cfg07_s cn31xx; ++ struct cvmx_pci_cfg07_s cn38xx; ++ struct cvmx_pci_cfg07_s cn38xxp2; ++ struct cvmx_pci_cfg07_s cn50xx; ++ struct cvmx_pci_cfg07_s cn58xx; ++ struct cvmx_pci_cfg07_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg08 { ++ uint32_t u32; ++ struct cvmx_pci_cfg08_s { ++ uint32_t lbasez:28; ++ uint32_t pf:1; ++ uint32_t typ:2; ++ uint32_t mspc:1; ++ } s; ++ struct cvmx_pci_cfg08_s cn30xx; ++ struct cvmx_pci_cfg08_s cn31xx; ++ struct cvmx_pci_cfg08_s cn38xx; ++ struct cvmx_pci_cfg08_s cn38xxp2; ++ struct cvmx_pci_cfg08_s cn50xx; ++ struct cvmx_pci_cfg08_s cn58xx; ++ struct cvmx_pci_cfg08_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg09 { ++ uint32_t u32; ++ struct cvmx_pci_cfg09_s { ++ uint32_t hbase:25; ++ uint32_t hbasez:7; ++ } s; ++ struct cvmx_pci_cfg09_s cn30xx; ++ struct cvmx_pci_cfg09_s cn31xx; ++ struct cvmx_pci_cfg09_s cn38xx; ++ struct cvmx_pci_cfg09_s cn38xxp2; ++ struct cvmx_pci_cfg09_s cn50xx; ++ struct cvmx_pci_cfg09_s cn58xx; ++ struct cvmx_pci_cfg09_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg10 { ++ uint32_t u32; ++ struct cvmx_pci_cfg10_s { ++ uint32_t cisp:32; ++ } s; ++ struct cvmx_pci_cfg10_s cn30xx; ++ struct cvmx_pci_cfg10_s cn31xx; ++ struct cvmx_pci_cfg10_s cn38xx; ++ struct cvmx_pci_cfg10_s cn38xxp2; ++ struct cvmx_pci_cfg10_s cn50xx; ++ struct cvmx_pci_cfg10_s cn58xx; ++ struct cvmx_pci_cfg10_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg11 { ++ uint32_t u32; ++ struct cvmx_pci_cfg11_s { ++ uint32_t ssid:16; ++ uint32_t ssvid:16; ++ } s; ++ struct cvmx_pci_cfg11_s cn30xx; ++ struct cvmx_pci_cfg11_s cn31xx; ++ struct cvmx_pci_cfg11_s cn38xx; ++ struct cvmx_pci_cfg11_s cn38xxp2; ++ struct cvmx_pci_cfg11_s cn50xx; ++ struct cvmx_pci_cfg11_s cn58xx; ++ struct cvmx_pci_cfg11_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg12 { ++ uint32_t u32; ++ struct cvmx_pci_cfg12_s { ++ uint32_t erbar:16; ++ uint32_t erbarz:5; ++ uint32_t reserved_1_10:10; ++ uint32_t erbar_en:1; ++ } s; ++ struct cvmx_pci_cfg12_s cn30xx; ++ struct cvmx_pci_cfg12_s cn31xx; ++ struct cvmx_pci_cfg12_s cn38xx; ++ struct cvmx_pci_cfg12_s cn38xxp2; ++ struct cvmx_pci_cfg12_s cn50xx; ++ struct cvmx_pci_cfg12_s cn58xx; ++ struct cvmx_pci_cfg12_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg13 { ++ uint32_t u32; ++ struct cvmx_pci_cfg13_s { ++ uint32_t reserved_8_31:24; ++ uint32_t cp:8; ++ } s; ++ struct cvmx_pci_cfg13_s cn30xx; ++ struct cvmx_pci_cfg13_s cn31xx; ++ struct cvmx_pci_cfg13_s cn38xx; ++ struct cvmx_pci_cfg13_s cn38xxp2; ++ struct cvmx_pci_cfg13_s cn50xx; ++ struct cvmx_pci_cfg13_s cn58xx; ++ struct cvmx_pci_cfg13_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg15 { ++ uint32_t u32; ++ struct cvmx_pci_cfg15_s { ++ uint32_t ml:8; ++ uint32_t mg:8; ++ uint32_t inta:8; ++ uint32_t il:8; ++ } s; ++ struct cvmx_pci_cfg15_s cn30xx; ++ struct cvmx_pci_cfg15_s cn31xx; ++ struct cvmx_pci_cfg15_s cn38xx; ++ struct cvmx_pci_cfg15_s cn38xxp2; ++ struct cvmx_pci_cfg15_s cn50xx; ++ struct cvmx_pci_cfg15_s cn58xx; ++ struct cvmx_pci_cfg15_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg16 { ++ uint32_t u32; ++ struct cvmx_pci_cfg16_s { ++ uint32_t trdnpr:1; ++ uint32_t trdard:1; ++ uint32_t rdsati:1; ++ uint32_t trdrs:1; ++ uint32_t trtae:1; ++ uint32_t twsei:1; ++ uint32_t twsen:1; ++ uint32_t twtae:1; ++ uint32_t tmae:1; ++ uint32_t tslte:3; ++ uint32_t tilt:4; ++ uint32_t pbe:12; ++ uint32_t dppmr:1; ++ uint32_t reserved_2_2:1; ++ uint32_t tswc:1; ++ uint32_t mltd:1; ++ } s; ++ struct cvmx_pci_cfg16_s cn30xx; ++ struct cvmx_pci_cfg16_s cn31xx; ++ struct cvmx_pci_cfg16_s cn38xx; ++ struct cvmx_pci_cfg16_s cn38xxp2; ++ struct cvmx_pci_cfg16_s cn50xx; ++ struct cvmx_pci_cfg16_s cn58xx; ++ struct cvmx_pci_cfg16_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg17 { ++ uint32_t u32; ++ struct cvmx_pci_cfg17_s { ++ uint32_t tscme:32; ++ } s; ++ struct cvmx_pci_cfg17_s cn30xx; ++ struct cvmx_pci_cfg17_s cn31xx; ++ struct cvmx_pci_cfg17_s cn38xx; ++ struct cvmx_pci_cfg17_s cn38xxp2; ++ struct cvmx_pci_cfg17_s cn50xx; ++ struct cvmx_pci_cfg17_s cn58xx; ++ struct cvmx_pci_cfg17_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg18 { ++ uint32_t u32; ++ struct cvmx_pci_cfg18_s { ++ uint32_t tdsrps:32; ++ } s; ++ struct cvmx_pci_cfg18_s cn30xx; ++ struct cvmx_pci_cfg18_s cn31xx; ++ struct cvmx_pci_cfg18_s cn38xx; ++ struct cvmx_pci_cfg18_s cn38xxp2; ++ struct cvmx_pci_cfg18_s cn50xx; ++ struct cvmx_pci_cfg18_s cn58xx; ++ struct cvmx_pci_cfg18_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg19 { ++ uint32_t u32; ++ struct cvmx_pci_cfg19_s { ++ uint32_t mrbcm:1; ++ uint32_t mrbci:1; ++ uint32_t mdwe:1; ++ uint32_t mdre:1; ++ uint32_t mdrimc:1; ++ uint32_t mdrrmc:3; ++ uint32_t tmes:8; ++ uint32_t teci:1; ++ uint32_t tmei:1; ++ uint32_t tmse:1; ++ uint32_t tmdpes:1; ++ uint32_t tmapes:1; ++ uint32_t reserved_9_10:2; ++ uint32_t tibcd:1; ++ uint32_t tibde:1; ++ uint32_t reserved_6_6:1; ++ uint32_t tidomc:1; ++ uint32_t tdomc:5; ++ } s; ++ struct cvmx_pci_cfg19_s cn30xx; ++ struct cvmx_pci_cfg19_s cn31xx; ++ struct cvmx_pci_cfg19_s cn38xx; ++ struct cvmx_pci_cfg19_s cn38xxp2; ++ struct cvmx_pci_cfg19_s cn50xx; ++ struct cvmx_pci_cfg19_s cn58xx; ++ struct cvmx_pci_cfg19_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg20 { ++ uint32_t u32; ++ struct cvmx_pci_cfg20_s { ++ uint32_t mdsp:32; ++ } s; ++ struct cvmx_pci_cfg20_s cn30xx; ++ struct cvmx_pci_cfg20_s cn31xx; ++ struct cvmx_pci_cfg20_s cn38xx; ++ struct cvmx_pci_cfg20_s cn38xxp2; ++ struct cvmx_pci_cfg20_s cn50xx; ++ struct cvmx_pci_cfg20_s cn58xx; ++ struct cvmx_pci_cfg20_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg21 { ++ uint32_t u32; ++ struct cvmx_pci_cfg21_s { ++ uint32_t scmre:32; ++ } s; ++ struct cvmx_pci_cfg21_s cn30xx; ++ struct cvmx_pci_cfg21_s cn31xx; ++ struct cvmx_pci_cfg21_s cn38xx; ++ struct cvmx_pci_cfg21_s cn38xxp2; ++ struct cvmx_pci_cfg21_s cn50xx; ++ struct cvmx_pci_cfg21_s cn58xx; ++ struct cvmx_pci_cfg21_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg22 { ++ uint32_t u32; ++ struct cvmx_pci_cfg22_s { ++ uint32_t mac:7; ++ uint32_t reserved_19_24:6; ++ uint32_t flush:1; ++ uint32_t mra:1; ++ uint32_t mtta:1; ++ uint32_t mrv:8; ++ uint32_t mttv:8; ++ } s; ++ struct cvmx_pci_cfg22_s cn30xx; ++ struct cvmx_pci_cfg22_s cn31xx; ++ struct cvmx_pci_cfg22_s cn38xx; ++ struct cvmx_pci_cfg22_s cn38xxp2; ++ struct cvmx_pci_cfg22_s cn50xx; ++ struct cvmx_pci_cfg22_s cn58xx; ++ struct cvmx_pci_cfg22_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg56 { ++ uint32_t u32; ++ struct cvmx_pci_cfg56_s { ++ uint32_t reserved_23_31:9; ++ uint32_t most:3; ++ uint32_t mmbc:2; ++ uint32_t roe:1; ++ uint32_t dpere:1; ++ uint32_t ncp:8; ++ uint32_t pxcid:8; ++ } s; ++ struct cvmx_pci_cfg56_s cn30xx; ++ struct cvmx_pci_cfg56_s cn31xx; ++ struct cvmx_pci_cfg56_s cn38xx; ++ struct cvmx_pci_cfg56_s cn38xxp2; ++ struct cvmx_pci_cfg56_s cn50xx; ++ struct cvmx_pci_cfg56_s cn58xx; ++ struct cvmx_pci_cfg56_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg57 { ++ uint32_t u32; ++ struct cvmx_pci_cfg57_s { ++ uint32_t reserved_30_31:2; ++ uint32_t scemr:1; ++ uint32_t mcrsd:3; ++ uint32_t mostd:3; ++ uint32_t mmrbcd:2; ++ uint32_t dc:1; ++ uint32_t usc:1; ++ uint32_t scd:1; ++ uint32_t m133:1; ++ uint32_t w64:1; ++ uint32_t bn:8; ++ uint32_t dn:5; ++ uint32_t fn:3; ++ } s; ++ struct cvmx_pci_cfg57_s cn30xx; ++ struct cvmx_pci_cfg57_s cn31xx; ++ struct cvmx_pci_cfg57_s cn38xx; ++ struct cvmx_pci_cfg57_s cn38xxp2; ++ struct cvmx_pci_cfg57_s cn50xx; ++ struct cvmx_pci_cfg57_s cn58xx; ++ struct cvmx_pci_cfg57_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg58 { ++ uint32_t u32; ++ struct cvmx_pci_cfg58_s { ++ uint32_t pmes:5; ++ uint32_t d2s:1; ++ uint32_t d1s:1; ++ uint32_t auxc:3; ++ uint32_t dsi:1; ++ uint32_t reserved_20_20:1; ++ uint32_t pmec:1; ++ uint32_t pcimiv:3; ++ uint32_t ncp:8; ++ uint32_t pmcid:8; ++ } s; ++ struct cvmx_pci_cfg58_s cn30xx; ++ struct cvmx_pci_cfg58_s cn31xx; ++ struct cvmx_pci_cfg58_s cn38xx; ++ struct cvmx_pci_cfg58_s cn38xxp2; ++ struct cvmx_pci_cfg58_s cn50xx; ++ struct cvmx_pci_cfg58_s cn58xx; ++ struct cvmx_pci_cfg58_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg59 { ++ uint32_t u32; ++ struct cvmx_pci_cfg59_s { ++ uint32_t pmdia:8; ++ uint32_t bpccen:1; ++ uint32_t bd3h:1; ++ uint32_t reserved_16_21:6; ++ uint32_t pmess:1; ++ uint32_t pmedsia:2; ++ uint32_t pmds:4; ++ uint32_t pmeens:1; ++ uint32_t reserved_2_7:6; ++ uint32_t ps:2; ++ } s; ++ struct cvmx_pci_cfg59_s cn30xx; ++ struct cvmx_pci_cfg59_s cn31xx; ++ struct cvmx_pci_cfg59_s cn38xx; ++ struct cvmx_pci_cfg59_s cn38xxp2; ++ struct cvmx_pci_cfg59_s cn50xx; ++ struct cvmx_pci_cfg59_s cn58xx; ++ struct cvmx_pci_cfg59_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg60 { ++ uint32_t u32; ++ struct cvmx_pci_cfg60_s { ++ uint32_t reserved_24_31:8; ++ uint32_t m64:1; ++ uint32_t mme:3; ++ uint32_t mmc:3; ++ uint32_t msien:1; ++ uint32_t ncp:8; ++ uint32_t msicid:8; ++ } s; ++ struct cvmx_pci_cfg60_s cn30xx; ++ struct cvmx_pci_cfg60_s cn31xx; ++ struct cvmx_pci_cfg60_s cn38xx; ++ struct cvmx_pci_cfg60_s cn38xxp2; ++ struct cvmx_pci_cfg60_s cn50xx; ++ struct cvmx_pci_cfg60_s cn58xx; ++ struct cvmx_pci_cfg60_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg61 { ++ uint32_t u32; ++ struct cvmx_pci_cfg61_s { ++ uint32_t msi31t2:30; ++ uint32_t reserved_0_1:2; ++ } s; ++ struct cvmx_pci_cfg61_s cn30xx; ++ struct cvmx_pci_cfg61_s cn31xx; ++ struct cvmx_pci_cfg61_s cn38xx; ++ struct cvmx_pci_cfg61_s cn38xxp2; ++ struct cvmx_pci_cfg61_s cn50xx; ++ struct cvmx_pci_cfg61_s cn58xx; ++ struct cvmx_pci_cfg61_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg62 { ++ uint32_t u32; ++ struct cvmx_pci_cfg62_s { ++ uint32_t msi:32; ++ } s; ++ struct cvmx_pci_cfg62_s cn30xx; ++ struct cvmx_pci_cfg62_s cn31xx; ++ struct cvmx_pci_cfg62_s cn38xx; ++ struct cvmx_pci_cfg62_s cn38xxp2; ++ struct cvmx_pci_cfg62_s cn50xx; ++ struct cvmx_pci_cfg62_s cn58xx; ++ struct cvmx_pci_cfg62_s cn58xxp1; ++}; ++ ++union cvmx_pci_cfg63 { ++ uint32_t u32; ++ struct cvmx_pci_cfg63_s { ++ uint32_t reserved_16_31:16; ++ uint32_t msimd:16; ++ } s; ++ struct cvmx_pci_cfg63_s cn30xx; ++ struct cvmx_pci_cfg63_s cn31xx; ++ struct cvmx_pci_cfg63_s cn38xx; ++ struct cvmx_pci_cfg63_s cn38xxp2; ++ struct cvmx_pci_cfg63_s cn50xx; ++ struct cvmx_pci_cfg63_s cn58xx; ++ struct cvmx_pci_cfg63_s cn58xxp1; ++}; ++ ++union cvmx_pci_cnt_reg { ++ uint64_t u64; ++ struct cvmx_pci_cnt_reg_s { ++ uint64_t reserved_38_63:26; ++ uint64_t hm_pcix:1; ++ uint64_t hm_speed:2; ++ uint64_t ap_pcix:1; ++ uint64_t ap_speed:2; ++ uint64_t pcicnt:32; ++ } s; ++ struct cvmx_pci_cnt_reg_s cn50xx; ++ struct cvmx_pci_cnt_reg_s cn58xx; ++ struct cvmx_pci_cnt_reg_s cn58xxp1; ++}; ++ ++union cvmx_pci_ctl_status_2 { ++ uint32_t u32; ++ struct cvmx_pci_ctl_status_2_s { ++ uint32_t reserved_29_31:3; ++ uint32_t bb1_hole:3; ++ uint32_t bb1_siz:1; ++ uint32_t bb_ca:1; ++ uint32_t bb_es:2; ++ uint32_t bb1:1; ++ uint32_t bb0:1; ++ uint32_t erst_n:1; ++ uint32_t bar2pres:1; ++ uint32_t scmtyp:1; ++ uint32_t scm:1; ++ uint32_t en_wfilt:1; ++ uint32_t reserved_14_14:1; ++ uint32_t ap_pcix:1; ++ uint32_t ap_64ad:1; ++ uint32_t b12_bist:1; ++ uint32_t pmo_amod:1; ++ uint32_t pmo_fpc:3; ++ uint32_t tsr_hwm:3; ++ uint32_t bar2_enb:1; ++ uint32_t bar2_esx:2; ++ uint32_t bar2_cax:1; ++ } s; ++ struct cvmx_pci_ctl_status_2_s cn30xx; ++ struct cvmx_pci_ctl_status_2_cn31xx { ++ uint32_t reserved_20_31:12; ++ uint32_t erst_n:1; ++ uint32_t bar2pres:1; ++ uint32_t scmtyp:1; ++ uint32_t scm:1; ++ uint32_t en_wfilt:1; ++ uint32_t reserved_14_14:1; ++ uint32_t ap_pcix:1; ++ uint32_t ap_64ad:1; ++ uint32_t b12_bist:1; ++ uint32_t pmo_amod:1; ++ uint32_t pmo_fpc:3; ++ uint32_t tsr_hwm:3; ++ uint32_t bar2_enb:1; ++ uint32_t bar2_esx:2; ++ uint32_t bar2_cax:1; ++ } cn31xx; ++ struct cvmx_pci_ctl_status_2_s cn38xx; ++ struct cvmx_pci_ctl_status_2_cn31xx cn38xxp2; ++ struct cvmx_pci_ctl_status_2_s cn50xx; ++ struct cvmx_pci_ctl_status_2_s cn58xx; ++ struct cvmx_pci_ctl_status_2_s cn58xxp1; ++}; ++ ++union cvmx_pci_dbellx { ++ uint32_t u32; ++ struct cvmx_pci_dbellx_s { ++ uint32_t reserved_16_31:16; ++ uint32_t inc_val:16; ++ } s; ++ struct cvmx_pci_dbellx_s cn30xx; ++ struct cvmx_pci_dbellx_s cn31xx; ++ struct cvmx_pci_dbellx_s cn38xx; ++ struct cvmx_pci_dbellx_s cn38xxp2; ++ struct cvmx_pci_dbellx_s cn50xx; ++ struct cvmx_pci_dbellx_s cn58xx; ++ struct cvmx_pci_dbellx_s cn58xxp1; ++}; ++ ++union cvmx_pci_dma_cntx { ++ uint32_t u32; ++ struct cvmx_pci_dma_cntx_s { ++ uint32_t dma_cnt:32; ++ } s; ++ struct cvmx_pci_dma_cntx_s cn30xx; ++ struct cvmx_pci_dma_cntx_s cn31xx; ++ struct cvmx_pci_dma_cntx_s cn38xx; ++ struct cvmx_pci_dma_cntx_s cn38xxp2; ++ struct cvmx_pci_dma_cntx_s cn50xx; ++ struct cvmx_pci_dma_cntx_s cn58xx; ++ struct cvmx_pci_dma_cntx_s cn58xxp1; ++}; ++ ++union cvmx_pci_dma_int_levx { ++ uint32_t u32; ++ struct cvmx_pci_dma_int_levx_s { ++ uint32_t pkt_cnt:32; ++ } s; ++ struct cvmx_pci_dma_int_levx_s cn30xx; ++ struct cvmx_pci_dma_int_levx_s cn31xx; ++ struct cvmx_pci_dma_int_levx_s cn38xx; ++ struct cvmx_pci_dma_int_levx_s cn38xxp2; ++ struct cvmx_pci_dma_int_levx_s cn50xx; ++ struct cvmx_pci_dma_int_levx_s cn58xx; ++ struct cvmx_pci_dma_int_levx_s cn58xxp1; ++}; ++ ++union cvmx_pci_dma_timex { ++ uint32_t u32; ++ struct cvmx_pci_dma_timex_s { ++ uint32_t dma_time:32; ++ } s; ++ struct cvmx_pci_dma_timex_s cn30xx; ++ struct cvmx_pci_dma_timex_s cn31xx; ++ struct cvmx_pci_dma_timex_s cn38xx; ++ struct cvmx_pci_dma_timex_s cn38xxp2; ++ struct cvmx_pci_dma_timex_s cn50xx; ++ struct cvmx_pci_dma_timex_s cn58xx; ++ struct cvmx_pci_dma_timex_s cn58xxp1; ++}; ++ ++union cvmx_pci_instr_countx { ++ uint32_t u32; ++ struct cvmx_pci_instr_countx_s { ++ uint32_t icnt:32; ++ } s; ++ struct cvmx_pci_instr_countx_s cn30xx; ++ struct cvmx_pci_instr_countx_s cn31xx; ++ struct cvmx_pci_instr_countx_s cn38xx; ++ struct cvmx_pci_instr_countx_s cn38xxp2; ++ struct cvmx_pci_instr_countx_s cn50xx; ++ struct cvmx_pci_instr_countx_s cn58xx; ++ struct cvmx_pci_instr_countx_s cn58xxp1; ++}; ++ ++union cvmx_pci_int_enb { ++ uint64_t u64; ++ struct cvmx_pci_int_enb_s { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t idtime1:1; ++ uint64_t idtime0:1; ++ uint64_t idcnt1:1; ++ uint64_t idcnt0:1; ++ uint64_t iptime3:1; ++ uint64_t iptime2:1; ++ uint64_t iptime1:1; ++ uint64_t iptime0:1; ++ uint64_t ipcnt3:1; ++ uint64_t ipcnt2:1; ++ uint64_t ipcnt1:1; ++ uint64_t ipcnt0:1; ++ uint64_t irsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t idperr:1; ++ uint64_t iaperr:1; ++ uint64_t iserr:1; ++ uint64_t itsr_abt:1; ++ uint64_t imsc_msg:1; ++ uint64_t imsi_mabt:1; ++ uint64_t imsi_tabt:1; ++ uint64_t imsi_per:1; ++ uint64_t imr_tto:1; ++ uint64_t imr_abt:1; ++ uint64_t itr_abt:1; ++ uint64_t imr_wtto:1; ++ uint64_t imr_wabt:1; ++ uint64_t itr_wabt:1; ++ } s; ++ struct cvmx_pci_int_enb_cn30xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t idtime1:1; ++ uint64_t idtime0:1; ++ uint64_t idcnt1:1; ++ uint64_t idcnt0:1; ++ uint64_t reserved_22_24:3; ++ uint64_t iptime0:1; ++ uint64_t reserved_18_20:3; ++ uint64_t ipcnt0:1; ++ uint64_t irsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t idperr:1; ++ uint64_t iaperr:1; ++ uint64_t iserr:1; ++ uint64_t itsr_abt:1; ++ uint64_t imsc_msg:1; ++ uint64_t imsi_mabt:1; ++ uint64_t imsi_tabt:1; ++ uint64_t imsi_per:1; ++ uint64_t imr_tto:1; ++ uint64_t imr_abt:1; ++ uint64_t itr_abt:1; ++ uint64_t imr_wtto:1; ++ uint64_t imr_wabt:1; ++ uint64_t itr_wabt:1; ++ } cn30xx; ++ struct cvmx_pci_int_enb_cn31xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t idtime1:1; ++ uint64_t idtime0:1; ++ uint64_t idcnt1:1; ++ uint64_t idcnt0:1; ++ uint64_t reserved_23_24:2; ++ uint64_t iptime1:1; ++ uint64_t iptime0:1; ++ uint64_t reserved_19_20:2; ++ uint64_t ipcnt1:1; ++ uint64_t ipcnt0:1; ++ uint64_t irsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t idperr:1; ++ uint64_t iaperr:1; ++ uint64_t iserr:1; ++ uint64_t itsr_abt:1; ++ uint64_t imsc_msg:1; ++ uint64_t imsi_mabt:1; ++ uint64_t imsi_tabt:1; ++ uint64_t imsi_per:1; ++ uint64_t imr_tto:1; ++ uint64_t imr_abt:1; ++ uint64_t itr_abt:1; ++ uint64_t imr_wtto:1; ++ uint64_t imr_wabt:1; ++ uint64_t itr_wabt:1; ++ } cn31xx; ++ struct cvmx_pci_int_enb_s cn38xx; ++ struct cvmx_pci_int_enb_s cn38xxp2; ++ struct cvmx_pci_int_enb_cn31xx cn50xx; ++ struct cvmx_pci_int_enb_s cn58xx; ++ struct cvmx_pci_int_enb_s cn58xxp1; ++}; ++ ++union cvmx_pci_int_enb2 { ++ uint64_t u64; ++ struct cvmx_pci_int_enb2_s { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t rdtime1:1; ++ uint64_t rdtime0:1; ++ uint64_t rdcnt1:1; ++ uint64_t rdcnt0:1; ++ uint64_t rptime3:1; ++ uint64_t rptime2:1; ++ uint64_t rptime1:1; ++ uint64_t rptime0:1; ++ uint64_t rpcnt3:1; ++ uint64_t rpcnt2:1; ++ uint64_t rpcnt1:1; ++ uint64_t rpcnt0:1; ++ uint64_t rrsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t rdperr:1; ++ uint64_t raperr:1; ++ uint64_t rserr:1; ++ uint64_t rtsr_abt:1; ++ uint64_t rmsc_msg:1; ++ uint64_t rmsi_mabt:1; ++ uint64_t rmsi_tabt:1; ++ uint64_t rmsi_per:1; ++ uint64_t rmr_tto:1; ++ uint64_t rmr_abt:1; ++ uint64_t rtr_abt:1; ++ uint64_t rmr_wtto:1; ++ uint64_t rmr_wabt:1; ++ uint64_t rtr_wabt:1; ++ } s; ++ struct cvmx_pci_int_enb2_cn30xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t rdtime1:1; ++ uint64_t rdtime0:1; ++ uint64_t rdcnt1:1; ++ uint64_t rdcnt0:1; ++ uint64_t reserved_22_24:3; ++ uint64_t rptime0:1; ++ uint64_t reserved_18_20:3; ++ uint64_t rpcnt0:1; ++ uint64_t rrsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t rdperr:1; ++ uint64_t raperr:1; ++ uint64_t rserr:1; ++ uint64_t rtsr_abt:1; ++ uint64_t rmsc_msg:1; ++ uint64_t rmsi_mabt:1; ++ uint64_t rmsi_tabt:1; ++ uint64_t rmsi_per:1; ++ uint64_t rmr_tto:1; ++ uint64_t rmr_abt:1; ++ uint64_t rtr_abt:1; ++ uint64_t rmr_wtto:1; ++ uint64_t rmr_wabt:1; ++ uint64_t rtr_wabt:1; ++ } cn30xx; ++ struct cvmx_pci_int_enb2_cn31xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t rdtime1:1; ++ uint64_t rdtime0:1; ++ uint64_t rdcnt1:1; ++ uint64_t rdcnt0:1; ++ uint64_t reserved_23_24:2; ++ uint64_t rptime1:1; ++ uint64_t rptime0:1; ++ uint64_t reserved_19_20:2; ++ uint64_t rpcnt1:1; ++ uint64_t rpcnt0:1; ++ uint64_t rrsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t rdperr:1; ++ uint64_t raperr:1; ++ uint64_t rserr:1; ++ uint64_t rtsr_abt:1; ++ uint64_t rmsc_msg:1; ++ uint64_t rmsi_mabt:1; ++ uint64_t rmsi_tabt:1; ++ uint64_t rmsi_per:1; ++ uint64_t rmr_tto:1; ++ uint64_t rmr_abt:1; ++ uint64_t rtr_abt:1; ++ uint64_t rmr_wtto:1; ++ uint64_t rmr_wabt:1; ++ uint64_t rtr_wabt:1; ++ } cn31xx; ++ struct cvmx_pci_int_enb2_s cn38xx; ++ struct cvmx_pci_int_enb2_s cn38xxp2; ++ struct cvmx_pci_int_enb2_cn31xx cn50xx; ++ struct cvmx_pci_int_enb2_s cn58xx; ++ struct cvmx_pci_int_enb2_s cn58xxp1; ++}; ++ ++union cvmx_pci_int_sum { ++ uint64_t u64; ++ struct cvmx_pci_int_sum_s { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t ptime3:1; ++ uint64_t ptime2:1; ++ uint64_t ptime1:1; ++ uint64_t ptime0:1; ++ uint64_t pcnt3:1; ++ uint64_t pcnt2:1; ++ uint64_t pcnt1:1; ++ uint64_t pcnt0:1; ++ uint64_t rsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t dperr:1; ++ uint64_t aperr:1; ++ uint64_t serr:1; ++ uint64_t tsr_abt:1; ++ uint64_t msc_msg:1; ++ uint64_t msi_mabt:1; ++ uint64_t msi_tabt:1; ++ uint64_t msi_per:1; ++ uint64_t mr_tto:1; ++ uint64_t mr_abt:1; ++ uint64_t tr_abt:1; ++ uint64_t mr_wtto:1; ++ uint64_t mr_wabt:1; ++ uint64_t tr_wabt:1; ++ } s; ++ struct cvmx_pci_int_sum_cn30xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t reserved_22_24:3; ++ uint64_t ptime0:1; ++ uint64_t reserved_18_20:3; ++ uint64_t pcnt0:1; ++ uint64_t rsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t dperr:1; ++ uint64_t aperr:1; ++ uint64_t serr:1; ++ uint64_t tsr_abt:1; ++ uint64_t msc_msg:1; ++ uint64_t msi_mabt:1; ++ uint64_t msi_tabt:1; ++ uint64_t msi_per:1; ++ uint64_t mr_tto:1; ++ uint64_t mr_abt:1; ++ uint64_t tr_abt:1; ++ uint64_t mr_wtto:1; ++ uint64_t mr_wabt:1; ++ uint64_t tr_wabt:1; ++ } cn30xx; ++ struct cvmx_pci_int_sum_cn31xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t reserved_23_24:2; ++ uint64_t ptime1:1; ++ uint64_t ptime0:1; ++ uint64_t reserved_19_20:2; ++ uint64_t pcnt1:1; ++ uint64_t pcnt0:1; ++ uint64_t rsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t dperr:1; ++ uint64_t aperr:1; ++ uint64_t serr:1; ++ uint64_t tsr_abt:1; ++ uint64_t msc_msg:1; ++ uint64_t msi_mabt:1; ++ uint64_t msi_tabt:1; ++ uint64_t msi_per:1; ++ uint64_t mr_tto:1; ++ uint64_t mr_abt:1; ++ uint64_t tr_abt:1; ++ uint64_t mr_wtto:1; ++ uint64_t mr_wabt:1; ++ uint64_t tr_wabt:1; ++ } cn31xx; ++ struct cvmx_pci_int_sum_s cn38xx; ++ struct cvmx_pci_int_sum_s cn38xxp2; ++ struct cvmx_pci_int_sum_cn31xx cn50xx; ++ struct cvmx_pci_int_sum_s cn58xx; ++ struct cvmx_pci_int_sum_s cn58xxp1; ++}; ++ ++union cvmx_pci_int_sum2 { ++ uint64_t u64; ++ struct cvmx_pci_int_sum2_s { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t ptime3:1; ++ uint64_t ptime2:1; ++ uint64_t ptime1:1; ++ uint64_t ptime0:1; ++ uint64_t pcnt3:1; ++ uint64_t pcnt2:1; ++ uint64_t pcnt1:1; ++ uint64_t pcnt0:1; ++ uint64_t rsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t dperr:1; ++ uint64_t aperr:1; ++ uint64_t serr:1; ++ uint64_t tsr_abt:1; ++ uint64_t msc_msg:1; ++ uint64_t msi_mabt:1; ++ uint64_t msi_tabt:1; ++ uint64_t msi_per:1; ++ uint64_t mr_tto:1; ++ uint64_t mr_abt:1; ++ uint64_t tr_abt:1; ++ uint64_t mr_wtto:1; ++ uint64_t mr_wabt:1; ++ uint64_t tr_wabt:1; ++ } s; ++ struct cvmx_pci_int_sum2_cn30xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t reserved_22_24:3; ++ uint64_t ptime0:1; ++ uint64_t reserved_18_20:3; ++ uint64_t pcnt0:1; ++ uint64_t rsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t dperr:1; ++ uint64_t aperr:1; ++ uint64_t serr:1; ++ uint64_t tsr_abt:1; ++ uint64_t msc_msg:1; ++ uint64_t msi_mabt:1; ++ uint64_t msi_tabt:1; ++ uint64_t msi_per:1; ++ uint64_t mr_tto:1; ++ uint64_t mr_abt:1; ++ uint64_t tr_abt:1; ++ uint64_t mr_wtto:1; ++ uint64_t mr_wabt:1; ++ uint64_t tr_wabt:1; ++ } cn30xx; ++ struct cvmx_pci_int_sum2_cn31xx { ++ uint64_t reserved_34_63:30; ++ uint64_t ill_rd:1; ++ uint64_t ill_wr:1; ++ uint64_t win_wr:1; ++ uint64_t dma1_fi:1; ++ uint64_t dma0_fi:1; ++ uint64_t dtime1:1; ++ uint64_t dtime0:1; ++ uint64_t dcnt1:1; ++ uint64_t dcnt0:1; ++ uint64_t reserved_23_24:2; ++ uint64_t ptime1:1; ++ uint64_t ptime0:1; ++ uint64_t reserved_19_20:2; ++ uint64_t pcnt1:1; ++ uint64_t pcnt0:1; ++ uint64_t rsl_int:1; ++ uint64_t ill_rrd:1; ++ uint64_t ill_rwr:1; ++ uint64_t dperr:1; ++ uint64_t aperr:1; ++ uint64_t serr:1; ++ uint64_t tsr_abt:1; ++ uint64_t msc_msg:1; ++ uint64_t msi_mabt:1; ++ uint64_t msi_tabt:1; ++ uint64_t msi_per:1; ++ uint64_t mr_tto:1; ++ uint64_t mr_abt:1; ++ uint64_t tr_abt:1; ++ uint64_t mr_wtto:1; ++ uint64_t mr_wabt:1; ++ uint64_t tr_wabt:1; ++ } cn31xx; ++ struct cvmx_pci_int_sum2_s cn38xx; ++ struct cvmx_pci_int_sum2_s cn38xxp2; ++ struct cvmx_pci_int_sum2_cn31xx cn50xx; ++ struct cvmx_pci_int_sum2_s cn58xx; ++ struct cvmx_pci_int_sum2_s cn58xxp1; ++}; ++ ++union cvmx_pci_msi_rcv { ++ uint32_t u32; ++ struct cvmx_pci_msi_rcv_s { ++ uint32_t reserved_6_31:26; ++ uint32_t intr:6; ++ } s; ++ struct cvmx_pci_msi_rcv_s cn30xx; ++ struct cvmx_pci_msi_rcv_s cn31xx; ++ struct cvmx_pci_msi_rcv_s cn38xx; ++ struct cvmx_pci_msi_rcv_s cn38xxp2; ++ struct cvmx_pci_msi_rcv_s cn50xx; ++ struct cvmx_pci_msi_rcv_s cn58xx; ++ struct cvmx_pci_msi_rcv_s cn58xxp1; ++}; ++ ++union cvmx_pci_pkt_creditsx { ++ uint32_t u32; ++ struct cvmx_pci_pkt_creditsx_s { ++ uint32_t pkt_cnt:16; ++ uint32_t ptr_cnt:16; ++ } s; ++ struct cvmx_pci_pkt_creditsx_s cn30xx; ++ struct cvmx_pci_pkt_creditsx_s cn31xx; ++ struct cvmx_pci_pkt_creditsx_s cn38xx; ++ struct cvmx_pci_pkt_creditsx_s cn38xxp2; ++ struct cvmx_pci_pkt_creditsx_s cn50xx; ++ struct cvmx_pci_pkt_creditsx_s cn58xx; ++ struct cvmx_pci_pkt_creditsx_s cn58xxp1; ++}; ++ ++union cvmx_pci_pkts_sentx { ++ uint32_t u32; ++ struct cvmx_pci_pkts_sentx_s { ++ uint32_t pkt_cnt:32; ++ } s; ++ struct cvmx_pci_pkts_sentx_s cn30xx; ++ struct cvmx_pci_pkts_sentx_s cn31xx; ++ struct cvmx_pci_pkts_sentx_s cn38xx; ++ struct cvmx_pci_pkts_sentx_s cn38xxp2; ++ struct cvmx_pci_pkts_sentx_s cn50xx; ++ struct cvmx_pci_pkts_sentx_s cn58xx; ++ struct cvmx_pci_pkts_sentx_s cn58xxp1; ++}; ++ ++union cvmx_pci_pkts_sent_int_levx { ++ uint32_t u32; ++ struct cvmx_pci_pkts_sent_int_levx_s { ++ uint32_t pkt_cnt:32; ++ } s; ++ struct cvmx_pci_pkts_sent_int_levx_s cn30xx; ++ struct cvmx_pci_pkts_sent_int_levx_s cn31xx; ++ struct cvmx_pci_pkts_sent_int_levx_s cn38xx; ++ struct cvmx_pci_pkts_sent_int_levx_s cn38xxp2; ++ struct cvmx_pci_pkts_sent_int_levx_s cn50xx; ++ struct cvmx_pci_pkts_sent_int_levx_s cn58xx; ++ struct cvmx_pci_pkts_sent_int_levx_s cn58xxp1; ++}; ++ ++union cvmx_pci_pkts_sent_timex { ++ uint32_t u32; ++ struct cvmx_pci_pkts_sent_timex_s { ++ uint32_t pkt_time:32; ++ } s; ++ struct cvmx_pci_pkts_sent_timex_s cn30xx; ++ struct cvmx_pci_pkts_sent_timex_s cn31xx; ++ struct cvmx_pci_pkts_sent_timex_s cn38xx; ++ struct cvmx_pci_pkts_sent_timex_s cn38xxp2; ++ struct cvmx_pci_pkts_sent_timex_s cn50xx; ++ struct cvmx_pci_pkts_sent_timex_s cn58xx; ++ struct cvmx_pci_pkts_sent_timex_s cn58xxp1; ++}; ++ ++union cvmx_pci_read_cmd_6 { ++ uint32_t u32; ++ struct cvmx_pci_read_cmd_6_s { ++ uint32_t reserved_9_31:23; ++ uint32_t min_data:6; ++ uint32_t prefetch:3; ++ } s; ++ struct cvmx_pci_read_cmd_6_s cn30xx; ++ struct cvmx_pci_read_cmd_6_s cn31xx; ++ struct cvmx_pci_read_cmd_6_s cn38xx; ++ struct cvmx_pci_read_cmd_6_s cn38xxp2; ++ struct cvmx_pci_read_cmd_6_s cn50xx; ++ struct cvmx_pci_read_cmd_6_s cn58xx; ++ struct cvmx_pci_read_cmd_6_s cn58xxp1; ++}; ++ ++union cvmx_pci_read_cmd_c { ++ uint32_t u32; ++ struct cvmx_pci_read_cmd_c_s { ++ uint32_t reserved_9_31:23; ++ uint32_t min_data:6; ++ uint32_t prefetch:3; ++ } s; ++ struct cvmx_pci_read_cmd_c_s cn30xx; ++ struct cvmx_pci_read_cmd_c_s cn31xx; ++ struct cvmx_pci_read_cmd_c_s cn38xx; ++ struct cvmx_pci_read_cmd_c_s cn38xxp2; ++ struct cvmx_pci_read_cmd_c_s cn50xx; ++ struct cvmx_pci_read_cmd_c_s cn58xx; ++ struct cvmx_pci_read_cmd_c_s cn58xxp1; ++}; ++ ++union cvmx_pci_read_cmd_e { ++ uint32_t u32; ++ struct cvmx_pci_read_cmd_e_s { ++ uint32_t reserved_9_31:23; ++ uint32_t min_data:6; ++ uint32_t prefetch:3; ++ } s; ++ struct cvmx_pci_read_cmd_e_s cn30xx; ++ struct cvmx_pci_read_cmd_e_s cn31xx; ++ struct cvmx_pci_read_cmd_e_s cn38xx; ++ struct cvmx_pci_read_cmd_e_s cn38xxp2; ++ struct cvmx_pci_read_cmd_e_s cn50xx; ++ struct cvmx_pci_read_cmd_e_s cn58xx; ++ struct cvmx_pci_read_cmd_e_s cn58xxp1; ++}; ++ ++union cvmx_pci_read_timeout { ++ uint64_t u64; ++ struct cvmx_pci_read_timeout_s { ++ uint64_t reserved_32_63:32; ++ uint64_t enb:1; ++ uint64_t cnt:31; ++ } s; ++ struct cvmx_pci_read_timeout_s cn30xx; ++ struct cvmx_pci_read_timeout_s cn31xx; ++ struct cvmx_pci_read_timeout_s cn38xx; ++ struct cvmx_pci_read_timeout_s cn38xxp2; ++ struct cvmx_pci_read_timeout_s cn50xx; ++ struct cvmx_pci_read_timeout_s cn58xx; ++ struct cvmx_pci_read_timeout_s cn58xxp1; ++}; ++ ++union cvmx_pci_scm_reg { ++ uint64_t u64; ++ struct cvmx_pci_scm_reg_s { ++ uint64_t reserved_32_63:32; ++ uint64_t scm:32; ++ } s; ++ struct cvmx_pci_scm_reg_s cn30xx; ++ struct cvmx_pci_scm_reg_s cn31xx; ++ struct cvmx_pci_scm_reg_s cn38xx; ++ struct cvmx_pci_scm_reg_s cn38xxp2; ++ struct cvmx_pci_scm_reg_s cn50xx; ++ struct cvmx_pci_scm_reg_s cn58xx; ++ struct cvmx_pci_scm_reg_s cn58xxp1; ++}; ++ ++union cvmx_pci_tsr_reg { ++ uint64_t u64; ++ struct cvmx_pci_tsr_reg_s { ++ uint64_t reserved_36_63:28; ++ uint64_t tsr:36; ++ } s; ++ struct cvmx_pci_tsr_reg_s cn30xx; ++ struct cvmx_pci_tsr_reg_s cn31xx; ++ struct cvmx_pci_tsr_reg_s cn38xx; ++ struct cvmx_pci_tsr_reg_s cn38xxp2; ++ struct cvmx_pci_tsr_reg_s cn50xx; ++ struct cvmx_pci_tsr_reg_s cn58xx; ++ struct cvmx_pci_tsr_reg_s cn58xxp1; ++}; ++ ++union cvmx_pci_win_rd_addr { ++ uint64_t u64; ++ struct cvmx_pci_win_rd_addr_s { ++ uint64_t reserved_49_63:15; ++ uint64_t iobit:1; ++ uint64_t reserved_0_47:48; ++ } s; ++ struct cvmx_pci_win_rd_addr_cn30xx { ++ uint64_t reserved_49_63:15; ++ uint64_t iobit:1; ++ uint64_t rd_addr:46; ++ uint64_t reserved_0_1:2; ++ } cn30xx; ++ struct cvmx_pci_win_rd_addr_cn30xx cn31xx; ++ struct cvmx_pci_win_rd_addr_cn38xx { ++ uint64_t reserved_49_63:15; ++ uint64_t iobit:1; ++ uint64_t rd_addr:45; ++ uint64_t reserved_0_2:3; ++ } cn38xx; ++ struct cvmx_pci_win_rd_addr_cn38xx cn38xxp2; ++ struct cvmx_pci_win_rd_addr_cn30xx cn50xx; ++ struct cvmx_pci_win_rd_addr_cn38xx cn58xx; ++ struct cvmx_pci_win_rd_addr_cn38xx cn58xxp1; ++}; ++ ++union cvmx_pci_win_rd_data { ++ uint64_t u64; ++ struct cvmx_pci_win_rd_data_s { ++ uint64_t rd_data:64; ++ } s; ++ struct cvmx_pci_win_rd_data_s cn30xx; ++ struct cvmx_pci_win_rd_data_s cn31xx; ++ struct cvmx_pci_win_rd_data_s cn38xx; ++ struct cvmx_pci_win_rd_data_s cn38xxp2; ++ struct cvmx_pci_win_rd_data_s cn50xx; ++ struct cvmx_pci_win_rd_data_s cn58xx; ++ struct cvmx_pci_win_rd_data_s cn58xxp1; ++}; ++ ++union cvmx_pci_win_wr_addr { ++ uint64_t u64; ++ struct cvmx_pci_win_wr_addr_s { ++ uint64_t reserved_49_63:15; ++ uint64_t iobit:1; ++ uint64_t wr_addr:45; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_pci_win_wr_addr_s cn30xx; ++ struct cvmx_pci_win_wr_addr_s cn31xx; ++ struct cvmx_pci_win_wr_addr_s cn38xx; ++ struct cvmx_pci_win_wr_addr_s cn38xxp2; ++ struct cvmx_pci_win_wr_addr_s cn50xx; ++ struct cvmx_pci_win_wr_addr_s cn58xx; ++ struct cvmx_pci_win_wr_addr_s cn58xxp1; ++}; ++ ++union cvmx_pci_win_wr_data { ++ uint64_t u64; ++ struct cvmx_pci_win_wr_data_s { ++ uint64_t wr_data:64; ++ } s; ++ struct cvmx_pci_win_wr_data_s cn30xx; ++ struct cvmx_pci_win_wr_data_s cn31xx; ++ struct cvmx_pci_win_wr_data_s cn38xx; ++ struct cvmx_pci_win_wr_data_s cn38xxp2; ++ struct cvmx_pci_win_wr_data_s cn50xx; ++ struct cvmx_pci_win_wr_data_s cn58xx; ++ struct cvmx_pci_win_wr_data_s cn58xxp1; ++}; ++ ++union cvmx_pci_win_wr_mask { ++ uint64_t u64; ++ struct cvmx_pci_win_wr_mask_s { ++ uint64_t reserved_8_63:56; ++ uint64_t wr_mask:8; ++ } s; ++ struct cvmx_pci_win_wr_mask_s cn30xx; ++ struct cvmx_pci_win_wr_mask_s cn31xx; ++ struct cvmx_pci_win_wr_mask_s cn38xx; ++ struct cvmx_pci_win_wr_mask_s cn38xxp2; ++ struct cvmx_pci_win_wr_mask_s cn50xx; ++ struct cvmx_pci_win_wr_mask_s cn58xx; ++ struct cvmx_pci_win_wr_mask_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h +@@ -0,0 +1,1365 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PCIEEP_DEFS_H__ ++#define __CVMX_PCIEEP_DEFS_H__ ++ ++#define CVMX_PCIEEP_CFG000 \ ++ (0x0000000000000000ull) ++#define CVMX_PCIEEP_CFG001 \ ++ (0x0000000000000004ull) ++#define CVMX_PCIEEP_CFG002 \ ++ (0x0000000000000008ull) ++#define CVMX_PCIEEP_CFG003 \ ++ (0x000000000000000Cull) ++#define CVMX_PCIEEP_CFG004 \ ++ (0x0000000000000010ull) ++#define CVMX_PCIEEP_CFG004_MASK \ ++ (0x0000000080000010ull) ++#define CVMX_PCIEEP_CFG005 \ ++ (0x0000000000000014ull) ++#define CVMX_PCIEEP_CFG005_MASK \ ++ (0x0000000080000014ull) ++#define CVMX_PCIEEP_CFG006 \ ++ (0x0000000000000018ull) ++#define CVMX_PCIEEP_CFG006_MASK \ ++ (0x0000000080000018ull) ++#define CVMX_PCIEEP_CFG007 \ ++ (0x000000000000001Cull) ++#define CVMX_PCIEEP_CFG007_MASK \ ++ (0x000000008000001Cull) ++#define CVMX_PCIEEP_CFG008 \ ++ (0x0000000000000020ull) ++#define CVMX_PCIEEP_CFG008_MASK \ ++ (0x0000000080000020ull) ++#define CVMX_PCIEEP_CFG009 \ ++ (0x0000000000000024ull) ++#define CVMX_PCIEEP_CFG009_MASK \ ++ (0x0000000080000024ull) ++#define CVMX_PCIEEP_CFG010 \ ++ (0x0000000000000028ull) ++#define CVMX_PCIEEP_CFG011 \ ++ (0x000000000000002Cull) ++#define CVMX_PCIEEP_CFG012 \ ++ (0x0000000000000030ull) ++#define CVMX_PCIEEP_CFG012_MASK \ ++ (0x0000000080000030ull) ++#define CVMX_PCIEEP_CFG013 \ ++ (0x0000000000000034ull) ++#define CVMX_PCIEEP_CFG015 \ ++ (0x000000000000003Cull) ++#define CVMX_PCIEEP_CFG016 \ ++ (0x0000000000000040ull) ++#define CVMX_PCIEEP_CFG017 \ ++ (0x0000000000000044ull) ++#define CVMX_PCIEEP_CFG020 \ ++ (0x0000000000000050ull) ++#define CVMX_PCIEEP_CFG021 \ ++ (0x0000000000000054ull) ++#define CVMX_PCIEEP_CFG022 \ ++ (0x0000000000000058ull) ++#define CVMX_PCIEEP_CFG023 \ ++ (0x000000000000005Cull) ++#define CVMX_PCIEEP_CFG028 \ ++ (0x0000000000000070ull) ++#define CVMX_PCIEEP_CFG029 \ ++ (0x0000000000000074ull) ++#define CVMX_PCIEEP_CFG030 \ ++ (0x0000000000000078ull) ++#define CVMX_PCIEEP_CFG031 \ ++ (0x000000000000007Cull) ++#define CVMX_PCIEEP_CFG032 \ ++ (0x0000000000000080ull) ++#define CVMX_PCIEEP_CFG033 \ ++ (0x0000000000000084ull) ++#define CVMX_PCIEEP_CFG034 \ ++ (0x0000000000000088ull) ++#define CVMX_PCIEEP_CFG037 \ ++ (0x0000000000000094ull) ++#define CVMX_PCIEEP_CFG038 \ ++ (0x0000000000000098ull) ++#define CVMX_PCIEEP_CFG039 \ ++ (0x000000000000009Cull) ++#define CVMX_PCIEEP_CFG040 \ ++ (0x00000000000000A0ull) ++#define CVMX_PCIEEP_CFG041 \ ++ (0x00000000000000A4ull) ++#define CVMX_PCIEEP_CFG042 \ ++ (0x00000000000000A8ull) ++#define CVMX_PCIEEP_CFG064 \ ++ (0x0000000000000100ull) ++#define CVMX_PCIEEP_CFG065 \ ++ (0x0000000000000104ull) ++#define CVMX_PCIEEP_CFG066 \ ++ (0x0000000000000108ull) ++#define CVMX_PCIEEP_CFG067 \ ++ (0x000000000000010Cull) ++#define CVMX_PCIEEP_CFG068 \ ++ (0x0000000000000110ull) ++#define CVMX_PCIEEP_CFG069 \ ++ (0x0000000000000114ull) ++#define CVMX_PCIEEP_CFG070 \ ++ (0x0000000000000118ull) ++#define CVMX_PCIEEP_CFG071 \ ++ (0x000000000000011Cull) ++#define CVMX_PCIEEP_CFG072 \ ++ (0x0000000000000120ull) ++#define CVMX_PCIEEP_CFG073 \ ++ (0x0000000000000124ull) ++#define CVMX_PCIEEP_CFG074 \ ++ (0x0000000000000128ull) ++#define CVMX_PCIEEP_CFG448 \ ++ (0x0000000000000700ull) ++#define CVMX_PCIEEP_CFG449 \ ++ (0x0000000000000704ull) ++#define CVMX_PCIEEP_CFG450 \ ++ (0x0000000000000708ull) ++#define CVMX_PCIEEP_CFG451 \ ++ (0x000000000000070Cull) ++#define CVMX_PCIEEP_CFG452 \ ++ (0x0000000000000710ull) ++#define CVMX_PCIEEP_CFG453 \ ++ (0x0000000000000714ull) ++#define CVMX_PCIEEP_CFG454 \ ++ (0x0000000000000718ull) ++#define CVMX_PCIEEP_CFG455 \ ++ (0x000000000000071Cull) ++#define CVMX_PCIEEP_CFG456 \ ++ (0x0000000000000720ull) ++#define CVMX_PCIEEP_CFG458 \ ++ (0x0000000000000728ull) ++#define CVMX_PCIEEP_CFG459 \ ++ (0x000000000000072Cull) ++#define CVMX_PCIEEP_CFG460 \ ++ (0x0000000000000730ull) ++#define CVMX_PCIEEP_CFG461 \ ++ (0x0000000000000734ull) ++#define CVMX_PCIEEP_CFG462 \ ++ (0x0000000000000738ull) ++#define CVMX_PCIEEP_CFG463 \ ++ (0x000000000000073Cull) ++#define CVMX_PCIEEP_CFG464 \ ++ (0x0000000000000740ull) ++#define CVMX_PCIEEP_CFG465 \ ++ (0x0000000000000744ull) ++#define CVMX_PCIEEP_CFG466 \ ++ (0x0000000000000748ull) ++#define CVMX_PCIEEP_CFG467 \ ++ (0x000000000000074Cull) ++#define CVMX_PCIEEP_CFG468 \ ++ (0x0000000000000750ull) ++#define CVMX_PCIEEP_CFG490 \ ++ (0x00000000000007A8ull) ++#define CVMX_PCIEEP_CFG491 \ ++ (0x00000000000007ACull) ++#define CVMX_PCIEEP_CFG492 \ ++ (0x00000000000007B0ull) ++#define CVMX_PCIEEP_CFG516 \ ++ (0x0000000000000810ull) ++#define CVMX_PCIEEP_CFG517 \ ++ (0x0000000000000814ull) ++ ++union cvmx_pcieep_cfg000 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg000_s { ++ uint32_t devid:16; ++ uint32_t vendid:16; ++ } s; ++ struct cvmx_pcieep_cfg000_s cn52xx; ++ struct cvmx_pcieep_cfg000_s cn52xxp1; ++ struct cvmx_pcieep_cfg000_s cn56xx; ++ struct cvmx_pcieep_cfg000_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg001 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg001_s { ++ uint32_t dpe:1; ++ uint32_t sse:1; ++ uint32_t rma:1; ++ uint32_t rta:1; ++ uint32_t sta:1; ++ uint32_t devt:2; ++ uint32_t mdpe:1; ++ uint32_t fbb:1; ++ uint32_t reserved_22_22:1; ++ uint32_t m66:1; ++ uint32_t cl:1; ++ uint32_t i_stat:1; ++ uint32_t reserved_11_18:8; ++ uint32_t i_dis:1; ++ uint32_t fbbe:1; ++ uint32_t see:1; ++ uint32_t ids_wcc:1; ++ uint32_t per:1; ++ uint32_t vps:1; ++ uint32_t mwice:1; ++ uint32_t scse:1; ++ uint32_t me:1; ++ uint32_t msae:1; ++ uint32_t isae:1; ++ } s; ++ struct cvmx_pcieep_cfg001_s cn52xx; ++ struct cvmx_pcieep_cfg001_s cn52xxp1; ++ struct cvmx_pcieep_cfg001_s cn56xx; ++ struct cvmx_pcieep_cfg001_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg002 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg002_s { ++ uint32_t bcc:8; ++ uint32_t sc:8; ++ uint32_t pi:8; ++ uint32_t rid:8; ++ } s; ++ struct cvmx_pcieep_cfg002_s cn52xx; ++ struct cvmx_pcieep_cfg002_s cn52xxp1; ++ struct cvmx_pcieep_cfg002_s cn56xx; ++ struct cvmx_pcieep_cfg002_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg003 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg003_s { ++ uint32_t bist:8; ++ uint32_t mfd:1; ++ uint32_t chf:7; ++ uint32_t lt:8; ++ uint32_t cls:8; ++ } s; ++ struct cvmx_pcieep_cfg003_s cn52xx; ++ struct cvmx_pcieep_cfg003_s cn52xxp1; ++ struct cvmx_pcieep_cfg003_s cn56xx; ++ struct cvmx_pcieep_cfg003_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg004 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg004_s { ++ uint32_t lbab:18; ++ uint32_t reserved_4_13:10; ++ uint32_t pf:1; ++ uint32_t typ:2; ++ uint32_t mspc:1; ++ } s; ++ struct cvmx_pcieep_cfg004_s cn52xx; ++ struct cvmx_pcieep_cfg004_s cn52xxp1; ++ struct cvmx_pcieep_cfg004_s cn56xx; ++ struct cvmx_pcieep_cfg004_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg004_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg004_mask_s { ++ uint32_t lmask:31; ++ uint32_t enb:1; ++ } s; ++ struct cvmx_pcieep_cfg004_mask_s cn52xx; ++ struct cvmx_pcieep_cfg004_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg004_mask_s cn56xx; ++ struct cvmx_pcieep_cfg004_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg005 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg005_s { ++ uint32_t ubab:32; ++ } s; ++ struct cvmx_pcieep_cfg005_s cn52xx; ++ struct cvmx_pcieep_cfg005_s cn52xxp1; ++ struct cvmx_pcieep_cfg005_s cn56xx; ++ struct cvmx_pcieep_cfg005_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg005_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg005_mask_s { ++ uint32_t umask:32; ++ } s; ++ struct cvmx_pcieep_cfg005_mask_s cn52xx; ++ struct cvmx_pcieep_cfg005_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg005_mask_s cn56xx; ++ struct cvmx_pcieep_cfg005_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg006 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg006_s { ++ uint32_t lbab:6; ++ uint32_t reserved_4_25:22; ++ uint32_t pf:1; ++ uint32_t typ:2; ++ uint32_t mspc:1; ++ } s; ++ struct cvmx_pcieep_cfg006_s cn52xx; ++ struct cvmx_pcieep_cfg006_s cn52xxp1; ++ struct cvmx_pcieep_cfg006_s cn56xx; ++ struct cvmx_pcieep_cfg006_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg006_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg006_mask_s { ++ uint32_t lmask:31; ++ uint32_t enb:1; ++ } s; ++ struct cvmx_pcieep_cfg006_mask_s cn52xx; ++ struct cvmx_pcieep_cfg006_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg006_mask_s cn56xx; ++ struct cvmx_pcieep_cfg006_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg007 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg007_s { ++ uint32_t ubab:32; ++ } s; ++ struct cvmx_pcieep_cfg007_s cn52xx; ++ struct cvmx_pcieep_cfg007_s cn52xxp1; ++ struct cvmx_pcieep_cfg007_s cn56xx; ++ struct cvmx_pcieep_cfg007_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg007_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg007_mask_s { ++ uint32_t umask:32; ++ } s; ++ struct cvmx_pcieep_cfg007_mask_s cn52xx; ++ struct cvmx_pcieep_cfg007_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg007_mask_s cn56xx; ++ struct cvmx_pcieep_cfg007_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg008 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg008_s { ++ uint32_t reserved_4_31:28; ++ uint32_t pf:1; ++ uint32_t typ:2; ++ uint32_t mspc:1; ++ } s; ++ struct cvmx_pcieep_cfg008_s cn52xx; ++ struct cvmx_pcieep_cfg008_s cn52xxp1; ++ struct cvmx_pcieep_cfg008_s cn56xx; ++ struct cvmx_pcieep_cfg008_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg008_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg008_mask_s { ++ uint32_t lmask:31; ++ uint32_t enb:1; ++ } s; ++ struct cvmx_pcieep_cfg008_mask_s cn52xx; ++ struct cvmx_pcieep_cfg008_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg008_mask_s cn56xx; ++ struct cvmx_pcieep_cfg008_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg009 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg009_s { ++ uint32_t ubab:25; ++ uint32_t reserved_0_6:7; ++ } s; ++ struct cvmx_pcieep_cfg009_s cn52xx; ++ struct cvmx_pcieep_cfg009_s cn52xxp1; ++ struct cvmx_pcieep_cfg009_s cn56xx; ++ struct cvmx_pcieep_cfg009_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg009_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg009_mask_s { ++ uint32_t umask:32; ++ } s; ++ struct cvmx_pcieep_cfg009_mask_s cn52xx; ++ struct cvmx_pcieep_cfg009_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg009_mask_s cn56xx; ++ struct cvmx_pcieep_cfg009_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg010 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg010_s { ++ uint32_t cisp:32; ++ } s; ++ struct cvmx_pcieep_cfg010_s cn52xx; ++ struct cvmx_pcieep_cfg010_s cn52xxp1; ++ struct cvmx_pcieep_cfg010_s cn56xx; ++ struct cvmx_pcieep_cfg010_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg011 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg011_s { ++ uint32_t ssid:16; ++ uint32_t ssvid:16; ++ } s; ++ struct cvmx_pcieep_cfg011_s cn52xx; ++ struct cvmx_pcieep_cfg011_s cn52xxp1; ++ struct cvmx_pcieep_cfg011_s cn56xx; ++ struct cvmx_pcieep_cfg011_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg012 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg012_s { ++ uint32_t eraddr:16; ++ uint32_t reserved_1_15:15; ++ uint32_t er_en:1; ++ } s; ++ struct cvmx_pcieep_cfg012_s cn52xx; ++ struct cvmx_pcieep_cfg012_s cn52xxp1; ++ struct cvmx_pcieep_cfg012_s cn56xx; ++ struct cvmx_pcieep_cfg012_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg012_mask { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg012_mask_s { ++ uint32_t mask:31; ++ uint32_t enb:1; ++ } s; ++ struct cvmx_pcieep_cfg012_mask_s cn52xx; ++ struct cvmx_pcieep_cfg012_mask_s cn52xxp1; ++ struct cvmx_pcieep_cfg012_mask_s cn56xx; ++ struct cvmx_pcieep_cfg012_mask_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg013 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg013_s { ++ uint32_t reserved_8_31:24; ++ uint32_t cp:8; ++ } s; ++ struct cvmx_pcieep_cfg013_s cn52xx; ++ struct cvmx_pcieep_cfg013_s cn52xxp1; ++ struct cvmx_pcieep_cfg013_s cn56xx; ++ struct cvmx_pcieep_cfg013_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg015 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg015_s { ++ uint32_t ml:8; ++ uint32_t mg:8; ++ uint32_t inta:8; ++ uint32_t il:8; ++ } s; ++ struct cvmx_pcieep_cfg015_s cn52xx; ++ struct cvmx_pcieep_cfg015_s cn52xxp1; ++ struct cvmx_pcieep_cfg015_s cn56xx; ++ struct cvmx_pcieep_cfg015_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg016 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg016_s { ++ uint32_t pmes:5; ++ uint32_t d2s:1; ++ uint32_t d1s:1; ++ uint32_t auxc:3; ++ uint32_t dsi:1; ++ uint32_t reserved_20_20:1; ++ uint32_t pme_clock:1; ++ uint32_t pmsv:3; ++ uint32_t ncp:8; ++ uint32_t pmcid:8; ++ } s; ++ struct cvmx_pcieep_cfg016_s cn52xx; ++ struct cvmx_pcieep_cfg016_s cn52xxp1; ++ struct cvmx_pcieep_cfg016_s cn56xx; ++ struct cvmx_pcieep_cfg016_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg017 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg017_s { ++ uint32_t pmdia:8; ++ uint32_t bpccee:1; ++ uint32_t bd3h:1; ++ uint32_t reserved_16_21:6; ++ uint32_t pmess:1; ++ uint32_t pmedsia:2; ++ uint32_t pmds:4; ++ uint32_t pmeens:1; ++ uint32_t reserved_4_7:4; ++ uint32_t nsr:1; ++ uint32_t reserved_2_2:1; ++ uint32_t ps:2; ++ } s; ++ struct cvmx_pcieep_cfg017_s cn52xx; ++ struct cvmx_pcieep_cfg017_s cn52xxp1; ++ struct cvmx_pcieep_cfg017_s cn56xx; ++ struct cvmx_pcieep_cfg017_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg020 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg020_s { ++ uint32_t reserved_24_31:8; ++ uint32_t m64:1; ++ uint32_t mme:3; ++ uint32_t mmc:3; ++ uint32_t msien:1; ++ uint32_t ncp:8; ++ uint32_t msicid:8; ++ } s; ++ struct cvmx_pcieep_cfg020_s cn52xx; ++ struct cvmx_pcieep_cfg020_s cn52xxp1; ++ struct cvmx_pcieep_cfg020_s cn56xx; ++ struct cvmx_pcieep_cfg020_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg021 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg021_s { ++ uint32_t lmsi:30; ++ uint32_t reserved_0_1:2; ++ } s; ++ struct cvmx_pcieep_cfg021_s cn52xx; ++ struct cvmx_pcieep_cfg021_s cn52xxp1; ++ struct cvmx_pcieep_cfg021_s cn56xx; ++ struct cvmx_pcieep_cfg021_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg022 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg022_s { ++ uint32_t umsi:32; ++ } s; ++ struct cvmx_pcieep_cfg022_s cn52xx; ++ struct cvmx_pcieep_cfg022_s cn52xxp1; ++ struct cvmx_pcieep_cfg022_s cn56xx; ++ struct cvmx_pcieep_cfg022_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg023 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg023_s { ++ uint32_t reserved_16_31:16; ++ uint32_t msimd:16; ++ } s; ++ struct cvmx_pcieep_cfg023_s cn52xx; ++ struct cvmx_pcieep_cfg023_s cn52xxp1; ++ struct cvmx_pcieep_cfg023_s cn56xx; ++ struct cvmx_pcieep_cfg023_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg028 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg028_s { ++ uint32_t reserved_30_31:2; ++ uint32_t imn:5; ++ uint32_t si:1; ++ uint32_t dpt:4; ++ uint32_t pciecv:4; ++ uint32_t ncp:8; ++ uint32_t pcieid:8; ++ } s; ++ struct cvmx_pcieep_cfg028_s cn52xx; ++ struct cvmx_pcieep_cfg028_s cn52xxp1; ++ struct cvmx_pcieep_cfg028_s cn56xx; ++ struct cvmx_pcieep_cfg028_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg029 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg029_s { ++ uint32_t reserved_28_31:4; ++ uint32_t cspls:2; ++ uint32_t csplv:8; ++ uint32_t reserved_16_17:2; ++ uint32_t rber:1; ++ uint32_t reserved_12_14:3; ++ uint32_t el1al:3; ++ uint32_t el0al:3; ++ uint32_t etfs:1; ++ uint32_t pfs:2; ++ uint32_t mpss:3; ++ } s; ++ struct cvmx_pcieep_cfg029_s cn52xx; ++ struct cvmx_pcieep_cfg029_s cn52xxp1; ++ struct cvmx_pcieep_cfg029_s cn56xx; ++ struct cvmx_pcieep_cfg029_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg030 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg030_s { ++ uint32_t reserved_22_31:10; ++ uint32_t tp:1; ++ uint32_t ap_d:1; ++ uint32_t ur_d:1; ++ uint32_t fe_d:1; ++ uint32_t nfe_d:1; ++ uint32_t ce_d:1; ++ uint32_t reserved_15_15:1; ++ uint32_t mrrs:3; ++ uint32_t ns_en:1; ++ uint32_t ap_en:1; ++ uint32_t pf_en:1; ++ uint32_t etf_en:1; ++ uint32_t mps:3; ++ uint32_t ro_en:1; ++ uint32_t ur_en:1; ++ uint32_t fe_en:1; ++ uint32_t nfe_en:1; ++ uint32_t ce_en:1; ++ } s; ++ struct cvmx_pcieep_cfg030_s cn52xx; ++ struct cvmx_pcieep_cfg030_s cn52xxp1; ++ struct cvmx_pcieep_cfg030_s cn56xx; ++ struct cvmx_pcieep_cfg030_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg031 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg031_s { ++ uint32_t pnum:8; ++ uint32_t reserved_22_23:2; ++ uint32_t lbnc:1; ++ uint32_t dllarc:1; ++ uint32_t sderc:1; ++ uint32_t cpm:1; ++ uint32_t l1el:3; ++ uint32_t l0el:3; ++ uint32_t aslpms:2; ++ uint32_t mlw:6; ++ uint32_t mls:4; ++ } s; ++ struct cvmx_pcieep_cfg031_s cn52xx; ++ struct cvmx_pcieep_cfg031_s cn52xxp1; ++ struct cvmx_pcieep_cfg031_s cn56xx; ++ struct cvmx_pcieep_cfg031_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg032 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg032_s { ++ uint32_t reserved_30_31:2; ++ uint32_t dlla:1; ++ uint32_t scc:1; ++ uint32_t lt:1; ++ uint32_t reserved_26_26:1; ++ uint32_t nlw:6; ++ uint32_t ls:4; ++ uint32_t reserved_10_15:6; ++ uint32_t hawd:1; ++ uint32_t ecpm:1; ++ uint32_t es:1; ++ uint32_t ccc:1; ++ uint32_t rl:1; ++ uint32_t ld:1; ++ uint32_t rcb:1; ++ uint32_t reserved_2_2:1; ++ uint32_t aslpc:2; ++ } s; ++ struct cvmx_pcieep_cfg032_s cn52xx; ++ struct cvmx_pcieep_cfg032_s cn52xxp1; ++ struct cvmx_pcieep_cfg032_s cn56xx; ++ struct cvmx_pcieep_cfg032_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg033 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg033_s { ++ uint32_t ps_num:13; ++ uint32_t nccs:1; ++ uint32_t emip:1; ++ uint32_t sp_ls:2; ++ uint32_t sp_lv:8; ++ uint32_t hp_c:1; ++ uint32_t hp_s:1; ++ uint32_t pip:1; ++ uint32_t aip:1; ++ uint32_t mrlsp:1; ++ uint32_t pcp:1; ++ uint32_t abp:1; ++ } s; ++ struct cvmx_pcieep_cfg033_s cn52xx; ++ struct cvmx_pcieep_cfg033_s cn52xxp1; ++ struct cvmx_pcieep_cfg033_s cn56xx; ++ struct cvmx_pcieep_cfg033_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg034 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg034_s { ++ uint32_t reserved_25_31:7; ++ uint32_t dlls_c:1; ++ uint32_t emis:1; ++ uint32_t pds:1; ++ uint32_t mrlss:1; ++ uint32_t ccint_d:1; ++ uint32_t pd_c:1; ++ uint32_t mrls_c:1; ++ uint32_t pf_d:1; ++ uint32_t abp_d:1; ++ uint32_t reserved_13_15:3; ++ uint32_t dlls_en:1; ++ uint32_t emic:1; ++ uint32_t pcc:1; ++ uint32_t pic:2; ++ uint32_t aic:2; ++ uint32_t hpint_en:1; ++ uint32_t ccint_en:1; ++ uint32_t pd_en:1; ++ uint32_t mrls_en:1; ++ uint32_t pf_en:1; ++ uint32_t abp_en:1; ++ } s; ++ struct cvmx_pcieep_cfg034_s cn52xx; ++ struct cvmx_pcieep_cfg034_s cn52xxp1; ++ struct cvmx_pcieep_cfg034_s cn56xx; ++ struct cvmx_pcieep_cfg034_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg037 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg037_s { ++ uint32_t reserved_5_31:27; ++ uint32_t ctds:1; ++ uint32_t ctrs:4; ++ } s; ++ struct cvmx_pcieep_cfg037_s cn52xx; ++ struct cvmx_pcieep_cfg037_s cn52xxp1; ++ struct cvmx_pcieep_cfg037_s cn56xx; ++ struct cvmx_pcieep_cfg037_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg038 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg038_s { ++ uint32_t reserved_5_31:27; ++ uint32_t ctd:1; ++ uint32_t ctv:4; ++ } s; ++ struct cvmx_pcieep_cfg038_s cn52xx; ++ struct cvmx_pcieep_cfg038_s cn52xxp1; ++ struct cvmx_pcieep_cfg038_s cn56xx; ++ struct cvmx_pcieep_cfg038_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg039 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg039_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pcieep_cfg039_s cn52xx; ++ struct cvmx_pcieep_cfg039_s cn52xxp1; ++ struct cvmx_pcieep_cfg039_s cn56xx; ++ struct cvmx_pcieep_cfg039_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg040 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg040_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pcieep_cfg040_s cn52xx; ++ struct cvmx_pcieep_cfg040_s cn52xxp1; ++ struct cvmx_pcieep_cfg040_s cn56xx; ++ struct cvmx_pcieep_cfg040_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg041 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg041_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pcieep_cfg041_s cn52xx; ++ struct cvmx_pcieep_cfg041_s cn52xxp1; ++ struct cvmx_pcieep_cfg041_s cn56xx; ++ struct cvmx_pcieep_cfg041_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg042 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg042_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pcieep_cfg042_s cn52xx; ++ struct cvmx_pcieep_cfg042_s cn52xxp1; ++ struct cvmx_pcieep_cfg042_s cn56xx; ++ struct cvmx_pcieep_cfg042_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg064 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg064_s { ++ uint32_t nco:12; ++ uint32_t cv:4; ++ uint32_t pcieec:16; ++ } s; ++ struct cvmx_pcieep_cfg064_s cn52xx; ++ struct cvmx_pcieep_cfg064_s cn52xxp1; ++ struct cvmx_pcieep_cfg064_s cn56xx; ++ struct cvmx_pcieep_cfg064_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg065 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg065_s { ++ uint32_t reserved_21_31:11; ++ uint32_t ures:1; ++ uint32_t ecrces:1; ++ uint32_t mtlps:1; ++ uint32_t ros:1; ++ uint32_t ucs:1; ++ uint32_t cas:1; ++ uint32_t cts:1; ++ uint32_t fcpes:1; ++ uint32_t ptlps:1; ++ uint32_t reserved_6_11:6; ++ uint32_t sdes:1; ++ uint32_t dlpes:1; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pcieep_cfg065_s cn52xx; ++ struct cvmx_pcieep_cfg065_s cn52xxp1; ++ struct cvmx_pcieep_cfg065_s cn56xx; ++ struct cvmx_pcieep_cfg065_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg066 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg066_s { ++ uint32_t reserved_21_31:11; ++ uint32_t urem:1; ++ uint32_t ecrcem:1; ++ uint32_t mtlpm:1; ++ uint32_t rom:1; ++ uint32_t ucm:1; ++ uint32_t cam:1; ++ uint32_t ctm:1; ++ uint32_t fcpem:1; ++ uint32_t ptlpm:1; ++ uint32_t reserved_6_11:6; ++ uint32_t sdem:1; ++ uint32_t dlpem:1; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pcieep_cfg066_s cn52xx; ++ struct cvmx_pcieep_cfg066_s cn52xxp1; ++ struct cvmx_pcieep_cfg066_s cn56xx; ++ struct cvmx_pcieep_cfg066_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg067 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg067_s { ++ uint32_t reserved_21_31:11; ++ uint32_t ures:1; ++ uint32_t ecrces:1; ++ uint32_t mtlps:1; ++ uint32_t ros:1; ++ uint32_t ucs:1; ++ uint32_t cas:1; ++ uint32_t cts:1; ++ uint32_t fcpes:1; ++ uint32_t ptlps:1; ++ uint32_t reserved_6_11:6; ++ uint32_t sdes:1; ++ uint32_t dlpes:1; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pcieep_cfg067_s cn52xx; ++ struct cvmx_pcieep_cfg067_s cn52xxp1; ++ struct cvmx_pcieep_cfg067_s cn56xx; ++ struct cvmx_pcieep_cfg067_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg068 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg068_s { ++ uint32_t reserved_14_31:18; ++ uint32_t anfes:1; ++ uint32_t rtts:1; ++ uint32_t reserved_9_11:3; ++ uint32_t rnrs:1; ++ uint32_t bdllps:1; ++ uint32_t btlps:1; ++ uint32_t reserved_1_5:5; ++ uint32_t res:1; ++ } s; ++ struct cvmx_pcieep_cfg068_s cn52xx; ++ struct cvmx_pcieep_cfg068_s cn52xxp1; ++ struct cvmx_pcieep_cfg068_s cn56xx; ++ struct cvmx_pcieep_cfg068_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg069 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg069_s { ++ uint32_t reserved_14_31:18; ++ uint32_t anfem:1; ++ uint32_t rttm:1; ++ uint32_t reserved_9_11:3; ++ uint32_t rnrm:1; ++ uint32_t bdllpm:1; ++ uint32_t btlpm:1; ++ uint32_t reserved_1_5:5; ++ uint32_t rem:1; ++ } s; ++ struct cvmx_pcieep_cfg069_s cn52xx; ++ struct cvmx_pcieep_cfg069_s cn52xxp1; ++ struct cvmx_pcieep_cfg069_s cn56xx; ++ struct cvmx_pcieep_cfg069_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg070 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg070_s { ++ uint32_t reserved_9_31:23; ++ uint32_t ce:1; ++ uint32_t cc:1; ++ uint32_t ge:1; ++ uint32_t gc:1; ++ uint32_t fep:5; ++ } s; ++ struct cvmx_pcieep_cfg070_s cn52xx; ++ struct cvmx_pcieep_cfg070_s cn52xxp1; ++ struct cvmx_pcieep_cfg070_s cn56xx; ++ struct cvmx_pcieep_cfg070_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg071 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg071_s { ++ uint32_t dword1:32; ++ } s; ++ struct cvmx_pcieep_cfg071_s cn52xx; ++ struct cvmx_pcieep_cfg071_s cn52xxp1; ++ struct cvmx_pcieep_cfg071_s cn56xx; ++ struct cvmx_pcieep_cfg071_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg072 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg072_s { ++ uint32_t dword2:32; ++ } s; ++ struct cvmx_pcieep_cfg072_s cn52xx; ++ struct cvmx_pcieep_cfg072_s cn52xxp1; ++ struct cvmx_pcieep_cfg072_s cn56xx; ++ struct cvmx_pcieep_cfg072_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg073 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg073_s { ++ uint32_t dword3:32; ++ } s; ++ struct cvmx_pcieep_cfg073_s cn52xx; ++ struct cvmx_pcieep_cfg073_s cn52xxp1; ++ struct cvmx_pcieep_cfg073_s cn56xx; ++ struct cvmx_pcieep_cfg073_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg074 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg074_s { ++ uint32_t dword4:32; ++ } s; ++ struct cvmx_pcieep_cfg074_s cn52xx; ++ struct cvmx_pcieep_cfg074_s cn52xxp1; ++ struct cvmx_pcieep_cfg074_s cn56xx; ++ struct cvmx_pcieep_cfg074_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg448 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg448_s { ++ uint32_t rtl:16; ++ uint32_t rtltl:16; ++ } s; ++ struct cvmx_pcieep_cfg448_s cn52xx; ++ struct cvmx_pcieep_cfg448_s cn52xxp1; ++ struct cvmx_pcieep_cfg448_s cn56xx; ++ struct cvmx_pcieep_cfg448_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg449 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg449_s { ++ uint32_t omr:32; ++ } s; ++ struct cvmx_pcieep_cfg449_s cn52xx; ++ struct cvmx_pcieep_cfg449_s cn52xxp1; ++ struct cvmx_pcieep_cfg449_s cn56xx; ++ struct cvmx_pcieep_cfg449_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg450 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg450_s { ++ uint32_t lpec:8; ++ uint32_t reserved_22_23:2; ++ uint32_t link_state:6; ++ uint32_t force_link:1; ++ uint32_t reserved_8_14:7; ++ uint32_t link_num:8; ++ } s; ++ struct cvmx_pcieep_cfg450_s cn52xx; ++ struct cvmx_pcieep_cfg450_s cn52xxp1; ++ struct cvmx_pcieep_cfg450_s cn56xx; ++ struct cvmx_pcieep_cfg450_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg451 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg451_s { ++ uint32_t reserved_30_31:2; ++ uint32_t l1el:3; ++ uint32_t l0el:3; ++ uint32_t n_fts_cc:8; ++ uint32_t n_fts:8; ++ uint32_t ack_freq:8; ++ } s; ++ struct cvmx_pcieep_cfg451_s cn52xx; ++ struct cvmx_pcieep_cfg451_s cn52xxp1; ++ struct cvmx_pcieep_cfg451_s cn56xx; ++ struct cvmx_pcieep_cfg451_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg452 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg452_s { ++ uint32_t reserved_26_31:6; ++ uint32_t eccrc:1; ++ uint32_t reserved_22_24:3; ++ uint32_t lme:6; ++ uint32_t reserved_8_15:8; ++ uint32_t flm:1; ++ uint32_t reserved_6_6:1; ++ uint32_t dllle:1; ++ uint32_t reserved_4_4:1; ++ uint32_t ra:1; ++ uint32_t le:1; ++ uint32_t sd:1; ++ uint32_t omr:1; ++ } s; ++ struct cvmx_pcieep_cfg452_s cn52xx; ++ struct cvmx_pcieep_cfg452_s cn52xxp1; ++ struct cvmx_pcieep_cfg452_s cn56xx; ++ struct cvmx_pcieep_cfg452_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg453 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg453_s { ++ uint32_t dlld:1; ++ uint32_t reserved_26_30:5; ++ uint32_t ack_nak:1; ++ uint32_t fcd:1; ++ uint32_t ilst:24; ++ } s; ++ struct cvmx_pcieep_cfg453_s cn52xx; ++ struct cvmx_pcieep_cfg453_s cn52xxp1; ++ struct cvmx_pcieep_cfg453_s cn56xx; ++ struct cvmx_pcieep_cfg453_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg454 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg454_s { ++ uint32_t reserved_29_31:3; ++ uint32_t tmfcwt:5; ++ uint32_t tmanlt:5; ++ uint32_t tmrt:5; ++ uint32_t reserved_11_13:3; ++ uint32_t nskps:3; ++ uint32_t reserved_4_7:4; ++ uint32_t ntss:4; ++ } s; ++ struct cvmx_pcieep_cfg454_s cn52xx; ++ struct cvmx_pcieep_cfg454_s cn52xxp1; ++ struct cvmx_pcieep_cfg454_s cn56xx; ++ struct cvmx_pcieep_cfg454_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg455 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg455_s { ++ uint32_t m_cfg0_filt:1; ++ uint32_t m_io_filt:1; ++ uint32_t msg_ctrl:1; ++ uint32_t m_cpl_ecrc_filt:1; ++ uint32_t m_ecrc_filt:1; ++ uint32_t m_cpl_len_err:1; ++ uint32_t m_cpl_attr_err:1; ++ uint32_t m_cpl_tc_err:1; ++ uint32_t m_cpl_fun_err:1; ++ uint32_t m_cpl_rid_err:1; ++ uint32_t m_cpl_tag_err:1; ++ uint32_t m_lk_filt:1; ++ uint32_t m_cfg1_filt:1; ++ uint32_t m_bar_match:1; ++ uint32_t m_pois_filt:1; ++ uint32_t m_fun:1; ++ uint32_t dfcwt:1; ++ uint32_t reserved_11_14:4; ++ uint32_t skpiv:11; ++ } s; ++ struct cvmx_pcieep_cfg455_s cn52xx; ++ struct cvmx_pcieep_cfg455_s cn52xxp1; ++ struct cvmx_pcieep_cfg455_s cn56xx; ++ struct cvmx_pcieep_cfg455_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg456 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg456_s { ++ uint32_t reserved_2_31:30; ++ uint32_t m_vend1_drp:1; ++ uint32_t m_vend0_drp:1; ++ } s; ++ struct cvmx_pcieep_cfg456_s cn52xx; ++ struct cvmx_pcieep_cfg456_s cn52xxp1; ++ struct cvmx_pcieep_cfg456_s cn56xx; ++ struct cvmx_pcieep_cfg456_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg458 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg458_s { ++ uint32_t dbg_info_l32:32; ++ } s; ++ struct cvmx_pcieep_cfg458_s cn52xx; ++ struct cvmx_pcieep_cfg458_s cn52xxp1; ++ struct cvmx_pcieep_cfg458_s cn56xx; ++ struct cvmx_pcieep_cfg458_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg459 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg459_s { ++ uint32_t dbg_info_u32:32; ++ } s; ++ struct cvmx_pcieep_cfg459_s cn52xx; ++ struct cvmx_pcieep_cfg459_s cn52xxp1; ++ struct cvmx_pcieep_cfg459_s cn56xx; ++ struct cvmx_pcieep_cfg459_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg460 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg460_s { ++ uint32_t reserved_20_31:12; ++ uint32_t tphfcc:8; ++ uint32_t tpdfcc:12; ++ } s; ++ struct cvmx_pcieep_cfg460_s cn52xx; ++ struct cvmx_pcieep_cfg460_s cn52xxp1; ++ struct cvmx_pcieep_cfg460_s cn56xx; ++ struct cvmx_pcieep_cfg460_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg461 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg461_s { ++ uint32_t reserved_20_31:12; ++ uint32_t tchfcc:8; ++ uint32_t tcdfcc:12; ++ } s; ++ struct cvmx_pcieep_cfg461_s cn52xx; ++ struct cvmx_pcieep_cfg461_s cn52xxp1; ++ struct cvmx_pcieep_cfg461_s cn56xx; ++ struct cvmx_pcieep_cfg461_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg462 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg462_s { ++ uint32_t reserved_20_31:12; ++ uint32_t tchfcc:8; ++ uint32_t tcdfcc:12; ++ } s; ++ struct cvmx_pcieep_cfg462_s cn52xx; ++ struct cvmx_pcieep_cfg462_s cn52xxp1; ++ struct cvmx_pcieep_cfg462_s cn56xx; ++ struct cvmx_pcieep_cfg462_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg463 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg463_s { ++ uint32_t reserved_3_31:29; ++ uint32_t rqne:1; ++ uint32_t trbne:1; ++ uint32_t rtlpfccnr:1; ++ } s; ++ struct cvmx_pcieep_cfg463_s cn52xx; ++ struct cvmx_pcieep_cfg463_s cn52xxp1; ++ struct cvmx_pcieep_cfg463_s cn56xx; ++ struct cvmx_pcieep_cfg463_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg464 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg464_s { ++ uint32_t wrr_vc3:8; ++ uint32_t wrr_vc2:8; ++ uint32_t wrr_vc1:8; ++ uint32_t wrr_vc0:8; ++ } s; ++ struct cvmx_pcieep_cfg464_s cn52xx; ++ struct cvmx_pcieep_cfg464_s cn52xxp1; ++ struct cvmx_pcieep_cfg464_s cn56xx; ++ struct cvmx_pcieep_cfg464_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg465 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg465_s { ++ uint32_t wrr_vc7:8; ++ uint32_t wrr_vc6:8; ++ uint32_t wrr_vc5:8; ++ uint32_t wrr_vc4:8; ++ } s; ++ struct cvmx_pcieep_cfg465_s cn52xx; ++ struct cvmx_pcieep_cfg465_s cn52xxp1; ++ struct cvmx_pcieep_cfg465_s cn56xx; ++ struct cvmx_pcieep_cfg465_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg466 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg466_s { ++ uint32_t rx_queue_order:1; ++ uint32_t type_ordering:1; ++ uint32_t reserved_24_29:6; ++ uint32_t queue_mode:3; ++ uint32_t reserved_20_20:1; ++ uint32_t header_credits:8; ++ uint32_t data_credits:12; ++ } s; ++ struct cvmx_pcieep_cfg466_s cn52xx; ++ struct cvmx_pcieep_cfg466_s cn52xxp1; ++ struct cvmx_pcieep_cfg466_s cn56xx; ++ struct cvmx_pcieep_cfg466_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg467 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg467_s { ++ uint32_t reserved_24_31:8; ++ uint32_t queue_mode:3; ++ uint32_t reserved_20_20:1; ++ uint32_t header_credits:8; ++ uint32_t data_credits:12; ++ } s; ++ struct cvmx_pcieep_cfg467_s cn52xx; ++ struct cvmx_pcieep_cfg467_s cn52xxp1; ++ struct cvmx_pcieep_cfg467_s cn56xx; ++ struct cvmx_pcieep_cfg467_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg468 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg468_s { ++ uint32_t reserved_24_31:8; ++ uint32_t queue_mode:3; ++ uint32_t reserved_20_20:1; ++ uint32_t header_credits:8; ++ uint32_t data_credits:12; ++ } s; ++ struct cvmx_pcieep_cfg468_s cn52xx; ++ struct cvmx_pcieep_cfg468_s cn52xxp1; ++ struct cvmx_pcieep_cfg468_s cn56xx; ++ struct cvmx_pcieep_cfg468_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg490 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg490_s { ++ uint32_t reserved_26_31:6; ++ uint32_t header_depth:10; ++ uint32_t reserved_14_15:2; ++ uint32_t data_depth:14; ++ } s; ++ struct cvmx_pcieep_cfg490_s cn52xx; ++ struct cvmx_pcieep_cfg490_s cn52xxp1; ++ struct cvmx_pcieep_cfg490_s cn56xx; ++ struct cvmx_pcieep_cfg490_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg491 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg491_s { ++ uint32_t reserved_26_31:6; ++ uint32_t header_depth:10; ++ uint32_t reserved_14_15:2; ++ uint32_t data_depth:14; ++ } s; ++ struct cvmx_pcieep_cfg491_s cn52xx; ++ struct cvmx_pcieep_cfg491_s cn52xxp1; ++ struct cvmx_pcieep_cfg491_s cn56xx; ++ struct cvmx_pcieep_cfg491_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg492 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg492_s { ++ uint32_t reserved_26_31:6; ++ uint32_t header_depth:10; ++ uint32_t reserved_14_15:2; ++ uint32_t data_depth:14; ++ } s; ++ struct cvmx_pcieep_cfg492_s cn52xx; ++ struct cvmx_pcieep_cfg492_s cn52xxp1; ++ struct cvmx_pcieep_cfg492_s cn56xx; ++ struct cvmx_pcieep_cfg492_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg516 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg516_s { ++ uint32_t phy_stat:32; ++ } s; ++ struct cvmx_pcieep_cfg516_s cn52xx; ++ struct cvmx_pcieep_cfg516_s cn52xxp1; ++ struct cvmx_pcieep_cfg516_s cn56xx; ++ struct cvmx_pcieep_cfg516_s cn56xxp1; ++}; ++ ++union cvmx_pcieep_cfg517 { ++ uint32_t u32; ++ struct cvmx_pcieep_cfg517_s { ++ uint32_t phy_ctrl:32; ++ } s; ++ struct cvmx_pcieep_cfg517_s cn52xx; ++ struct cvmx_pcieep_cfg517_s cn52xxp1; ++ struct cvmx_pcieep_cfg517_s cn56xx; ++ struct cvmx_pcieep_cfg517_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h +@@ -0,0 +1,1397 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PCIERCX_DEFS_H__ ++#define __CVMX_PCIERCX_DEFS_H__ ++ ++#define CVMX_PCIERCX_CFG000(offset) \ ++ (0x0000000000000000ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG001(offset) \ ++ (0x0000000000000004ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG002(offset) \ ++ (0x0000000000000008ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG003(offset) \ ++ (0x000000000000000Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG004(offset) \ ++ (0x0000000000000010ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG005(offset) \ ++ (0x0000000000000014ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG006(offset) \ ++ (0x0000000000000018ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG007(offset) \ ++ (0x000000000000001Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG008(offset) \ ++ (0x0000000000000020ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG009(offset) \ ++ (0x0000000000000024ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG010(offset) \ ++ (0x0000000000000028ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG011(offset) \ ++ (0x000000000000002Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG012(offset) \ ++ (0x0000000000000030ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG013(offset) \ ++ (0x0000000000000034ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG014(offset) \ ++ (0x0000000000000038ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG015(offset) \ ++ (0x000000000000003Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG016(offset) \ ++ (0x0000000000000040ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG017(offset) \ ++ (0x0000000000000044ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG020(offset) \ ++ (0x0000000000000050ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG021(offset) \ ++ (0x0000000000000054ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG022(offset) \ ++ (0x0000000000000058ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG023(offset) \ ++ (0x000000000000005Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG028(offset) \ ++ (0x0000000000000070ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG029(offset) \ ++ (0x0000000000000074ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG030(offset) \ ++ (0x0000000000000078ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG031(offset) \ ++ (0x000000000000007Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG032(offset) \ ++ (0x0000000000000080ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG033(offset) \ ++ (0x0000000000000084ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG034(offset) \ ++ (0x0000000000000088ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG035(offset) \ ++ (0x000000000000008Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG036(offset) \ ++ (0x0000000000000090ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG037(offset) \ ++ (0x0000000000000094ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG038(offset) \ ++ (0x0000000000000098ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG039(offset) \ ++ (0x000000000000009Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG040(offset) \ ++ (0x00000000000000A0ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG041(offset) \ ++ (0x00000000000000A4ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG042(offset) \ ++ (0x00000000000000A8ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG064(offset) \ ++ (0x0000000000000100ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG065(offset) \ ++ (0x0000000000000104ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG066(offset) \ ++ (0x0000000000000108ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG067(offset) \ ++ (0x000000000000010Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG068(offset) \ ++ (0x0000000000000110ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG069(offset) \ ++ (0x0000000000000114ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG070(offset) \ ++ (0x0000000000000118ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG071(offset) \ ++ (0x000000000000011Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG072(offset) \ ++ (0x0000000000000120ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG073(offset) \ ++ (0x0000000000000124ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG074(offset) \ ++ (0x0000000000000128ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG075(offset) \ ++ (0x000000000000012Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG076(offset) \ ++ (0x0000000000000130ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG077(offset) \ ++ (0x0000000000000134ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG448(offset) \ ++ (0x0000000000000700ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG449(offset) \ ++ (0x0000000000000704ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG450(offset) \ ++ (0x0000000000000708ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG451(offset) \ ++ (0x000000000000070Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG452(offset) \ ++ (0x0000000000000710ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG453(offset) \ ++ (0x0000000000000714ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG454(offset) \ ++ (0x0000000000000718ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG455(offset) \ ++ (0x000000000000071Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG456(offset) \ ++ (0x0000000000000720ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG458(offset) \ ++ (0x0000000000000728ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG459(offset) \ ++ (0x000000000000072Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG460(offset) \ ++ (0x0000000000000730ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG461(offset) \ ++ (0x0000000000000734ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG462(offset) \ ++ (0x0000000000000738ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG463(offset) \ ++ (0x000000000000073Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG464(offset) \ ++ (0x0000000000000740ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG465(offset) \ ++ (0x0000000000000744ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG466(offset) \ ++ (0x0000000000000748ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG467(offset) \ ++ (0x000000000000074Cull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG468(offset) \ ++ (0x0000000000000750ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG490(offset) \ ++ (0x00000000000007A8ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG491(offset) \ ++ (0x00000000000007ACull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG492(offset) \ ++ (0x00000000000007B0ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG516(offset) \ ++ (0x0000000000000810ull + (((offset) & 1) * 0)) ++#define CVMX_PCIERCX_CFG517(offset) \ ++ (0x0000000000000814ull + (((offset) & 1) * 0)) ++ ++union cvmx_pciercx_cfg000 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg000_s { ++ uint32_t devid:16; ++ uint32_t vendid:16; ++ } s; ++ struct cvmx_pciercx_cfg000_s cn52xx; ++ struct cvmx_pciercx_cfg000_s cn52xxp1; ++ struct cvmx_pciercx_cfg000_s cn56xx; ++ struct cvmx_pciercx_cfg000_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg001 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg001_s { ++ uint32_t dpe:1; ++ uint32_t sse:1; ++ uint32_t rma:1; ++ uint32_t rta:1; ++ uint32_t sta:1; ++ uint32_t devt:2; ++ uint32_t mdpe:1; ++ uint32_t fbb:1; ++ uint32_t reserved_22_22:1; ++ uint32_t m66:1; ++ uint32_t cl:1; ++ uint32_t i_stat:1; ++ uint32_t reserved_11_18:8; ++ uint32_t i_dis:1; ++ uint32_t fbbe:1; ++ uint32_t see:1; ++ uint32_t ids_wcc:1; ++ uint32_t per:1; ++ uint32_t vps:1; ++ uint32_t mwice:1; ++ uint32_t scse:1; ++ uint32_t me:1; ++ uint32_t msae:1; ++ uint32_t isae:1; ++ } s; ++ struct cvmx_pciercx_cfg001_s cn52xx; ++ struct cvmx_pciercx_cfg001_s cn52xxp1; ++ struct cvmx_pciercx_cfg001_s cn56xx; ++ struct cvmx_pciercx_cfg001_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg002 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg002_s { ++ uint32_t bcc:8; ++ uint32_t sc:8; ++ uint32_t pi:8; ++ uint32_t rid:8; ++ } s; ++ struct cvmx_pciercx_cfg002_s cn52xx; ++ struct cvmx_pciercx_cfg002_s cn52xxp1; ++ struct cvmx_pciercx_cfg002_s cn56xx; ++ struct cvmx_pciercx_cfg002_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg003 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg003_s { ++ uint32_t bist:8; ++ uint32_t mfd:1; ++ uint32_t chf:7; ++ uint32_t lt:8; ++ uint32_t cls:8; ++ } s; ++ struct cvmx_pciercx_cfg003_s cn52xx; ++ struct cvmx_pciercx_cfg003_s cn52xxp1; ++ struct cvmx_pciercx_cfg003_s cn56xx; ++ struct cvmx_pciercx_cfg003_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg004 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg004_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg004_s cn52xx; ++ struct cvmx_pciercx_cfg004_s cn52xxp1; ++ struct cvmx_pciercx_cfg004_s cn56xx; ++ struct cvmx_pciercx_cfg004_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg005 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg005_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg005_s cn52xx; ++ struct cvmx_pciercx_cfg005_s cn52xxp1; ++ struct cvmx_pciercx_cfg005_s cn56xx; ++ struct cvmx_pciercx_cfg005_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg006 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg006_s { ++ uint32_t slt:8; ++ uint32_t subbnum:8; ++ uint32_t sbnum:8; ++ uint32_t pbnum:8; ++ } s; ++ struct cvmx_pciercx_cfg006_s cn52xx; ++ struct cvmx_pciercx_cfg006_s cn52xxp1; ++ struct cvmx_pciercx_cfg006_s cn56xx; ++ struct cvmx_pciercx_cfg006_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg007 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg007_s { ++ uint32_t dpe:1; ++ uint32_t sse:1; ++ uint32_t rma:1; ++ uint32_t rta:1; ++ uint32_t sta:1; ++ uint32_t devt:2; ++ uint32_t mdpe:1; ++ uint32_t fbb:1; ++ uint32_t reserved_22_22:1; ++ uint32_t m66:1; ++ uint32_t reserved_16_20:5; ++ uint32_t lio_limi:4; ++ uint32_t reserved_9_11:3; ++ uint32_t io32b:1; ++ uint32_t lio_base:4; ++ uint32_t reserved_1_3:3; ++ uint32_t io32a:1; ++ } s; ++ struct cvmx_pciercx_cfg007_s cn52xx; ++ struct cvmx_pciercx_cfg007_s cn52xxp1; ++ struct cvmx_pciercx_cfg007_s cn56xx; ++ struct cvmx_pciercx_cfg007_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg008 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg008_s { ++ uint32_t ml_addr:12; ++ uint32_t reserved_16_19:4; ++ uint32_t mb_addr:12; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pciercx_cfg008_s cn52xx; ++ struct cvmx_pciercx_cfg008_s cn52xxp1; ++ struct cvmx_pciercx_cfg008_s cn56xx; ++ struct cvmx_pciercx_cfg008_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg009 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg009_s { ++ uint32_t lmem_limit:12; ++ uint32_t reserved_17_19:3; ++ uint32_t mem64b:1; ++ uint32_t lmem_base:12; ++ uint32_t reserved_1_3:3; ++ uint32_t mem64a:1; ++ } s; ++ struct cvmx_pciercx_cfg009_s cn52xx; ++ struct cvmx_pciercx_cfg009_s cn52xxp1; ++ struct cvmx_pciercx_cfg009_s cn56xx; ++ struct cvmx_pciercx_cfg009_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg010 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg010_s { ++ uint32_t umem_base:32; ++ } s; ++ struct cvmx_pciercx_cfg010_s cn52xx; ++ struct cvmx_pciercx_cfg010_s cn52xxp1; ++ struct cvmx_pciercx_cfg010_s cn56xx; ++ struct cvmx_pciercx_cfg010_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg011 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg011_s { ++ uint32_t umem_limit:32; ++ } s; ++ struct cvmx_pciercx_cfg011_s cn52xx; ++ struct cvmx_pciercx_cfg011_s cn52xxp1; ++ struct cvmx_pciercx_cfg011_s cn56xx; ++ struct cvmx_pciercx_cfg011_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg012 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg012_s { ++ uint32_t uio_limit:16; ++ uint32_t uio_base:16; ++ } s; ++ struct cvmx_pciercx_cfg012_s cn52xx; ++ struct cvmx_pciercx_cfg012_s cn52xxp1; ++ struct cvmx_pciercx_cfg012_s cn56xx; ++ struct cvmx_pciercx_cfg012_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg013 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg013_s { ++ uint32_t reserved_8_31:24; ++ uint32_t cp:8; ++ } s; ++ struct cvmx_pciercx_cfg013_s cn52xx; ++ struct cvmx_pciercx_cfg013_s cn52xxp1; ++ struct cvmx_pciercx_cfg013_s cn56xx; ++ struct cvmx_pciercx_cfg013_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg014 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg014_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg014_s cn52xx; ++ struct cvmx_pciercx_cfg014_s cn52xxp1; ++ struct cvmx_pciercx_cfg014_s cn56xx; ++ struct cvmx_pciercx_cfg014_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg015 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg015_s { ++ uint32_t reserved_28_31:4; ++ uint32_t dtsees:1; ++ uint32_t dts:1; ++ uint32_t sdt:1; ++ uint32_t pdt:1; ++ uint32_t fbbe:1; ++ uint32_t sbrst:1; ++ uint32_t mam:1; ++ uint32_t vga16d:1; ++ uint32_t vgae:1; ++ uint32_t isae:1; ++ uint32_t see:1; ++ uint32_t pere:1; ++ uint32_t inta:8; ++ uint32_t il:8; ++ } s; ++ struct cvmx_pciercx_cfg015_s cn52xx; ++ struct cvmx_pciercx_cfg015_s cn52xxp1; ++ struct cvmx_pciercx_cfg015_s cn56xx; ++ struct cvmx_pciercx_cfg015_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg016 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg016_s { ++ uint32_t pmes:5; ++ uint32_t d2s:1; ++ uint32_t d1s:1; ++ uint32_t auxc:3; ++ uint32_t dsi:1; ++ uint32_t reserved_20_20:1; ++ uint32_t pme_clock:1; ++ uint32_t pmsv:3; ++ uint32_t ncp:8; ++ uint32_t pmcid:8; ++ } s; ++ struct cvmx_pciercx_cfg016_s cn52xx; ++ struct cvmx_pciercx_cfg016_s cn52xxp1; ++ struct cvmx_pciercx_cfg016_s cn56xx; ++ struct cvmx_pciercx_cfg016_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg017 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg017_s { ++ uint32_t pmdia:8; ++ uint32_t bpccee:1; ++ uint32_t bd3h:1; ++ uint32_t reserved_16_21:6; ++ uint32_t pmess:1; ++ uint32_t pmedsia:2; ++ uint32_t pmds:4; ++ uint32_t pmeens:1; ++ uint32_t reserved_4_7:4; ++ uint32_t nsr:1; ++ uint32_t reserved_2_2:1; ++ uint32_t ps:2; ++ } s; ++ struct cvmx_pciercx_cfg017_s cn52xx; ++ struct cvmx_pciercx_cfg017_s cn52xxp1; ++ struct cvmx_pciercx_cfg017_s cn56xx; ++ struct cvmx_pciercx_cfg017_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg020 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg020_s { ++ uint32_t reserved_24_31:8; ++ uint32_t m64:1; ++ uint32_t mme:3; ++ uint32_t mmc:3; ++ uint32_t msien:1; ++ uint32_t ncp:8; ++ uint32_t msicid:8; ++ } s; ++ struct cvmx_pciercx_cfg020_s cn52xx; ++ struct cvmx_pciercx_cfg020_s cn52xxp1; ++ struct cvmx_pciercx_cfg020_s cn56xx; ++ struct cvmx_pciercx_cfg020_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg021 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg021_s { ++ uint32_t lmsi:30; ++ uint32_t reserved_0_1:2; ++ } s; ++ struct cvmx_pciercx_cfg021_s cn52xx; ++ struct cvmx_pciercx_cfg021_s cn52xxp1; ++ struct cvmx_pciercx_cfg021_s cn56xx; ++ struct cvmx_pciercx_cfg021_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg022 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg022_s { ++ uint32_t umsi:32; ++ } s; ++ struct cvmx_pciercx_cfg022_s cn52xx; ++ struct cvmx_pciercx_cfg022_s cn52xxp1; ++ struct cvmx_pciercx_cfg022_s cn56xx; ++ struct cvmx_pciercx_cfg022_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg023 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg023_s { ++ uint32_t reserved_16_31:16; ++ uint32_t msimd:16; ++ } s; ++ struct cvmx_pciercx_cfg023_s cn52xx; ++ struct cvmx_pciercx_cfg023_s cn52xxp1; ++ struct cvmx_pciercx_cfg023_s cn56xx; ++ struct cvmx_pciercx_cfg023_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg028 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg028_s { ++ uint32_t reserved_30_31:2; ++ uint32_t imn:5; ++ uint32_t si:1; ++ uint32_t dpt:4; ++ uint32_t pciecv:4; ++ uint32_t ncp:8; ++ uint32_t pcieid:8; ++ } s; ++ struct cvmx_pciercx_cfg028_s cn52xx; ++ struct cvmx_pciercx_cfg028_s cn52xxp1; ++ struct cvmx_pciercx_cfg028_s cn56xx; ++ struct cvmx_pciercx_cfg028_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg029 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg029_s { ++ uint32_t reserved_28_31:4; ++ uint32_t cspls:2; ++ uint32_t csplv:8; ++ uint32_t reserved_16_17:2; ++ uint32_t rber:1; ++ uint32_t reserved_12_14:3; ++ uint32_t el1al:3; ++ uint32_t el0al:3; ++ uint32_t etfs:1; ++ uint32_t pfs:2; ++ uint32_t mpss:3; ++ } s; ++ struct cvmx_pciercx_cfg029_s cn52xx; ++ struct cvmx_pciercx_cfg029_s cn52xxp1; ++ struct cvmx_pciercx_cfg029_s cn56xx; ++ struct cvmx_pciercx_cfg029_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg030 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg030_s { ++ uint32_t reserved_22_31:10; ++ uint32_t tp:1; ++ uint32_t ap_d:1; ++ uint32_t ur_d:1; ++ uint32_t fe_d:1; ++ uint32_t nfe_d:1; ++ uint32_t ce_d:1; ++ uint32_t reserved_15_15:1; ++ uint32_t mrrs:3; ++ uint32_t ns_en:1; ++ uint32_t ap_en:1; ++ uint32_t pf_en:1; ++ uint32_t etf_en:1; ++ uint32_t mps:3; ++ uint32_t ro_en:1; ++ uint32_t ur_en:1; ++ uint32_t fe_en:1; ++ uint32_t nfe_en:1; ++ uint32_t ce_en:1; ++ } s; ++ struct cvmx_pciercx_cfg030_s cn52xx; ++ struct cvmx_pciercx_cfg030_s cn52xxp1; ++ struct cvmx_pciercx_cfg030_s cn56xx; ++ struct cvmx_pciercx_cfg030_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg031 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg031_s { ++ uint32_t pnum:8; ++ uint32_t reserved_22_23:2; ++ uint32_t lbnc:1; ++ uint32_t dllarc:1; ++ uint32_t sderc:1; ++ uint32_t cpm:1; ++ uint32_t l1el:3; ++ uint32_t l0el:3; ++ uint32_t aslpms:2; ++ uint32_t mlw:6; ++ uint32_t mls:4; ++ } s; ++ struct cvmx_pciercx_cfg031_s cn52xx; ++ struct cvmx_pciercx_cfg031_s cn52xxp1; ++ struct cvmx_pciercx_cfg031_s cn56xx; ++ struct cvmx_pciercx_cfg031_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg032 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg032_s { ++ uint32_t lab:1; ++ uint32_t lbm:1; ++ uint32_t dlla:1; ++ uint32_t scc:1; ++ uint32_t lt:1; ++ uint32_t reserved_26_26:1; ++ uint32_t nlw:6; ++ uint32_t ls:4; ++ uint32_t reserved_12_15:4; ++ uint32_t lab_int_enb:1; ++ uint32_t lbm_int_enb:1; ++ uint32_t hawd:1; ++ uint32_t ecpm:1; ++ uint32_t es:1; ++ uint32_t ccc:1; ++ uint32_t rl:1; ++ uint32_t ld:1; ++ uint32_t rcb:1; ++ uint32_t reserved_2_2:1; ++ uint32_t aslpc:2; ++ } s; ++ struct cvmx_pciercx_cfg032_s cn52xx; ++ struct cvmx_pciercx_cfg032_s cn52xxp1; ++ struct cvmx_pciercx_cfg032_s cn56xx; ++ struct cvmx_pciercx_cfg032_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg033 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg033_s { ++ uint32_t ps_num:13; ++ uint32_t nccs:1; ++ uint32_t emip:1; ++ uint32_t sp_ls:2; ++ uint32_t sp_lv:8; ++ uint32_t hp_c:1; ++ uint32_t hp_s:1; ++ uint32_t pip:1; ++ uint32_t aip:1; ++ uint32_t mrlsp:1; ++ uint32_t pcp:1; ++ uint32_t abp:1; ++ } s; ++ struct cvmx_pciercx_cfg033_s cn52xx; ++ struct cvmx_pciercx_cfg033_s cn52xxp1; ++ struct cvmx_pciercx_cfg033_s cn56xx; ++ struct cvmx_pciercx_cfg033_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg034 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg034_s { ++ uint32_t reserved_25_31:7; ++ uint32_t dlls_c:1; ++ uint32_t emis:1; ++ uint32_t pds:1; ++ uint32_t mrlss:1; ++ uint32_t ccint_d:1; ++ uint32_t pd_c:1; ++ uint32_t mrls_c:1; ++ uint32_t pf_d:1; ++ uint32_t abp_d:1; ++ uint32_t reserved_13_15:3; ++ uint32_t dlls_en:1; ++ uint32_t emic:1; ++ uint32_t pcc:1; ++ uint32_t pic:2; ++ uint32_t aic:2; ++ uint32_t hpint_en:1; ++ uint32_t ccint_en:1; ++ uint32_t pd_en:1; ++ uint32_t mrls_en:1; ++ uint32_t pf_en:1; ++ uint32_t abp_en:1; ++ } s; ++ struct cvmx_pciercx_cfg034_s cn52xx; ++ struct cvmx_pciercx_cfg034_s cn52xxp1; ++ struct cvmx_pciercx_cfg034_s cn56xx; ++ struct cvmx_pciercx_cfg034_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg035 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg035_s { ++ uint32_t reserved_17_31:15; ++ uint32_t crssv:1; ++ uint32_t reserved_5_15:11; ++ uint32_t crssve:1; ++ uint32_t pmeie:1; ++ uint32_t sefee:1; ++ uint32_t senfee:1; ++ uint32_t secee:1; ++ } s; ++ struct cvmx_pciercx_cfg035_s cn52xx; ++ struct cvmx_pciercx_cfg035_s cn52xxp1; ++ struct cvmx_pciercx_cfg035_s cn56xx; ++ struct cvmx_pciercx_cfg035_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg036 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg036_s { ++ uint32_t reserved_18_31:14; ++ uint32_t pme_pend:1; ++ uint32_t pme_stat:1; ++ uint32_t pme_rid:16; ++ } s; ++ struct cvmx_pciercx_cfg036_s cn52xx; ++ struct cvmx_pciercx_cfg036_s cn52xxp1; ++ struct cvmx_pciercx_cfg036_s cn56xx; ++ struct cvmx_pciercx_cfg036_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg037 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg037_s { ++ uint32_t reserved_5_31:27; ++ uint32_t ctds:1; ++ uint32_t ctrs:4; ++ } s; ++ struct cvmx_pciercx_cfg037_s cn52xx; ++ struct cvmx_pciercx_cfg037_s cn52xxp1; ++ struct cvmx_pciercx_cfg037_s cn56xx; ++ struct cvmx_pciercx_cfg037_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg038 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg038_s { ++ uint32_t reserved_5_31:27; ++ uint32_t ctd:1; ++ uint32_t ctv:4; ++ } s; ++ struct cvmx_pciercx_cfg038_s cn52xx; ++ struct cvmx_pciercx_cfg038_s cn52xxp1; ++ struct cvmx_pciercx_cfg038_s cn56xx; ++ struct cvmx_pciercx_cfg038_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg039 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg039_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg039_s cn52xx; ++ struct cvmx_pciercx_cfg039_s cn52xxp1; ++ struct cvmx_pciercx_cfg039_s cn56xx; ++ struct cvmx_pciercx_cfg039_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg040 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg040_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg040_s cn52xx; ++ struct cvmx_pciercx_cfg040_s cn52xxp1; ++ struct cvmx_pciercx_cfg040_s cn56xx; ++ struct cvmx_pciercx_cfg040_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg041 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg041_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg041_s cn52xx; ++ struct cvmx_pciercx_cfg041_s cn52xxp1; ++ struct cvmx_pciercx_cfg041_s cn56xx; ++ struct cvmx_pciercx_cfg041_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg042 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg042_s { ++ uint32_t reserved_0_31:32; ++ } s; ++ struct cvmx_pciercx_cfg042_s cn52xx; ++ struct cvmx_pciercx_cfg042_s cn52xxp1; ++ struct cvmx_pciercx_cfg042_s cn56xx; ++ struct cvmx_pciercx_cfg042_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg064 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg064_s { ++ uint32_t nco:12; ++ uint32_t cv:4; ++ uint32_t pcieec:16; ++ } s; ++ struct cvmx_pciercx_cfg064_s cn52xx; ++ struct cvmx_pciercx_cfg064_s cn52xxp1; ++ struct cvmx_pciercx_cfg064_s cn56xx; ++ struct cvmx_pciercx_cfg064_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg065 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg065_s { ++ uint32_t reserved_21_31:11; ++ uint32_t ures:1; ++ uint32_t ecrces:1; ++ uint32_t mtlps:1; ++ uint32_t ros:1; ++ uint32_t ucs:1; ++ uint32_t cas:1; ++ uint32_t cts:1; ++ uint32_t fcpes:1; ++ uint32_t ptlps:1; ++ uint32_t reserved_6_11:6; ++ uint32_t sdes:1; ++ uint32_t dlpes:1; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pciercx_cfg065_s cn52xx; ++ struct cvmx_pciercx_cfg065_s cn52xxp1; ++ struct cvmx_pciercx_cfg065_s cn56xx; ++ struct cvmx_pciercx_cfg065_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg066 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg066_s { ++ uint32_t reserved_21_31:11; ++ uint32_t urem:1; ++ uint32_t ecrcem:1; ++ uint32_t mtlpm:1; ++ uint32_t rom:1; ++ uint32_t ucm:1; ++ uint32_t cam:1; ++ uint32_t ctm:1; ++ uint32_t fcpem:1; ++ uint32_t ptlpm:1; ++ uint32_t reserved_6_11:6; ++ uint32_t sdem:1; ++ uint32_t dlpem:1; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pciercx_cfg066_s cn52xx; ++ struct cvmx_pciercx_cfg066_s cn52xxp1; ++ struct cvmx_pciercx_cfg066_s cn56xx; ++ struct cvmx_pciercx_cfg066_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg067 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg067_s { ++ uint32_t reserved_21_31:11; ++ uint32_t ures:1; ++ uint32_t ecrces:1; ++ uint32_t mtlps:1; ++ uint32_t ros:1; ++ uint32_t ucs:1; ++ uint32_t cas:1; ++ uint32_t cts:1; ++ uint32_t fcpes:1; ++ uint32_t ptlps:1; ++ uint32_t reserved_6_11:6; ++ uint32_t sdes:1; ++ uint32_t dlpes:1; ++ uint32_t reserved_0_3:4; ++ } s; ++ struct cvmx_pciercx_cfg067_s cn52xx; ++ struct cvmx_pciercx_cfg067_s cn52xxp1; ++ struct cvmx_pciercx_cfg067_s cn56xx; ++ struct cvmx_pciercx_cfg067_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg068 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg068_s { ++ uint32_t reserved_14_31:18; ++ uint32_t anfes:1; ++ uint32_t rtts:1; ++ uint32_t reserved_9_11:3; ++ uint32_t rnrs:1; ++ uint32_t bdllps:1; ++ uint32_t btlps:1; ++ uint32_t reserved_1_5:5; ++ uint32_t res:1; ++ } s; ++ struct cvmx_pciercx_cfg068_s cn52xx; ++ struct cvmx_pciercx_cfg068_s cn52xxp1; ++ struct cvmx_pciercx_cfg068_s cn56xx; ++ struct cvmx_pciercx_cfg068_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg069 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg069_s { ++ uint32_t reserved_14_31:18; ++ uint32_t anfem:1; ++ uint32_t rttm:1; ++ uint32_t reserved_9_11:3; ++ uint32_t rnrm:1; ++ uint32_t bdllpm:1; ++ uint32_t btlpm:1; ++ uint32_t reserved_1_5:5; ++ uint32_t rem:1; ++ } s; ++ struct cvmx_pciercx_cfg069_s cn52xx; ++ struct cvmx_pciercx_cfg069_s cn52xxp1; ++ struct cvmx_pciercx_cfg069_s cn56xx; ++ struct cvmx_pciercx_cfg069_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg070 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg070_s { ++ uint32_t reserved_9_31:23; ++ uint32_t ce:1; ++ uint32_t cc:1; ++ uint32_t ge:1; ++ uint32_t gc:1; ++ uint32_t fep:5; ++ } s; ++ struct cvmx_pciercx_cfg070_s cn52xx; ++ struct cvmx_pciercx_cfg070_s cn52xxp1; ++ struct cvmx_pciercx_cfg070_s cn56xx; ++ struct cvmx_pciercx_cfg070_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg071 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg071_s { ++ uint32_t dword1:32; ++ } s; ++ struct cvmx_pciercx_cfg071_s cn52xx; ++ struct cvmx_pciercx_cfg071_s cn52xxp1; ++ struct cvmx_pciercx_cfg071_s cn56xx; ++ struct cvmx_pciercx_cfg071_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg072 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg072_s { ++ uint32_t dword2:32; ++ } s; ++ struct cvmx_pciercx_cfg072_s cn52xx; ++ struct cvmx_pciercx_cfg072_s cn52xxp1; ++ struct cvmx_pciercx_cfg072_s cn56xx; ++ struct cvmx_pciercx_cfg072_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg073 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg073_s { ++ uint32_t dword3:32; ++ } s; ++ struct cvmx_pciercx_cfg073_s cn52xx; ++ struct cvmx_pciercx_cfg073_s cn52xxp1; ++ struct cvmx_pciercx_cfg073_s cn56xx; ++ struct cvmx_pciercx_cfg073_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg074 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg074_s { ++ uint32_t dword4:32; ++ } s; ++ struct cvmx_pciercx_cfg074_s cn52xx; ++ struct cvmx_pciercx_cfg074_s cn52xxp1; ++ struct cvmx_pciercx_cfg074_s cn56xx; ++ struct cvmx_pciercx_cfg074_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg075 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg075_s { ++ uint32_t reserved_3_31:29; ++ uint32_t fere:1; ++ uint32_t nfere:1; ++ uint32_t cere:1; ++ } s; ++ struct cvmx_pciercx_cfg075_s cn52xx; ++ struct cvmx_pciercx_cfg075_s cn52xxp1; ++ struct cvmx_pciercx_cfg075_s cn56xx; ++ struct cvmx_pciercx_cfg075_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg076 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg076_s { ++ uint32_t aeimn:5; ++ uint32_t reserved_7_26:20; ++ uint32_t femr:1; ++ uint32_t nfemr:1; ++ uint32_t fuf:1; ++ uint32_t multi_efnfr:1; ++ uint32_t efnfr:1; ++ uint32_t multi_ecr:1; ++ uint32_t ecr:1; ++ } s; ++ struct cvmx_pciercx_cfg076_s cn52xx; ++ struct cvmx_pciercx_cfg076_s cn52xxp1; ++ struct cvmx_pciercx_cfg076_s cn56xx; ++ struct cvmx_pciercx_cfg076_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg077 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg077_s { ++ uint32_t efnfsi:16; ++ uint32_t ecsi:16; ++ } s; ++ struct cvmx_pciercx_cfg077_s cn52xx; ++ struct cvmx_pciercx_cfg077_s cn52xxp1; ++ struct cvmx_pciercx_cfg077_s cn56xx; ++ struct cvmx_pciercx_cfg077_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg448 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg448_s { ++ uint32_t rtl:16; ++ uint32_t rtltl:16; ++ } s; ++ struct cvmx_pciercx_cfg448_s cn52xx; ++ struct cvmx_pciercx_cfg448_s cn52xxp1; ++ struct cvmx_pciercx_cfg448_s cn56xx; ++ struct cvmx_pciercx_cfg448_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg449 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg449_s { ++ uint32_t omr:32; ++ } s; ++ struct cvmx_pciercx_cfg449_s cn52xx; ++ struct cvmx_pciercx_cfg449_s cn52xxp1; ++ struct cvmx_pciercx_cfg449_s cn56xx; ++ struct cvmx_pciercx_cfg449_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg450 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg450_s { ++ uint32_t lpec:8; ++ uint32_t reserved_22_23:2; ++ uint32_t link_state:6; ++ uint32_t force_link:1; ++ uint32_t reserved_8_14:7; ++ uint32_t link_num:8; ++ } s; ++ struct cvmx_pciercx_cfg450_s cn52xx; ++ struct cvmx_pciercx_cfg450_s cn52xxp1; ++ struct cvmx_pciercx_cfg450_s cn56xx; ++ struct cvmx_pciercx_cfg450_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg451 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg451_s { ++ uint32_t reserved_30_31:2; ++ uint32_t l1el:3; ++ uint32_t l0el:3; ++ uint32_t n_fts_cc:8; ++ uint32_t n_fts:8; ++ uint32_t ack_freq:8; ++ } s; ++ struct cvmx_pciercx_cfg451_s cn52xx; ++ struct cvmx_pciercx_cfg451_s cn52xxp1; ++ struct cvmx_pciercx_cfg451_s cn56xx; ++ struct cvmx_pciercx_cfg451_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg452 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg452_s { ++ uint32_t reserved_26_31:6; ++ uint32_t eccrc:1; ++ uint32_t reserved_22_24:3; ++ uint32_t lme:6; ++ uint32_t reserved_8_15:8; ++ uint32_t flm:1; ++ uint32_t reserved_6_6:1; ++ uint32_t dllle:1; ++ uint32_t reserved_4_4:1; ++ uint32_t ra:1; ++ uint32_t le:1; ++ uint32_t sd:1; ++ uint32_t omr:1; ++ } s; ++ struct cvmx_pciercx_cfg452_s cn52xx; ++ struct cvmx_pciercx_cfg452_s cn52xxp1; ++ struct cvmx_pciercx_cfg452_s cn56xx; ++ struct cvmx_pciercx_cfg452_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg453 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg453_s { ++ uint32_t dlld:1; ++ uint32_t reserved_26_30:5; ++ uint32_t ack_nak:1; ++ uint32_t fcd:1; ++ uint32_t ilst:24; ++ } s; ++ struct cvmx_pciercx_cfg453_s cn52xx; ++ struct cvmx_pciercx_cfg453_s cn52xxp1; ++ struct cvmx_pciercx_cfg453_s cn56xx; ++ struct cvmx_pciercx_cfg453_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg454 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg454_s { ++ uint32_t reserved_29_31:3; ++ uint32_t tmfcwt:5; ++ uint32_t tmanlt:5; ++ uint32_t tmrt:5; ++ uint32_t reserved_11_13:3; ++ uint32_t nskps:3; ++ uint32_t reserved_4_7:4; ++ uint32_t ntss:4; ++ } s; ++ struct cvmx_pciercx_cfg454_s cn52xx; ++ struct cvmx_pciercx_cfg454_s cn52xxp1; ++ struct cvmx_pciercx_cfg454_s cn56xx; ++ struct cvmx_pciercx_cfg454_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg455 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg455_s { ++ uint32_t m_cfg0_filt:1; ++ uint32_t m_io_filt:1; ++ uint32_t msg_ctrl:1; ++ uint32_t m_cpl_ecrc_filt:1; ++ uint32_t m_ecrc_filt:1; ++ uint32_t m_cpl_len_err:1; ++ uint32_t m_cpl_attr_err:1; ++ uint32_t m_cpl_tc_err:1; ++ uint32_t m_cpl_fun_err:1; ++ uint32_t m_cpl_rid_err:1; ++ uint32_t m_cpl_tag_err:1; ++ uint32_t m_lk_filt:1; ++ uint32_t m_cfg1_filt:1; ++ uint32_t m_bar_match:1; ++ uint32_t m_pois_filt:1; ++ uint32_t m_fun:1; ++ uint32_t dfcwt:1; ++ uint32_t reserved_11_14:4; ++ uint32_t skpiv:11; ++ } s; ++ struct cvmx_pciercx_cfg455_s cn52xx; ++ struct cvmx_pciercx_cfg455_s cn52xxp1; ++ struct cvmx_pciercx_cfg455_s cn56xx; ++ struct cvmx_pciercx_cfg455_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg456 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg456_s { ++ uint32_t reserved_2_31:30; ++ uint32_t m_vend1_drp:1; ++ uint32_t m_vend0_drp:1; ++ } s; ++ struct cvmx_pciercx_cfg456_s cn52xx; ++ struct cvmx_pciercx_cfg456_s cn52xxp1; ++ struct cvmx_pciercx_cfg456_s cn56xx; ++ struct cvmx_pciercx_cfg456_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg458 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg458_s { ++ uint32_t dbg_info_l32:32; ++ } s; ++ struct cvmx_pciercx_cfg458_s cn52xx; ++ struct cvmx_pciercx_cfg458_s cn52xxp1; ++ struct cvmx_pciercx_cfg458_s cn56xx; ++ struct cvmx_pciercx_cfg458_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg459 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg459_s { ++ uint32_t dbg_info_u32:32; ++ } s; ++ struct cvmx_pciercx_cfg459_s cn52xx; ++ struct cvmx_pciercx_cfg459_s cn52xxp1; ++ struct cvmx_pciercx_cfg459_s cn56xx; ++ struct cvmx_pciercx_cfg459_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg460 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg460_s { ++ uint32_t reserved_20_31:12; ++ uint32_t tphfcc:8; ++ uint32_t tpdfcc:12; ++ } s; ++ struct cvmx_pciercx_cfg460_s cn52xx; ++ struct cvmx_pciercx_cfg460_s cn52xxp1; ++ struct cvmx_pciercx_cfg460_s cn56xx; ++ struct cvmx_pciercx_cfg460_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg461 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg461_s { ++ uint32_t reserved_20_31:12; ++ uint32_t tchfcc:8; ++ uint32_t tcdfcc:12; ++ } s; ++ struct cvmx_pciercx_cfg461_s cn52xx; ++ struct cvmx_pciercx_cfg461_s cn52xxp1; ++ struct cvmx_pciercx_cfg461_s cn56xx; ++ struct cvmx_pciercx_cfg461_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg462 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg462_s { ++ uint32_t reserved_20_31:12; ++ uint32_t tchfcc:8; ++ uint32_t tcdfcc:12; ++ } s; ++ struct cvmx_pciercx_cfg462_s cn52xx; ++ struct cvmx_pciercx_cfg462_s cn52xxp1; ++ struct cvmx_pciercx_cfg462_s cn56xx; ++ struct cvmx_pciercx_cfg462_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg463 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg463_s { ++ uint32_t reserved_3_31:29; ++ uint32_t rqne:1; ++ uint32_t trbne:1; ++ uint32_t rtlpfccnr:1; ++ } s; ++ struct cvmx_pciercx_cfg463_s cn52xx; ++ struct cvmx_pciercx_cfg463_s cn52xxp1; ++ struct cvmx_pciercx_cfg463_s cn56xx; ++ struct cvmx_pciercx_cfg463_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg464 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg464_s { ++ uint32_t wrr_vc3:8; ++ uint32_t wrr_vc2:8; ++ uint32_t wrr_vc1:8; ++ uint32_t wrr_vc0:8; ++ } s; ++ struct cvmx_pciercx_cfg464_s cn52xx; ++ struct cvmx_pciercx_cfg464_s cn52xxp1; ++ struct cvmx_pciercx_cfg464_s cn56xx; ++ struct cvmx_pciercx_cfg464_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg465 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg465_s { ++ uint32_t wrr_vc7:8; ++ uint32_t wrr_vc6:8; ++ uint32_t wrr_vc5:8; ++ uint32_t wrr_vc4:8; ++ } s; ++ struct cvmx_pciercx_cfg465_s cn52xx; ++ struct cvmx_pciercx_cfg465_s cn52xxp1; ++ struct cvmx_pciercx_cfg465_s cn56xx; ++ struct cvmx_pciercx_cfg465_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg466 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg466_s { ++ uint32_t rx_queue_order:1; ++ uint32_t type_ordering:1; ++ uint32_t reserved_24_29:6; ++ uint32_t queue_mode:3; ++ uint32_t reserved_20_20:1; ++ uint32_t header_credits:8; ++ uint32_t data_credits:12; ++ } s; ++ struct cvmx_pciercx_cfg466_s cn52xx; ++ struct cvmx_pciercx_cfg466_s cn52xxp1; ++ struct cvmx_pciercx_cfg466_s cn56xx; ++ struct cvmx_pciercx_cfg466_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg467 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg467_s { ++ uint32_t reserved_24_31:8; ++ uint32_t queue_mode:3; ++ uint32_t reserved_20_20:1; ++ uint32_t header_credits:8; ++ uint32_t data_credits:12; ++ } s; ++ struct cvmx_pciercx_cfg467_s cn52xx; ++ struct cvmx_pciercx_cfg467_s cn52xxp1; ++ struct cvmx_pciercx_cfg467_s cn56xx; ++ struct cvmx_pciercx_cfg467_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg468 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg468_s { ++ uint32_t reserved_24_31:8; ++ uint32_t queue_mode:3; ++ uint32_t reserved_20_20:1; ++ uint32_t header_credits:8; ++ uint32_t data_credits:12; ++ } s; ++ struct cvmx_pciercx_cfg468_s cn52xx; ++ struct cvmx_pciercx_cfg468_s cn52xxp1; ++ struct cvmx_pciercx_cfg468_s cn56xx; ++ struct cvmx_pciercx_cfg468_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg490 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg490_s { ++ uint32_t reserved_26_31:6; ++ uint32_t header_depth:10; ++ uint32_t reserved_14_15:2; ++ uint32_t data_depth:14; ++ } s; ++ struct cvmx_pciercx_cfg490_s cn52xx; ++ struct cvmx_pciercx_cfg490_s cn52xxp1; ++ struct cvmx_pciercx_cfg490_s cn56xx; ++ struct cvmx_pciercx_cfg490_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg491 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg491_s { ++ uint32_t reserved_26_31:6; ++ uint32_t header_depth:10; ++ uint32_t reserved_14_15:2; ++ uint32_t data_depth:14; ++ } s; ++ struct cvmx_pciercx_cfg491_s cn52xx; ++ struct cvmx_pciercx_cfg491_s cn52xxp1; ++ struct cvmx_pciercx_cfg491_s cn56xx; ++ struct cvmx_pciercx_cfg491_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg492 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg492_s { ++ uint32_t reserved_26_31:6; ++ uint32_t header_depth:10; ++ uint32_t reserved_14_15:2; ++ uint32_t data_depth:14; ++ } s; ++ struct cvmx_pciercx_cfg492_s cn52xx; ++ struct cvmx_pciercx_cfg492_s cn52xxp1; ++ struct cvmx_pciercx_cfg492_s cn56xx; ++ struct cvmx_pciercx_cfg492_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg516 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg516_s { ++ uint32_t phy_stat:32; ++ } s; ++ struct cvmx_pciercx_cfg516_s cn52xx; ++ struct cvmx_pciercx_cfg516_s cn52xxp1; ++ struct cvmx_pciercx_cfg516_s cn56xx; ++ struct cvmx_pciercx_cfg516_s cn56xxp1; ++}; ++ ++union cvmx_pciercx_cfg517 { ++ uint32_t u32; ++ struct cvmx_pciercx_cfg517_s { ++ uint32_t phy_ctrl:32; ++ } s; ++ struct cvmx_pciercx_cfg517_s cn52xx; ++ struct cvmx_pciercx_cfg517_s cn52xxp1; ++ struct cvmx_pciercx_cfg517_s cn56xx; ++ struct cvmx_pciercx_cfg517_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-pescx-defs.h +@@ -0,0 +1,410 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PESCX_DEFS_H__ ++#define __CVMX_PESCX_DEFS_H__ ++ ++#define CVMX_PESCX_BIST_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000018ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_BIST_STATUS2(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000418ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_CFG_RD(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000030ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_CFG_WR(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000028ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_CPL_LUT_VALID(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000098ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_CTL_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000000ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_CTL_STATUS2(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000400ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_DBG_INFO(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000008ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_DBG_INFO_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C80000A0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_DIAG_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000020ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_P2N_BAR0_START(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000080ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_P2N_BAR1_START(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000088ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_P2N_BAR2_START(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000090ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_P2P_BARX_END(offset,block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000048ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_P2P_BARX_START(offset,block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000040ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PESCX_TLP_CREDITS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800C8000038ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_pescx_bist_status { ++ uint64_t u64; ++ struct cvmx_pescx_bist_status_s { ++ uint64_t reserved_13_63:51; ++ uint64_t rqdata5:1; ++ uint64_t ctlp_or:1; ++ uint64_t ntlp_or:1; ++ uint64_t ptlp_or:1; ++ uint64_t retry:1; ++ uint64_t rqdata0:1; ++ uint64_t rqdata1:1; ++ uint64_t rqdata2:1; ++ uint64_t rqdata3:1; ++ uint64_t rqdata4:1; ++ uint64_t rqhdr1:1; ++ uint64_t rqhdr0:1; ++ uint64_t sot:1; ++ } s; ++ struct cvmx_pescx_bist_status_s cn52xx; ++ struct cvmx_pescx_bist_status_cn52xxp1 { ++ uint64_t reserved_12_63:52; ++ uint64_t ctlp_or:1; ++ uint64_t ntlp_or:1; ++ uint64_t ptlp_or:1; ++ uint64_t retry:1; ++ uint64_t rqdata0:1; ++ uint64_t rqdata1:1; ++ uint64_t rqdata2:1; ++ uint64_t rqdata3:1; ++ uint64_t rqdata4:1; ++ uint64_t rqhdr1:1; ++ uint64_t rqhdr0:1; ++ uint64_t sot:1; ++ } cn52xxp1; ++ struct cvmx_pescx_bist_status_s cn56xx; ++ struct cvmx_pescx_bist_status_cn52xxp1 cn56xxp1; ++}; ++ ++union cvmx_pescx_bist_status2 { ++ uint64_t u64; ++ struct cvmx_pescx_bist_status2_s { ++ uint64_t reserved_14_63:50; ++ uint64_t cto_p2e:1; ++ uint64_t e2p_cpl:1; ++ uint64_t e2p_n:1; ++ uint64_t e2p_p:1; ++ uint64_t e2p_rsl:1; ++ uint64_t dbg_p2e:1; ++ uint64_t peai_p2e:1; ++ uint64_t rsl_p2e:1; ++ uint64_t pef_tpf1:1; ++ uint64_t pef_tpf0:1; ++ uint64_t pef_tnf:1; ++ uint64_t pef_tcf1:1; ++ uint64_t pef_tc0:1; ++ uint64_t ppf:1; ++ } s; ++ struct cvmx_pescx_bist_status2_s cn52xx; ++ struct cvmx_pescx_bist_status2_s cn52xxp1; ++ struct cvmx_pescx_bist_status2_s cn56xx; ++ struct cvmx_pescx_bist_status2_s cn56xxp1; ++}; ++ ++union cvmx_pescx_cfg_rd { ++ uint64_t u64; ++ struct cvmx_pescx_cfg_rd_s { ++ uint64_t data:32; ++ uint64_t addr:32; ++ } s; ++ struct cvmx_pescx_cfg_rd_s cn52xx; ++ struct cvmx_pescx_cfg_rd_s cn52xxp1; ++ struct cvmx_pescx_cfg_rd_s cn56xx; ++ struct cvmx_pescx_cfg_rd_s cn56xxp1; ++}; ++ ++union cvmx_pescx_cfg_wr { ++ uint64_t u64; ++ struct cvmx_pescx_cfg_wr_s { ++ uint64_t data:32; ++ uint64_t addr:32; ++ } s; ++ struct cvmx_pescx_cfg_wr_s cn52xx; ++ struct cvmx_pescx_cfg_wr_s cn52xxp1; ++ struct cvmx_pescx_cfg_wr_s cn56xx; ++ struct cvmx_pescx_cfg_wr_s cn56xxp1; ++}; ++ ++union cvmx_pescx_cpl_lut_valid { ++ uint64_t u64; ++ struct cvmx_pescx_cpl_lut_valid_s { ++ uint64_t reserved_32_63:32; ++ uint64_t tag:32; ++ } s; ++ struct cvmx_pescx_cpl_lut_valid_s cn52xx; ++ struct cvmx_pescx_cpl_lut_valid_s cn52xxp1; ++ struct cvmx_pescx_cpl_lut_valid_s cn56xx; ++ struct cvmx_pescx_cpl_lut_valid_s cn56xxp1; ++}; ++ ++union cvmx_pescx_ctl_status { ++ uint64_t u64; ++ struct cvmx_pescx_ctl_status_s { ++ uint64_t reserved_28_63:36; ++ uint64_t dnum:5; ++ uint64_t pbus:8; ++ uint64_t qlm_cfg:2; ++ uint64_t lane_swp:1; ++ uint64_t pm_xtoff:1; ++ uint64_t pm_xpme:1; ++ uint64_t ob_p_cmd:1; ++ uint64_t reserved_7_8:2; ++ uint64_t nf_ecrc:1; ++ uint64_t dly_one:1; ++ uint64_t lnk_enb:1; ++ uint64_t ro_ctlp:1; ++ uint64_t reserved_2_2:1; ++ uint64_t inv_ecrc:1; ++ uint64_t inv_lcrc:1; ++ } s; ++ struct cvmx_pescx_ctl_status_s cn52xx; ++ struct cvmx_pescx_ctl_status_s cn52xxp1; ++ struct cvmx_pescx_ctl_status_cn56xx { ++ uint64_t reserved_28_63:36; ++ uint64_t dnum:5; ++ uint64_t pbus:8; ++ uint64_t qlm_cfg:2; ++ uint64_t reserved_12_12:1; ++ uint64_t pm_xtoff:1; ++ uint64_t pm_xpme:1; ++ uint64_t ob_p_cmd:1; ++ uint64_t reserved_7_8:2; ++ uint64_t nf_ecrc:1; ++ uint64_t dly_one:1; ++ uint64_t lnk_enb:1; ++ uint64_t ro_ctlp:1; ++ uint64_t reserved_2_2:1; ++ uint64_t inv_ecrc:1; ++ uint64_t inv_lcrc:1; ++ } cn56xx; ++ struct cvmx_pescx_ctl_status_cn56xx cn56xxp1; ++}; ++ ++union cvmx_pescx_ctl_status2 { ++ uint64_t u64; ++ struct cvmx_pescx_ctl_status2_s { ++ uint64_t reserved_2_63:62; ++ uint64_t pclk_run:1; ++ uint64_t pcierst:1; ++ } s; ++ struct cvmx_pescx_ctl_status2_s cn52xx; ++ struct cvmx_pescx_ctl_status2_cn52xxp1 { ++ uint64_t reserved_1_63:63; ++ uint64_t pcierst:1; ++ } cn52xxp1; ++ struct cvmx_pescx_ctl_status2_s cn56xx; ++ struct cvmx_pescx_ctl_status2_cn52xxp1 cn56xxp1; ++}; ++ ++union cvmx_pescx_dbg_info { ++ uint64_t u64; ++ struct cvmx_pescx_dbg_info_s { ++ uint64_t reserved_31_63:33; ++ uint64_t ecrc_e:1; ++ uint64_t rawwpp:1; ++ uint64_t racpp:1; ++ uint64_t ramtlp:1; ++ uint64_t rarwdns:1; ++ uint64_t caar:1; ++ uint64_t racca:1; ++ uint64_t racur:1; ++ uint64_t rauc:1; ++ uint64_t rqo:1; ++ uint64_t fcuv:1; ++ uint64_t rpe:1; ++ uint64_t fcpvwt:1; ++ uint64_t dpeoosd:1; ++ uint64_t rtwdle:1; ++ uint64_t rdwdle:1; ++ uint64_t mre:1; ++ uint64_t rte:1; ++ uint64_t acto:1; ++ uint64_t rvdm:1; ++ uint64_t rumep:1; ++ uint64_t rptamrc:1; ++ uint64_t rpmerc:1; ++ uint64_t rfemrc:1; ++ uint64_t rnfemrc:1; ++ uint64_t rcemrc:1; ++ uint64_t rpoison:1; ++ uint64_t recrce:1; ++ uint64_t rtlplle:1; ++ uint64_t rtlpmal:1; ++ uint64_t spoison:1; ++ } s; ++ struct cvmx_pescx_dbg_info_s cn52xx; ++ struct cvmx_pescx_dbg_info_s cn52xxp1; ++ struct cvmx_pescx_dbg_info_s cn56xx; ++ struct cvmx_pescx_dbg_info_s cn56xxp1; ++}; ++ ++union cvmx_pescx_dbg_info_en { ++ uint64_t u64; ++ struct cvmx_pescx_dbg_info_en_s { ++ uint64_t reserved_31_63:33; ++ uint64_t ecrc_e:1; ++ uint64_t rawwpp:1; ++ uint64_t racpp:1; ++ uint64_t ramtlp:1; ++ uint64_t rarwdns:1; ++ uint64_t caar:1; ++ uint64_t racca:1; ++ uint64_t racur:1; ++ uint64_t rauc:1; ++ uint64_t rqo:1; ++ uint64_t fcuv:1; ++ uint64_t rpe:1; ++ uint64_t fcpvwt:1; ++ uint64_t dpeoosd:1; ++ uint64_t rtwdle:1; ++ uint64_t rdwdle:1; ++ uint64_t mre:1; ++ uint64_t rte:1; ++ uint64_t acto:1; ++ uint64_t rvdm:1; ++ uint64_t rumep:1; ++ uint64_t rptamrc:1; ++ uint64_t rpmerc:1; ++ uint64_t rfemrc:1; ++ uint64_t rnfemrc:1; ++ uint64_t rcemrc:1; ++ uint64_t rpoison:1; ++ uint64_t recrce:1; ++ uint64_t rtlplle:1; ++ uint64_t rtlpmal:1; ++ uint64_t spoison:1; ++ } s; ++ struct cvmx_pescx_dbg_info_en_s cn52xx; ++ struct cvmx_pescx_dbg_info_en_s cn52xxp1; ++ struct cvmx_pescx_dbg_info_en_s cn56xx; ++ struct cvmx_pescx_dbg_info_en_s cn56xxp1; ++}; ++ ++union cvmx_pescx_diag_status { ++ uint64_t u64; ++ struct cvmx_pescx_diag_status_s { ++ uint64_t reserved_4_63:60; ++ uint64_t pm_dst:1; ++ uint64_t pm_stat:1; ++ uint64_t pm_en:1; ++ uint64_t aux_en:1; ++ } s; ++ struct cvmx_pescx_diag_status_s cn52xx; ++ struct cvmx_pescx_diag_status_s cn52xxp1; ++ struct cvmx_pescx_diag_status_s cn56xx; ++ struct cvmx_pescx_diag_status_s cn56xxp1; ++}; ++ ++union cvmx_pescx_p2n_bar0_start { ++ uint64_t u64; ++ struct cvmx_pescx_p2n_bar0_start_s { ++ uint64_t addr:50; ++ uint64_t reserved_0_13:14; ++ } s; ++ struct cvmx_pescx_p2n_bar0_start_s cn52xx; ++ struct cvmx_pescx_p2n_bar0_start_s cn52xxp1; ++ struct cvmx_pescx_p2n_bar0_start_s cn56xx; ++ struct cvmx_pescx_p2n_bar0_start_s cn56xxp1; ++}; ++ ++union cvmx_pescx_p2n_bar1_start { ++ uint64_t u64; ++ struct cvmx_pescx_p2n_bar1_start_s { ++ uint64_t addr:38; ++ uint64_t reserved_0_25:26; ++ } s; ++ struct cvmx_pescx_p2n_bar1_start_s cn52xx; ++ struct cvmx_pescx_p2n_bar1_start_s cn52xxp1; ++ struct cvmx_pescx_p2n_bar1_start_s cn56xx; ++ struct cvmx_pescx_p2n_bar1_start_s cn56xxp1; ++}; ++ ++union cvmx_pescx_p2n_bar2_start { ++ uint64_t u64; ++ struct cvmx_pescx_p2n_bar2_start_s { ++ uint64_t addr:25; ++ uint64_t reserved_0_38:39; ++ } s; ++ struct cvmx_pescx_p2n_bar2_start_s cn52xx; ++ struct cvmx_pescx_p2n_bar2_start_s cn52xxp1; ++ struct cvmx_pescx_p2n_bar2_start_s cn56xx; ++ struct cvmx_pescx_p2n_bar2_start_s cn56xxp1; ++}; ++ ++union cvmx_pescx_p2p_barx_end { ++ uint64_t u64; ++ struct cvmx_pescx_p2p_barx_end_s { ++ uint64_t addr:52; ++ uint64_t reserved_0_11:12; ++ } s; ++ struct cvmx_pescx_p2p_barx_end_s cn52xx; ++ struct cvmx_pescx_p2p_barx_end_s cn52xxp1; ++ struct cvmx_pescx_p2p_barx_end_s cn56xx; ++ struct cvmx_pescx_p2p_barx_end_s cn56xxp1; ++}; ++ ++union cvmx_pescx_p2p_barx_start { ++ uint64_t u64; ++ struct cvmx_pescx_p2p_barx_start_s { ++ uint64_t addr:52; ++ uint64_t reserved_0_11:12; ++ } s; ++ struct cvmx_pescx_p2p_barx_start_s cn52xx; ++ struct cvmx_pescx_p2p_barx_start_s cn52xxp1; ++ struct cvmx_pescx_p2p_barx_start_s cn56xx; ++ struct cvmx_pescx_p2p_barx_start_s cn56xxp1; ++}; ++ ++union cvmx_pescx_tlp_credits { ++ uint64_t u64; ++ struct cvmx_pescx_tlp_credits_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pescx_tlp_credits_cn52xx { ++ uint64_t reserved_56_63:8; ++ uint64_t peai_ppf:8; ++ uint64_t pesc_cpl:8; ++ uint64_t pesc_np:8; ++ uint64_t pesc_p:8; ++ uint64_t npei_cpl:8; ++ uint64_t npei_np:8; ++ uint64_t npei_p:8; ++ } cn52xx; ++ struct cvmx_pescx_tlp_credits_cn52xxp1 { ++ uint64_t reserved_38_63:26; ++ uint64_t peai_ppf:8; ++ uint64_t pesc_cpl:5; ++ uint64_t pesc_np:5; ++ uint64_t pesc_p:5; ++ uint64_t npei_cpl:5; ++ uint64_t npei_np:5; ++ uint64_t npei_p:5; ++ } cn52xxp1; ++ struct cvmx_pescx_tlp_credits_cn52xx cn56xx; ++ struct cvmx_pescx_tlp_credits_cn52xxp1 cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-pexp-defs.h +@@ -0,0 +1,229 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * cvmx-pexp-defs.h ++ * ++ * Configuration and status register (CSR) definitions for ++ * OCTEON PEXP. ++ * ++ */ ++#ifndef __CVMX_PEXP_DEFS_H__ ++#define __CVMX_PEXP_DEFS_H__ ++ ++#define CVMX_PEXP_NPEI_BAR1_INDEXX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000008000ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_BIST_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011F0000008580ull) ++#define CVMX_PEXP_NPEI_BIST_STATUS2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008680ull) ++#define CVMX_PEXP_NPEI_CTL_PORT0 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008250ull) ++#define CVMX_PEXP_NPEI_CTL_PORT1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008260ull) ++#define CVMX_PEXP_NPEI_CTL_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011F0000008570ull) ++#define CVMX_PEXP_NPEI_CTL_STATUS2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC00ull) ++#define CVMX_PEXP_NPEI_DATA_OUT_CNT \ ++ CVMX_ADD_IO_SEG(0x00011F00000085F0ull) ++#define CVMX_PEXP_NPEI_DBG_DATA \ ++ CVMX_ADD_IO_SEG(0x00011F0000008510ull) ++#define CVMX_PEXP_NPEI_DBG_SELECT \ ++ CVMX_ADD_IO_SEG(0x00011F0000008500ull) ++#define CVMX_PEXP_NPEI_DMA0_INT_LEVEL \ ++ CVMX_ADD_IO_SEG(0x00011F00000085C0ull) ++#define CVMX_PEXP_NPEI_DMA1_INT_LEVEL \ ++ CVMX_ADD_IO_SEG(0x00011F00000085D0ull) ++#define CVMX_PEXP_NPEI_DMAX_COUNTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000008450ull + (((offset) & 7) * 16)) ++#define CVMX_PEXP_NPEI_DMAX_DBELL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F00000083B0ull + (((offset) & 7) * 16)) ++#define CVMX_PEXP_NPEI_DMAX_IBUFF_SADDR(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000008400ull + (((offset) & 7) * 16)) ++#define CVMX_PEXP_NPEI_DMAX_NADDR(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F00000084A0ull + (((offset) & 7) * 16)) ++#define CVMX_PEXP_NPEI_DMA_CNTS \ ++ CVMX_ADD_IO_SEG(0x00011F00000085E0ull) ++#define CVMX_PEXP_NPEI_DMA_CONTROL \ ++ CVMX_ADD_IO_SEG(0x00011F00000083A0ull) ++#define CVMX_PEXP_NPEI_INT_A_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000008560ull) ++#define CVMX_PEXP_NPEI_INT_A_ENB2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BCE0ull) ++#define CVMX_PEXP_NPEI_INT_A_SUM \ ++ CVMX_ADD_IO_SEG(0x00011F0000008550ull) ++#define CVMX_PEXP_NPEI_INT_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000008540ull) ++#define CVMX_PEXP_NPEI_INT_ENB2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BCD0ull) ++#define CVMX_PEXP_NPEI_INT_INFO \ ++ CVMX_ADD_IO_SEG(0x00011F0000008590ull) ++#define CVMX_PEXP_NPEI_INT_SUM \ ++ CVMX_ADD_IO_SEG(0x00011F0000008530ull) ++#define CVMX_PEXP_NPEI_INT_SUM2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BCC0ull) ++#define CVMX_PEXP_NPEI_LAST_WIN_RDATA0 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008600ull) ++#define CVMX_PEXP_NPEI_LAST_WIN_RDATA1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008610ull) ++#define CVMX_PEXP_NPEI_MEM_ACCESS_CTL \ ++ CVMX_ADD_IO_SEG(0x00011F00000084F0ull) ++#define CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000008280ull + (((offset) & 31) * 16) - 16 * 12) ++#define CVMX_PEXP_NPEI_MSI_ENB0 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC50ull) ++#define CVMX_PEXP_NPEI_MSI_ENB1 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC60ull) ++#define CVMX_PEXP_NPEI_MSI_ENB2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC70ull) ++#define CVMX_PEXP_NPEI_MSI_ENB3 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC80ull) ++#define CVMX_PEXP_NPEI_MSI_RCV0 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC10ull) ++#define CVMX_PEXP_NPEI_MSI_RCV1 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC20ull) ++#define CVMX_PEXP_NPEI_MSI_RCV2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC30ull) ++#define CVMX_PEXP_NPEI_MSI_RCV3 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC40ull) ++#define CVMX_PEXP_NPEI_MSI_RD_MAP \ ++ CVMX_ADD_IO_SEG(0x00011F000000BCA0ull) ++#define CVMX_PEXP_NPEI_MSI_W1C_ENB0 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BCF0ull) ++#define CVMX_PEXP_NPEI_MSI_W1C_ENB1 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD00ull) ++#define CVMX_PEXP_NPEI_MSI_W1C_ENB2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD10ull) ++#define CVMX_PEXP_NPEI_MSI_W1C_ENB3 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD20ull) ++#define CVMX_PEXP_NPEI_MSI_W1S_ENB0 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD30ull) ++#define CVMX_PEXP_NPEI_MSI_W1S_ENB1 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD40ull) ++#define CVMX_PEXP_NPEI_MSI_W1S_ENB2 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD50ull) ++#define CVMX_PEXP_NPEI_MSI_W1S_ENB3 \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD60ull) ++#define CVMX_PEXP_NPEI_MSI_WR_MAP \ ++ CVMX_ADD_IO_SEG(0x00011F000000BC90ull) ++#define CVMX_PEXP_NPEI_PCIE_CREDIT_CNT \ ++ CVMX_ADD_IO_SEG(0x00011F000000BD70ull) ++#define CVMX_PEXP_NPEI_PCIE_MSI_RCV \ ++ CVMX_ADD_IO_SEG(0x00011F000000BCB0ull) ++#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008650ull) ++#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008660ull) ++#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B3 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008670ull) ++#define CVMX_PEXP_NPEI_PKTX_CNTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000A400ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_INSTR_BADDR(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000A800ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000AC00ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000B000ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_INSTR_HEADER(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000B400ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_IN_BP(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000B800ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_SLIST_BADDR(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000009400ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000009800ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F0000009C00ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKT_CNT_INT \ ++ CVMX_ADD_IO_SEG(0x00011F0000009110ull) ++#define CVMX_PEXP_NPEI_PKT_CNT_INT_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000009130ull) ++#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ES \ ++ CVMX_ADD_IO_SEG(0x00011F00000090B0ull) ++#define CVMX_PEXP_NPEI_PKT_DATA_OUT_NS \ ++ CVMX_ADD_IO_SEG(0x00011F00000090A0ull) ++#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ROR \ ++ CVMX_ADD_IO_SEG(0x00011F0000009090ull) ++#define CVMX_PEXP_NPEI_PKT_DPADDR \ ++ CVMX_ADD_IO_SEG(0x00011F0000009080ull) ++#define CVMX_PEXP_NPEI_PKT_INPUT_CONTROL \ ++ CVMX_ADD_IO_SEG(0x00011F0000009150ull) ++#define CVMX_PEXP_NPEI_PKT_INSTR_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000009000ull) ++#define CVMX_PEXP_NPEI_PKT_INSTR_RD_SIZE \ ++ CVMX_ADD_IO_SEG(0x00011F0000009190ull) ++#define CVMX_PEXP_NPEI_PKT_INSTR_SIZE \ ++ CVMX_ADD_IO_SEG(0x00011F0000009020ull) ++#define CVMX_PEXP_NPEI_PKT_INT_LEVELS \ ++ CVMX_ADD_IO_SEG(0x00011F0000009100ull) ++#define CVMX_PEXP_NPEI_PKT_IN_BP \ ++ CVMX_ADD_IO_SEG(0x00011F00000086B0ull) ++#define CVMX_PEXP_NPEI_PKT_IN_DONEX_CNTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011F000000A000ull + (((offset) & 31) * 16)) ++#define CVMX_PEXP_NPEI_PKT_IN_INSTR_COUNTS \ ++ CVMX_ADD_IO_SEG(0x00011F00000086A0ull) ++#define CVMX_PEXP_NPEI_PKT_IN_PCIE_PORT \ ++ CVMX_ADD_IO_SEG(0x00011F00000091A0ull) ++#define CVMX_PEXP_NPEI_PKT_IPTR \ ++ CVMX_ADD_IO_SEG(0x00011F0000009070ull) ++#define CVMX_PEXP_NPEI_PKT_OUTPUT_WMARK \ ++ CVMX_ADD_IO_SEG(0x00011F0000009160ull) ++#define CVMX_PEXP_NPEI_PKT_OUT_BMODE \ ++ CVMX_ADD_IO_SEG(0x00011F00000090D0ull) ++#define CVMX_PEXP_NPEI_PKT_OUT_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000009010ull) ++#define CVMX_PEXP_NPEI_PKT_PCIE_PORT \ ++ CVMX_ADD_IO_SEG(0x00011F00000090E0ull) ++#define CVMX_PEXP_NPEI_PKT_PORT_IN_RST \ ++ CVMX_ADD_IO_SEG(0x00011F0000008690ull) ++#define CVMX_PEXP_NPEI_PKT_SLIST_ES \ ++ CVMX_ADD_IO_SEG(0x00011F0000009050ull) ++#define CVMX_PEXP_NPEI_PKT_SLIST_ID_SIZE \ ++ CVMX_ADD_IO_SEG(0x00011F0000009180ull) ++#define CVMX_PEXP_NPEI_PKT_SLIST_NS \ ++ CVMX_ADD_IO_SEG(0x00011F0000009040ull) ++#define CVMX_PEXP_NPEI_PKT_SLIST_ROR \ ++ CVMX_ADD_IO_SEG(0x00011F0000009030ull) ++#define CVMX_PEXP_NPEI_PKT_TIME_INT \ ++ CVMX_ADD_IO_SEG(0x00011F0000009120ull) ++#define CVMX_PEXP_NPEI_PKT_TIME_INT_ENB \ ++ CVMX_ADD_IO_SEG(0x00011F0000009140ull) ++#define CVMX_PEXP_NPEI_RSL_INT_BLOCKS \ ++ CVMX_ADD_IO_SEG(0x00011F0000008520ull) ++#define CVMX_PEXP_NPEI_SCRATCH_1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008270ull) ++#define CVMX_PEXP_NPEI_STATE1 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008620ull) ++#define CVMX_PEXP_NPEI_STATE2 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008630ull) ++#define CVMX_PEXP_NPEI_STATE3 \ ++ CVMX_ADD_IO_SEG(0x00011F0000008640ull) ++#define CVMX_PEXP_NPEI_WINDOW_CTL \ ++ CVMX_ADD_IO_SEG(0x00011F0000008380ull) ++ ++#endif diff --git a/target/linux/octeon/patches-2.6.30/003_pci_pcie_support.patch b/target/linux/octeon/patches-2.6.30/003_pci_pcie_support.patch new file mode 100644 index 0000000000..32ba634c38 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/003_pci_pcie_support.patch @@ -0,0 +1,5002 @@ +This patch adds support for PCI and PCIe to the base Cavium OCTEON +processor support. + +Signed-off-by: David Daney +--- + arch/mips/Kconfig | 2 + + arch/mips/cavium-octeon/Makefile | 4 + + arch/mips/cavium-octeon/dma-octeon.c | 310 ++++++- + arch/mips/cavium-octeon/executive/Makefile | 2 + + .../cavium-octeon/executive/cvmx-helper-errata.c | 379 +++++++ + .../cavium-octeon/executive/cvmx-helper-util.c | 502 ++++++++++ + arch/mips/cavium-octeon/executive/cvmx-pcie.c | 1053 ++++++++++++++++++++ + arch/mips/cavium-octeon/msi.c | 288 ++++++ + arch/mips/cavium-octeon/octeon-irq.c | 2 + + arch/mips/cavium-octeon/pci-common.c | 137 +++ + arch/mips/cavium-octeon/pci-common.h | 39 + + arch/mips/cavium-octeon/pci.c | 568 +++++++++++ + arch/mips/cavium-octeon/pcie.c | 441 ++++++++ + arch/mips/include/asm/octeon/cvmx-asm.h | 3 +- + arch/mips/include/asm/octeon/cvmx-helper-errata.h | 92 ++ + arch/mips/include/asm/octeon/cvmx-helper-util.h | 266 +++++ + arch/mips/include/asm/octeon/cvmx-packet.h | 16 +- + arch/mips/include/asm/octeon/cvmx-pcie.h | 284 ++++++ + arch/mips/include/asm/octeon/cvmx-wqe.h | 422 ++++++++ + arch/mips/include/asm/octeon/cvmx.h | 12 + + arch/mips/include/asm/octeon/octeon.h | 2 + + 21 files changed, 4816 insertions(+), 8 deletions(-) + create mode 100644 arch/mips/cavium-octeon/executive/cvmx-helper-errata.c + create mode 100644 arch/mips/cavium-octeon/executive/cvmx-helper-util.c + create mode 100644 arch/mips/cavium-octeon/executive/cvmx-pcie.c + create mode 100644 arch/mips/cavium-octeon/msi.c + create mode 100644 arch/mips/cavium-octeon/pci-common.c + create mode 100644 arch/mips/cavium-octeon/pci-common.h + create mode 100644 arch/mips/cavium-octeon/pci.c + create mode 100644 arch/mips/cavium-octeon/pcie.c + create mode 100644 arch/mips/include/asm/octeon/cvmx-helper-errata.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-helper-util.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-pcie.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-wqe.h + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -618,6 +618,8 @@ config CAVIUM_OCTEON_REFERENCE_BOARD + select SYS_HAS_EARLY_PRINTK + select SYS_HAS_CPU_CAVIUM_OCTEON + select SWAP_IO_SPACE ++ select HW_HAS_PCI ++ select ARCH_SUPPORTS_MSI + help + This option supports all of the Octeon reference boards from Cavium + Networks. It builds a kernel that dynamically determines the Octeon +--- a/arch/mips/cavium-octeon/Makefile ++++ b/arch/mips/cavium-octeon/Makefile +@@ -14,5 +14,9 @@ obj-y += dma-octeon.o flash_setup.o + obj-y += octeon-memcpy.o + + obj-$(CONFIG_SMP) += smp.o ++obj-$(CONFIG_PCI) += pci-common.o ++obj-$(CONFIG_PCI) += pci.o ++obj-$(CONFIG_PCI) += pcie.o ++obj-$(CONFIG_PCI_MSI) += msi.o + + EXTRA_CFLAGS += -Werror +--- a/arch/mips/cavium-octeon/dma-octeon.c ++++ b/arch/mips/cavium-octeon/dma-octeon.c +@@ -13,20 +13,326 @@ + */ + #include + #include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include + + #include + ++#ifdef CONFIG_PCI ++#include "pci-common.h" ++#endif ++ ++#define BAR2_PCI_ADDRESS 0x8000000000ul ++ ++struct bar1_index_state { ++ int16_t ref_count; /* Number of PCI mappings using this index */ ++ uint16_t address_bits; /* Upper bits of physical address. This is ++ shifted 22 bits */ ++}; ++ ++#ifdef CONFIG_PCI ++static DEFINE_SPINLOCK(bar1_lock); ++static struct bar1_index_state bar1_state[32]; ++#endif ++ + dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) + { ++#ifndef CONFIG_PCI + /* Without PCI/PCIe this function can be called for Octeon internal + devices such as USB. These devices all support 64bit addressing */ + mb(); + return virt_to_phys(ptr); ++#else ++ unsigned long flags; ++ uint64_t dma_mask; ++ int64_t start_index; ++ dma_addr_t result = -1; ++ uint64_t physical = virt_to_phys(ptr); ++ int64_t index; ++ ++ mb(); ++ /* ++ * Use the DMA masks to determine the allowed memory ++ * region. For us it doesn't limit the actual memory, just the ++ * address visible over PCI. Devices with limits need to use ++ * lower indexed Bar1 entries. ++ */ ++ if (dev) { ++ dma_mask = dev->coherent_dma_mask; ++ if (dev->dma_mask) ++ dma_mask = *dev->dma_mask; ++ } else ++ dma_mask = 0xfffffffful; ++ ++ /* ++ * Platform devices, such as the internal USB, skip all ++ * translation and use Octeon physical addresses directly. ++ */ ++ if (dev->bus == &platform_bus_type) ++ return physical; ++ ++ switch (octeon_dma_bar_type) { ++ case OCTEON_DMA_BAR_TYPE_PCIE: ++ if (unlikely(physical < (16ul << 10))) ++ panic("dma_map_single: Not allowed to map first 16KB." ++ " It interferes with BAR0 special area\n"); ++ else if ((physical + size >= (256ul << 20)) && ++ (physical < (512ul << 20))) ++ panic("dma_map_single: Not allowed to map bootbus\n"); ++ else if ((physical + size >= 0x400000000ull) && ++ physical < 0x410000000ull) ++ panic("dma_map_single: " ++ "Attempt to map illegal memory address 0x%lx\n", ++ physical); ++ else if (physical >= 0x420000000ull) ++ panic("dma_map_single: " ++ "Attempt to map illegal memory address 0x%lx\n", ++ physical); ++ else if ((physical + size >= ++ (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20)) ++ && physical < (4ull<<30)) ++ pr_warning("dma_map_single: Warning: " ++ "Mapping memory address that might " ++ "conflict with devices 0x%lx-0x%lx\n", ++ physical, physical+size-1); ++ /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ ++ if ((physical >= 0x410000000ull) && physical < 0x420000000ull) ++ result = physical - 0x400000000ull; ++ else ++ result = physical; ++ if (((result+size-1) & dma_mask) != result+size-1) ++ panic("dma_map_single: Attempt to map address " ++ "0x%lx-0x%lx, which can't be accessed according " ++ "to the dma mask 0x%lx\n", ++ physical, physical+size-1, dma_mask); ++ goto done; ++ ++ case OCTEON_DMA_BAR_TYPE_BIG: ++#ifdef CONFIG_64BIT ++ /* If the device supports 64bit addressing, then use BAR2 */ ++ if (dma_mask > BAR2_PCI_ADDRESS) { ++ result = physical + BAR2_PCI_ADDRESS; ++ goto done; ++ } ++#endif ++ if (unlikely(physical < (4ul << 10))) { ++ panic("dma_map_single: Not allowed to map first 4KB. " ++ "It interferes with BAR0 special area\n"); ++ } else if (physical < (256ul << 20)) { ++ if (unlikely(physical + size > (256ul << 20))) ++ panic("dma_map_single: Requested memory spans " ++ "Bar0 0:256MB and bootbus\n"); ++ result = physical; ++ goto done; ++ } else if (unlikely(physical < (512ul << 20))) { ++ panic("dma_map_single: Not allowed to map bootbus\n"); ++ } else if (physical < (2ul << 30)) { ++ if (unlikely(physical + size > (2ul << 30))) ++ panic("dma_map_single: Requested memory spans " ++ "Bar0 512MB:2GB and BAR1\n"); ++ result = physical; ++ goto done; ++ } else if (physical < (2ul << 30) + (128 << 20)) { ++ /* Fall through */ ++ } else if (physical < ++ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) { ++ if (unlikely ++ (physical + size > ++ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20))) ++ panic("dma_map_single: Requested memory " ++ "extends past Bar1 (4GB-%luMB)\n", ++ OCTEON_PCI_BAR1_HOLE_SIZE); ++ result = physical; ++ goto done; ++ } else if ((physical >= 0x410000000ull) && ++ (physical < 0x420000000ull)) { ++ if (unlikely(physical + size > 0x420000000ull)) ++ panic("dma_map_single: Requested memory spans " ++ "non existant memory\n"); ++ /* BAR0 fixed mapping 256MB:512MB -> ++ * 16GB+256MB:16GB+512MB */ ++ result = physical - 0x400000000ull; ++ goto done; ++ } else { ++ /* Continued below switch statement */ ++ } ++ break; ++ ++ case OCTEON_DMA_BAR_TYPE_SMALL: ++#ifdef CONFIG_64BIT ++ /* If the device supports 64bit addressing, then use BAR2 */ ++ if (dma_mask > BAR2_PCI_ADDRESS) { ++ result = physical + BAR2_PCI_ADDRESS; ++ goto done; ++ } ++#endif ++ /* Continued below switch statement */ ++ break; ++ ++ default: ++ panic("dma_map_single: Invalid octeon_dma_bar_type\n"); ++ } ++ ++ /* Don't allow mapping to span multiple Bar entries. The hardware guys ++ won't guarantee that DMA across boards work */ ++ if (unlikely((physical >> 22) != ((physical + size - 1) >> 22))) ++ panic("dma_map_single: " ++ "Requested memory spans more than one Bar1 entry\n"); ++ ++ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) ++ start_index = 31; ++ else if (unlikely(dma_mask < (1ul << 27))) ++ start_index = (dma_mask >> 22); ++ else ++ start_index = 31; ++ ++ /* Only one processor can access the Bar register at once */ ++ spin_lock_irqsave(&bar1_lock, flags); ++ ++ /* Look through Bar1 for existing mapping that will work */ ++ for (index = start_index; index >= 0; index--) { ++ if ((bar1_state[index].address_bits == physical >> 22) && ++ (bar1_state[index].ref_count)) { ++ /* An existing mapping will work, use it */ ++ bar1_state[index].ref_count++; ++ if (unlikely(bar1_state[index].ref_count < 0)) ++ panic("dma_map_single: " ++ "Bar1[%d] reference count overflowed\n", ++ (int) index); ++ result = (index << 22) | (physical & ((1 << 22) - 1)); ++ /* Large BAR1 is offset at 2GB */ ++ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) ++ result += 2ul << 30; ++ goto done_unlock; ++ } ++ } ++ ++ /* No existing mappings, look for a free entry */ ++ for (index = start_index; index >= 0; index--) { ++ if (unlikely(bar1_state[index].ref_count == 0)) { ++ union cvmx_pci_bar1_indexx bar1_index; ++ /* We have a free entry, use it */ ++ bar1_state[index].ref_count = 1; ++ bar1_state[index].address_bits = physical >> 22; ++ bar1_index.u32 = 0; ++ /* Address bits[35:22] sent to L2C */ ++ bar1_index.s.addr_idx = physical >> 22; ++ /* Don't put PCI accesses in L2. */ ++ bar1_index.s.ca = 1; ++ /* Endian Swap Mode */ ++ bar1_index.s.end_swp = 1; ++ /* Set '1' when the selected address range is valid. */ ++ bar1_index.s.addr_v = 1; ++ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), ++ bar1_index.u32); ++ /* An existing mapping will work, use it */ ++ result = (index << 22) | (physical & ((1 << 22) - 1)); ++ /* Large BAR1 is offset at 2GB */ ++ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) ++ result += 2ul << 30; ++ goto done_unlock; ++ } ++ } ++ ++ pr_err("dma_map_single: " ++ "Can't find empty BAR1 index for physical mapping 0x%llx\n", ++ (unsigned long long) physical); ++ ++done_unlock: ++ spin_unlock_irqrestore(&bar1_lock, flags); ++done: ++ pr_debug("dma_map_single 0x%lx->0x%lx\n", physical, result); ++ return result; ++#endif + } + + void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr) + { +- /* Without PCI/PCIe this function can be called for Octeon internal +- * devices such as USB. These devices all support 64bit addressing */ ++#ifndef CONFIG_PCI ++ /* ++ * Without PCI/PCIe this function can be called for Octeon internal ++ * devices such as USB. These devices all support 64bit addressing. ++ */ ++ return; ++#else ++ unsigned long flags; ++ uint64_t index; ++ ++ /* ++ * Platform devices, such as the internal USB, skip all ++ * translation and use Octeon physical addresses directly. ++ */ ++ if (dev->bus == &platform_bus_type) ++ return; ++ ++ switch (octeon_dma_bar_type) { ++ case OCTEON_DMA_BAR_TYPE_PCIE: ++ /* Nothing to do, all mappings are static */ ++ goto done; ++ ++ case OCTEON_DMA_BAR_TYPE_BIG: ++#ifdef CONFIG_64BIT ++ /* Nothing to do for addresses using BAR2 */ ++ if (dma_addr >= BAR2_PCI_ADDRESS) ++ goto done; ++#endif ++ if (unlikely(dma_addr < (4ul << 10))) ++ panic("dma_unmap_single: Unexpect DMA address 0x%lx\n", ++ dma_addr); ++ else if (dma_addr < (2ul << 30)) ++ /* Nothing to do for addresses using BAR0 */ ++ goto done; ++ else if (dma_addr < (2ul << 30) + (128ul << 20)) ++ /* Need to unmap, fall through */ ++ index = (dma_addr - (2ul << 30)) >> 22; ++ else if (dma_addr < ++ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) ++ goto done; /* Nothing to do for the rest of BAR1 */ ++ else ++ panic("dma_unmap_single: Unexpect DMA address 0x%lx\n", ++ dma_addr); ++ /* Continued below switch statement */ ++ break; ++ ++ case OCTEON_DMA_BAR_TYPE_SMALL: ++#ifdef CONFIG_64BIT ++ /* Nothing to do for addresses using BAR2 */ ++ if (dma_addr >= BAR2_PCI_ADDRESS) ++ goto done; ++#endif ++ index = dma_addr >> 22; ++ /* Continued below switch statement */ ++ break; ++ ++ default: ++ panic("dma_unmap_single: Invalid octeon_dma_bar_type\n"); ++ } ++ ++ if (unlikely(index > 31)) ++ panic("dma_unmap_single: " ++ "Attempt to unmap an invalid address (0x%llx)\n", ++ (unsigned long long) dma_addr); ++ ++ spin_lock_irqsave(&bar1_lock, flags); ++ bar1_state[index].ref_count--; ++ if (bar1_state[index].ref_count == 0) ++ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); ++ else if (unlikely(bar1_state[index].ref_count < 0)) ++ panic("dma_unmap_single: Bar1[%u] reference count < 0\n", ++ (int) index); ++ spin_unlock_irqrestore(&bar1_lock, flags); ++done: ++ pr_debug("dma_unmap_single 0x%lx\n", dma_addr); + return; ++#endif + } +--- a/arch/mips/cavium-octeon/executive/Makefile ++++ b/arch/mips/cavium-octeon/executive/Makefile +@@ -11,3 +11,5 @@ + + obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o + ++obj-$(CONFIG_PCI) += cvmx-pcie.o ++obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-util.o +--- /dev/null ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c +@@ -0,0 +1,379 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Fixes and workaround for Octeon chip errata. This file ++ * contains functions called by cvmx-helper to workaround known ++ * chip errata. For the most part, code doesn't need to call ++ * these functions directly. ++ * ++ */ ++#include ++ ++#include ++ ++#ifdef CVMX_ENABLE_PKO_FUNCTIONS ++ ++/** ++ * @INTERNAL ++ * Function to adjust internal IPD pointer alignments ++ * ++ * Returns 0 on success ++ * !0 on failure ++ */ ++int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) ++{ ++#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \ ++ (CVMX_FPA_PACKET_POOL_SIZE - 8 - CVMX_HELPER_FIRST_MBUFF_SKIP) ++#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \ ++ (CVMX_FPA_PACKET_POOL_SIZE - 8 - CVMX_HELPER_NOT_FIRST_MBUFF_SKIP) ++#define FIX_IPD_OUTPORT 0 ++ /* Ports 0-15 are interface 0, 16-31 are interface 1 */ ++#define INTERFACE(port) (port >> 4) ++#define INDEX(port) (port & 0xf) ++ uint64_t *p64; ++ cvmx_pko_command_word0_t pko_command; ++ cvmx_buf_ptr_t g_buffer, pkt_buffer; ++ cvmx_wqe_t *work; ++ int size, num_segs = 0, wqe_pcnt, pkt_pcnt; ++ cvmx_gmxx_prtx_cfg_t gmx_cfg; ++ int retry_cnt; ++ int retry_loop_cnt; ++ int mtu; ++ int i; ++ cvmx_helper_link_info_t link_info; ++ ++ /* Save values for restore at end */ ++ uint64_t prtx_cfg = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t tx_ptr_en = ++ cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t rx_ptr_en = ++ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t rxx_jabber = ++ cvmx_read_csr(CVMX_GMXX_RXX_JABBER(INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t frame_max = ++ cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX(INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ ++ /* Configure port to gig FDX as required for loopback mode */ ++ cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT); ++ ++ /* ++ * Disable reception on all ports so if traffic is present it ++ * will not interfere. ++ */ ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0); ++ ++ cvmx_wait(100000000ull); ++ ++ for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) { ++ retry_cnt = 100000; ++ wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT); ++ pkt_pcnt = (wqe_pcnt >> 7) & 0x7f; ++ wqe_pcnt &= 0x7f; ++ ++ num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3; ++ ++ if (num_segs == 0) ++ goto fix_ipd_exit; ++ ++ num_segs += 1; ++ ++ size = ++ FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES + ++ ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) - ++ (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2); ++ ++ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), ++ 1 << INDEX(FIX_IPD_OUTPORT)); ++ CVMX_SYNC; ++ ++ g_buffer.u64 = 0; ++ g_buffer.s.addr = ++ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL)); ++ if (g_buffer.s.addr == 0) { ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT buffer " ++ "allocation failure.\n"); ++ goto fix_ipd_exit; ++ } ++ ++ g_buffer.s.pool = CVMX_FPA_WQE_POOL; ++ g_buffer.s.size = num_segs; ++ ++ pkt_buffer.u64 = 0; ++ pkt_buffer.s.addr = ++ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL)); ++ if (pkt_buffer.s.addr == 0) { ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT buffer " ++ "allocation failure.\n"); ++ goto fix_ipd_exit; ++ } ++ pkt_buffer.s.i = 1; ++ pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL; ++ pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES; ++ ++ p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr); ++ p64[0] = 0xffffffffffff0000ull; ++ p64[1] = 0x08004510ull; ++ p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull; ++ p64[3] = 0x3a5fc0a81073c0a8ull; ++ ++ for (i = 0; i < num_segs; i++) { ++ if (i > 0) ++ pkt_buffer.s.size = ++ FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES; ++ ++ if (i == (num_segs - 1)) ++ pkt_buffer.s.i = 0; ++ ++ *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr + ++ 8 * i) = pkt_buffer.u64; ++ } ++ ++ /* Build the PKO command */ ++ pko_command.u64 = 0; ++ pko_command.s.segs = num_segs; ++ pko_command.s.total_bytes = size; ++ pko_command.s.dontfree = 0; ++ pko_command.s.gather = 1; ++ ++ gmx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ 1 << INDEX(FIX_IPD_OUTPORT)); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ 1 << INDEX(FIX_IPD_OUTPORT)); ++ ++ mtu = ++ cvmx_read_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ cvmx_write_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); ++ ++#if CVMX_PKO_USE_FAU_FOR_OUTPUT_QUEUES ++ cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, ++ cvmx_pko_get_base_queue ++ (FIX_IPD_OUTPORT), ++ CVMX_PKO_LOCK_NONE); ++ cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, ++ cvmx_pko_get_base_queue ++ (FIX_IPD_OUTPORT), pko_command, ++ g_buffer, CVMX_PKO_LOCK_NONE); ++#else ++ cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, ++ cvmx_pko_get_base_queue ++ (FIX_IPD_OUTPORT), ++ CVMX_PKO_LOCK_CMD_QUEUE); ++ cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, ++ cvmx_pko_get_base_queue ++ (FIX_IPD_OUTPORT), pko_command, ++ g_buffer, CVMX_PKO_LOCK_CMD_QUEUE); ++#endif ++ CVMX_SYNC; ++ ++ do { ++ work = cvmx_pow_work_request_sync(CVMX_POW_WAIT); ++ retry_cnt--; ++ } while ((work == NULL) && (retry_cnt > 0)); ++ ++ if (!retry_cnt) ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " ++ "get_work() timeout occured.\n"); ++ ++ /* Free packet */ ++ if (work) ++ cvmx_helper_free_packet_data(work); ++ } ++ ++fix_ipd_exit: ++ ++ /* Return CSR configs to saved values */ ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), ++ prtx_cfg); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ tx_ptr_en); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ rx_ptr_en); ++ cvmx_write_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), ++ rxx_jabber); ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), ++ frame_max); ++ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0); ++ /* Set link to down so autonegotiation will set it up again */ ++ link_info.u64 = 0; ++ cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info); ++ ++ /* ++ * Bring the link back up as autonegotiation is not done in ++ * user applications. ++ */ ++ cvmx_helper_link_autoconf(FIX_IPD_OUTPORT); ++ ++ CVMX_SYNC; ++ if (num_segs) ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n"); ++ ++ return !!num_segs; ++ ++} ++ ++/** ++ * @INTERNAL ++ * Workaround ASX setup errata with CN38XX pass1 ++ * ++ * @interface: Interface to setup ++ * @port: Port to setup (0..3) ++ * @cpu_clock_hz: ++ * Chip frequency in Hertz ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_errata_asx_pass1(int interface, int port, int cpu_clock_hz) ++{ ++ /* Set hi water mark as per errata GMX-4 */ ++ if (cpu_clock_hz >= 325000000 && cpu_clock_hz < 375000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 12); ++ else if (cpu_clock_hz >= 375000000 && cpu_clock_hz < 437000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 11); ++ else if (cpu_clock_hz >= 437000000 && cpu_clock_hz < 550000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 10); ++ else if (cpu_clock_hz >= 550000000 && cpu_clock_hz < 687000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 9); ++ else ++ cvmx_dprintf("Illegal clock frequency (%d). " ++ "CVMX_ASXX_TX_HI_WATERX not set\n", ++ cpu_clock_hz); ++ return 0; ++} ++ ++/** ++ * This function needs to be called on all Octeon chips with ++ * errata PKI-100. ++ * ++ * The Size field is 8 too large in WQE and next pointers ++ * ++ * The Size field generated by IPD is 8 larger than it should ++ * be. The Size field is <55:40> of both: ++ * - WORD3 in the work queue entry, and ++ * - the next buffer pointer (which precedes the packet data ++ * in each buffer). ++ * ++ * @work: Work queue entry to fix ++ * Returns Zero on success. Negative on failure ++ */ ++int cvmx_helper_fix_ipd_packet_chain(cvmx_wqe_t *work) ++{ ++ uint64_t number_buffers = work->word2.s.bufs; ++ ++ /* We only need to do this if the work has buffers */ ++ if (number_buffers) { ++ cvmx_buf_ptr_t buffer_ptr = work->packet_ptr; ++ /* Check for errata PKI-100 */ ++ if ((buffer_ptr.s.pool == 0) && ++ (((uint64_t) buffer_ptr.s.size + ++ ((uint64_t) buffer_ptr.s.back << 7) + ++ ((uint64_t) buffer_ptr.s.addr & 0x7F)) != ++ (CVMX_FPA_PACKET_POOL_SIZE + 8))) { ++ /* fix is not needed */ ++ return 0; ++ } ++ /* Decrement the work packet pointer */ ++ buffer_ptr.s.size -= 8; ++ work->packet_ptr = buffer_ptr; ++ ++ /* ++ * Now loop through decrementing the size for each ++ * additional buffer. ++ */ ++ while (--number_buffers) { ++ /* Chain pointers are 8 bytes before the data */ ++ cvmx_buf_ptr_t *ptr = ++ (cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); ++ buffer_ptr = *ptr; ++ buffer_ptr.s.size -= 8; ++ *ptr = buffer_ptr; ++ } ++ } ++ /* ++ * Make sure that these write go out before other operations ++ * such as FPA frees. ++ */ ++ CVMX_SYNCWS; ++ return 0; ++} ++ ++#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ ++ ++/** ++ * Due to errata G-720, the 2nd order CDR circuit on CN52XX pass ++ * 1 doesn't work properly. The following code disables 2nd order ++ * CDR for the specified QLM. ++ * ++ * @qlm: QLM to disable 2nd order CDR for. ++ */ ++void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm) ++{ ++ int lane; ++ cvmx_helper_qlm_jtag_init(); ++ /* We need to load all four lanes of the QLM, a total of 1072 bits */ ++ for (lane = 0; lane < 4; lane++) { ++ /* ++ * Each lane has 268 bits. We need to set ++ * cfg_cdr_incx<67:64> = 3 and cfg_cdr_secord<77> = ++ * 1. All other bits are zero. Bits go in LSB first, ++ * so start off with the zeros for bits <63:0>. ++ */ ++ cvmx_helper_qlm_jtag_shift_zeros(qlm, 63 - 0 + 1); ++ /* cfg_cdr_incx<67:64>=3 */ ++ cvmx_helper_qlm_jtag_shift(qlm, 67 - 64 + 1, 3); ++ /* Zeros for bits <76:68> */ ++ cvmx_helper_qlm_jtag_shift_zeros(qlm, 76 - 68 + 1); ++ /* cfg_cdr_secord<77>=1 */ ++ cvmx_helper_qlm_jtag_shift(qlm, 77 - 77 + 1, 1); ++ /* Zeros for bits <267:78> */ ++ cvmx_helper_qlm_jtag_shift_zeros(qlm, 267 - 78 + 1); ++ } ++ cvmx_helper_qlm_jtag_update(qlm); ++} +--- /dev/null ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c +@@ -0,0 +1,502 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Small helper utilities. ++ * ++ */ ++ ++#include ++ ++#include ++ ++#ifdef CVMX_ENABLE_HELPER_FUNCTIONS ++ ++/** ++ * Get the version of the CVMX libraries. ++ * ++ * Returns Version string. Note this buffer is allocated statically ++ * and will be shared by all callers. ++ */ ++const char *cvmx_helper_get_version(void) ++{ ++ return OCTEON_SDK_VERSION_STRING; ++} ++ ++/** ++ * Convert a interface mode into a human readable string ++ * ++ * @mode: Mode to convert ++ * ++ * Returns String ++ */ ++const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t ++ mode) ++{ ++ switch (mode) { ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ return "DISABLED"; ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ return "RGMII"; ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ return "GMII"; ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ return "SPI"; ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ return "PCIE"; ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ return "XAUI"; ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ return "SGMII"; ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ return "PICMG"; ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ return "NPI"; ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ return "LOOP"; ++ } ++ return "UNKNOWN"; ++} ++ ++/** ++ * Debug routine to dump the packet structure to the console ++ * ++ * @work: Work queue entry containing the packet to dump ++ */ ++int cvmx_helper_dump_packet(cvmx_wqe_t *work) ++{ ++ uint64_t count; ++ uint64_t remaining_bytes; ++ cvmx_buf_ptr_t buffer_ptr; ++ uint64_t start_of_buffer; ++ uint8_t *data_address; ++ uint8_t *end_of_data; ++ ++ cvmx_dprintf("Packet Length: %u\n", work->len); ++ cvmx_dprintf(" Input Port: %u\n", work->ipprt); ++ cvmx_dprintf(" QoS: %u\n", work->qos); ++ cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs); ++ ++ if (work->word2.s.bufs == 0) { ++ cvmx_ipd_wqe_fpa_queue_t wqe_pool; ++ wqe_pool.u64 = cvmx_read_csr(CVMX_IPD_WQE_FPA_QUEUE); ++ buffer_ptr.u64 = 0; ++ buffer_ptr.s.pool = wqe_pool.s.wqe_pool; ++ buffer_ptr.s.size = 128; ++ buffer_ptr.s.addr = cvmx_ptr_to_phys(work->packet_data); ++ if (cvmx_likely(!work->word2.s.not_IP)) { ++ if (work->word2.s.is_v6) ++ buffer_ptr.s.addr += 2; ++ else ++ buffer_ptr.s.addr += 6; ++ } ++ } else ++ buffer_ptr = work->packet_ptr; ++ remaining_bytes = work->len; ++ ++ while (remaining_bytes) { ++ start_of_buffer = ++ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; ++ cvmx_dprintf(" Buffer Start:%llx\n", ++ (unsigned long long)start_of_buffer); ++ cvmx_dprintf(" Buffer I : %u\n", buffer_ptr.s.i); ++ cvmx_dprintf(" Buffer Back: %u\n", buffer_ptr.s.back); ++ cvmx_dprintf(" Buffer Pool: %u\n", buffer_ptr.s.pool); ++ cvmx_dprintf(" Buffer Data: %llx\n", ++ (unsigned long long)buffer_ptr.s.addr); ++ cvmx_dprintf(" Buffer Size: %u\n", buffer_ptr.s.size); ++ ++ cvmx_dprintf("\t\t"); ++ data_address = (uint8_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr); ++ end_of_data = data_address + buffer_ptr.s.size; ++ count = 0; ++ while (data_address < end_of_data) { ++ if (remaining_bytes == 0) ++ break; ++ else ++ remaining_bytes--; ++ cvmx_dprintf("%02x", (unsigned int)*data_address); ++ data_address++; ++ if (remaining_bytes && (count == 7)) { ++ cvmx_dprintf("\n\t\t"); ++ count = 0; ++ } else ++ count++; ++ } ++ cvmx_dprintf("\n"); ++ ++ if (remaining_bytes) ++ buffer_ptr = ++ *(cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s. ++ addr - 8); ++ } ++ return 0; ++} ++ ++/** ++ * Setup Random Early Drop on a specific input queue ++ * ++ * @queue: Input queue to setup RED on (0-7) ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh) ++{ ++ cvmx_ipd_qos_red_marks_t red_marks; ++ cvmx_ipd_red_quex_param_t red_param; ++ ++ /* ++ * Set RED to begin dropping packets when there are ++ * pass_thresh buffers left. It will linearly drop more ++ * packets until reaching drop_thresh buffers. ++ */ ++ red_marks.u64 = 0; ++ red_marks.s.drop = drop_thresh; ++ red_marks.s.pass = pass_thresh; ++ cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64); ++ ++ /* Use the actual queue 0 counter, not the average */ ++ red_param.u64 = 0; ++ red_param.s.prb_con = ++ (255ul << 24) / (red_marks.s.pass - red_marks.s.drop); ++ red_param.s.avg_con = 1; ++ red_param.s.new_con = 255; ++ red_param.s.use_pcnt = 1; ++ cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64); ++ return 0; ++} ++ ++/** ++ * Setup Random Early Drop to automatically begin dropping packets. ++ * ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) ++{ ++ cvmx_ipd_portx_bp_page_cnt_t page_cnt; ++ cvmx_ipd_bp_prt_red_end_t ipd_bp_prt_red_end; ++ cvmx_ipd_red_port_enable_t red_port_enable; ++ int queue; ++ int interface; ++ int port; ++ ++ /* Disable backpressure based on queued buffers. It needs SW support */ ++ page_cnt.u64 = 0; ++ page_cnt.s.bp_enb = 0; ++ page_cnt.s.page_cnt = 100; ++ for (interface = 0; interface < 2; interface++) { ++ for (port = cvmx_helper_get_first_ipd_port(interface); ++ port < cvmx_helper_get_last_ipd_port(interface); port++) ++ cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), ++ page_cnt.u64); ++ } ++ ++ for (queue = 0; queue < 8; queue++) ++ cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh); ++ ++ /* Shutoff the dropping based on the per port page count. SW isn't ++ decrementing it right now */ ++ ipd_bp_prt_red_end.u64 = 0; ++ ipd_bp_prt_red_end.s.prt_enb = 0; ++ cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64); ++ ++ red_port_enable.u64 = 0; ++ red_port_enable.s.prt_enb = 0xfffffffffull; ++ red_port_enable.s.avg_dly = 10000; ++ red_port_enable.s.prb_dly = 10000; ++ cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64); ++ ++ return 0; ++} ++ ++/** ++ * Setup the common GMX settings that determine the number of ++ * ports. These setting apply to almost all configurations of all ++ * chips. ++ * ++ * @interface: Interface to configure ++ * @num_ports: Number of ports on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_setup_gmx(int interface, int num_ports) ++{ ++ cvmx_gmxx_tx_prts_t gmx_tx_prts; ++ cvmx_gmxx_rx_prts_t gmx_rx_prts; ++ cvmx_pko_reg_gmx_port_mode_t pko_mode; ++ ++ /* Tell GMX the number of TX ports on this interface */ ++ gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface)); ++ gmx_tx_prts.s.prts = num_ports; ++ cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64); ++ ++ /* ++ * Tell GMX the number of RX ports on this interface. This only ++ * applies to *GMII and XAUI ports. ++ */ ++ if (cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_RGMII ++ || cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_SGMII ++ || cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_GMII ++ || cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_XAUI) { ++ if (num_ports > 4) { ++ cvmx_dprintf("__cvmx_helper_setup_gmx: " ++ "Illegal num_ports\n"); ++ return -1; ++ } ++ ++ gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface)); ++ gmx_rx_prts.s.prts = num_ports; ++ cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64); ++ } ++ ++ /* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX and 31XX */ ++ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)) ++ return 0; ++ ++ /* Tell PKO the number of ports on this interface */ ++ pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE); ++ if (interface == 0) { ++ if (num_ports == 1) ++ pko_mode.s.mode0 = 4; ++ else if (num_ports == 2) ++ pko_mode.s.mode0 = 3; ++ else if (num_ports <= 4) ++ pko_mode.s.mode0 = 2; ++ else if (num_ports <= 8) ++ pko_mode.s.mode0 = 1; ++ else ++ pko_mode.s.mode0 = 0; ++ } else { ++ if (num_ports == 1) ++ pko_mode.s.mode1 = 4; ++ else if (num_ports == 2) ++ pko_mode.s.mode1 = 3; ++ else if (num_ports <= 4) ++ pko_mode.s.mode1 = 2; ++ else if (num_ports <= 8) ++ pko_mode.s.mode1 = 1; ++ else ++ pko_mode.s.mode1 = 0; ++ } ++ cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64); ++ return 0; ++} ++ ++/** ++ * Returns the IPD/PKO port number for a port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * @port: Port on the interface ++ * ++ * Returns IPD/PKO port number ++ */ ++int cvmx_helper_get_ipd_port(int interface, int port) ++{ ++ switch (interface) { ++ case 0: ++ return port; ++ case 1: ++ return port + 16; ++ case 2: ++ return port + 32; ++ case 3: ++ return port + 36; ++ } ++ return -1; ++} ++ ++#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ ++ ++/** ++ * Returns the interface number for an IPD/PKO port number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface number ++ */ ++int cvmx_helper_get_interface_num(int ipd_port) ++{ ++ if (ipd_port < 16) ++ return 0; ++ else if (ipd_port < 32) ++ return 1; ++ else if (ipd_port < 36) ++ return 2; ++ else if (ipd_port < 40) ++ return 3; ++ else ++ cvmx_dprintf("cvmx_helper_get_interface_num: " ++ "Illegal IPD port number\n"); ++ ++ return -1; ++} ++ ++/** ++ * Returns the interface index number for an IPD/PKO port ++ * number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface index number ++ */ ++int cvmx_helper_get_interface_index_num(int ipd_port) ++{ ++ if (ipd_port < 32) ++ return ipd_port & 15; ++ else if (ipd_port < 36) ++ return ipd_port & 3; ++ else if (ipd_port < 40) ++ return ipd_port & 3; ++ else ++ cvmx_dprintf("cvmx_helper_get_interface_index_num: " ++ "Illegal IPD port number\n"); ++ ++ return -1; ++} ++ ++/** ++ * Initialize the internal QLM JTAG logic to allow programming ++ * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions. ++ * These functions should only be used at the direction of Cavium ++ * Networks. Programming incorrect values into the JTAG chain ++ * can cause chip damage. ++ */ ++void cvmx_helper_qlm_jtag_init(void) ++{ ++ union cvmx_ciu_qlm_jtgc jtgc; ++ int clock_div = 0; ++ int divisor = cvmx_sysinfo_get()->cpu_clock_hz / (25 * 1000000); ++ divisor = (divisor - 1) >> 2; ++ /* Convert the divisor into a power of 2 shift */ ++ CVMX_CLZ(clock_div, divisor); ++ clock_div = 32 - clock_div; ++ ++ /* ++ * Clock divider for QLM JTAG operations. eclk is divided by ++ * 2^(CLK_DIV + 2). ++ */ ++ jtgc.u64 = 0; ++ jtgc.s.clk_div = clock_div; ++ jtgc.s.mux_sel = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ jtgc.s.bypass = 0x3; ++ else ++ jtgc.s.bypass = 0xf; ++ cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); ++ cvmx_read_csr(CVMX_CIU_QLM_JTGC); ++} ++ ++/** ++ * Write up to 32bits into the QLM jtag chain. Bits are shifted ++ * into the MSB and out the LSB, so you should shift in the low ++ * order bits followed by the high order bits. The JTAG chain is ++ * 4 * 268 bits long, or 1072. ++ * ++ * @qlm: QLM to shift value into ++ * @bits: Number of bits to shift in (1-32). ++ * @data: Data to shift in. Bit 0 enters the chain first, followed by ++ * bit 1, etc. ++ * ++ * Returns The low order bits of the JTAG chain that shifted out of the ++ * circle. ++ */ ++uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data) ++{ ++ union cvmx_ciu_qlm_jtgd jtgd; ++ jtgd.u64 = 0; ++ jtgd.s.shift = 1; ++ jtgd.s.shft_cnt = bits - 1; ++ jtgd.s.shft_reg = data; ++ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ++ jtgd.s.select = 1 << qlm; ++ cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); ++ do { ++ jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); ++ } while (jtgd.s.shift); ++ return jtgd.s.shft_reg >> (32 - bits); ++} ++ ++/** ++ * Shift long sequences of zeros into the QLM JTAG chain. It is ++ * common to need to shift more than 32 bits of zeros into the ++ * chain. This function is a convience wrapper around ++ * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of ++ * zeros at a time. ++ * ++ * @qlm: QLM to shift zeros into ++ * @bits: ++ */ ++void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits) ++{ ++ while (bits > 0) { ++ int n = bits; ++ if (n > 32) ++ n = 32; ++ cvmx_helper_qlm_jtag_shift(qlm, n, 0); ++ bits -= n; ++ } ++} ++ ++/** ++ * Program the QLM JTAG chain into all lanes of the QLM. You must ++ * have already shifted in 268*4, or 1072 bits into the JTAG ++ * chain. Updating invalid values can possibly cause chip damage. ++ * ++ * @qlm: QLM to program ++ */ ++void cvmx_helper_qlm_jtag_update(int qlm) ++{ ++ union cvmx_ciu_qlm_jtgd jtgd; ++ ++ /* Update the new data */ ++ jtgd.u64 = 0; ++ jtgd.s.update = 1; ++ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ++ jtgd.s.select = 1 << qlm; ++ cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); ++ do { ++ jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); ++ } while (jtgd.s.update); ++} +--- /dev/null ++++ b/arch/mips/cavium-octeon/executive/cvmx-pcie.c +@@ -0,0 +1,1053 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Interface to PCIe as a host(RC) or target(EP) ++ * ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * Return the Core virtual base address for PCIe IO access. IOs are ++ * read/written as an offset from this address. ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns 64bit Octeon IO base address for read/write ++ */ ++uint64_t cvmx_pcie_get_io_base_address(int pcie_port) ++{ ++ union cvmx_pcie_address pcie_addr; ++ pcie_addr.u64 = 0; ++ pcie_addr.io.upper = 0; ++ pcie_addr.io.io = 1; ++ pcie_addr.io.did = 3; ++ pcie_addr.io.subdid = 2; ++ pcie_addr.io.es = 1; ++ pcie_addr.io.port = pcie_port; ++ return pcie_addr.u64; ++} ++ ++/** ++ * Size of the IO address region returned at address ++ * cvmx_pcie_get_io_base_address() ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns Size of the IO window ++ */ ++uint64_t cvmx_pcie_get_io_size(int pcie_port) ++{ ++ return 1ull << 32; ++} ++ ++/** ++ * Return the Core virtual base address for PCIe MEM access. Memory is ++ * read/written as an offset from this address. ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns 64bit Octeon IO base address for read/write ++ */ ++uint64_t cvmx_pcie_get_mem_base_address(int pcie_port) ++{ ++ union cvmx_pcie_address pcie_addr; ++ pcie_addr.u64 = 0; ++ pcie_addr.mem.upper = 0; ++ pcie_addr.mem.io = 1; ++ pcie_addr.mem.did = 3; ++ pcie_addr.mem.subdid = 3 + pcie_port; ++ return pcie_addr.u64; ++} ++ ++/** ++ * Size of the Mem address region returned at address ++ * cvmx_pcie_get_mem_base_address() ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns Size of the Mem window ++ */ ++uint64_t cvmx_pcie_get_mem_size(int pcie_port) ++{ ++ return 1ull << 36; ++} ++ ++/** ++ * Initialize the RC config space CSRs ++ * ++ * @pcie_port: PCIe port to initialize ++ */ ++static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) ++{ ++ union cvmx_pciercx_cfg030 pciercx_cfg030; ++ union cvmx_npei_ctl_status2 npei_ctl_status2; ++ union cvmx_pciercx_cfg070 pciercx_cfg070; ++ union cvmx_pciercx_cfg001 pciercx_cfg001; ++ union cvmx_pciercx_cfg032 pciercx_cfg032; ++ union cvmx_pciercx_cfg006 pciercx_cfg006; ++ union cvmx_pciercx_cfg008 pciercx_cfg008; ++ union cvmx_pciercx_cfg009 pciercx_cfg009; ++ union cvmx_pciercx_cfg010 pciercx_cfg010; ++ union cvmx_pciercx_cfg011 pciercx_cfg011; ++ union cvmx_pciercx_cfg035 pciercx_cfg035; ++ union cvmx_pciercx_cfg075 pciercx_cfg075; ++ union cvmx_pciercx_cfg034 pciercx_cfg034; ++ ++ /* Max Payload Size (PCIE*_CFG030[MPS]) */ ++ /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ ++ /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ ++ /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ ++ pciercx_cfg030.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); ++ /* ++ * Max payload size = 128 bytes for best Octeon DMA ++ * performance. ++ */ ++ pciercx_cfg030.s.mps = 0; ++ /* ++ * Max read request size = 128 bytes for best Octeon DMA ++ * performance. ++ */ ++ pciercx_cfg030.s.mrrs = 0; ++ /* Enable relaxed ordering. */ ++ pciercx_cfg030.s.ro_en = 1; ++ /* Enable no snoop. */ ++ pciercx_cfg030.s.ns_en = 1; ++ /* Correctable error reporting enable. */ ++ pciercx_cfg030.s.ce_en = 1; ++ /* Non-fatal error reporting enable. */ ++ pciercx_cfg030.s.nfe_en = 1; ++ /* Fatal error reporting enable. */ ++ pciercx_cfg030.s.fe_en = 1; ++ /* Unsupported request reporting enable. */ ++ pciercx_cfg030.s.ur_en = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), ++ pciercx_cfg030.u32); ++ ++ /* ++ * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match ++ * PCIE*_CFG030[MPS] ++ * ++ * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not ++ * exceed PCIE*_CFG030[MRRS]. ++ */ ++ npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); ++ /* Max payload size = 128 bytes for best Octeon DMA performance */ ++ npei_ctl_status2.s.mps = 0; ++ /* Max read request size = 128 bytes for best Octeon DMA performance */ ++ npei_ctl_status2.s.mrrs = 0; ++ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); ++ ++ /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ ++ pciercx_cfg070.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); ++ pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ ++ pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), ++ pciercx_cfg070.u32); ++ ++ /* ++ * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should ++ * always be set. ++ * ++ * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error ++ * Message Enable (PCIE*_CFG001[SEE]) ++ */ ++ pciercx_cfg001.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); ++ pciercx_cfg001.s.msae = 1; /* Memory space enable. */ ++ pciercx_cfg001.s.me = 1; /* Bus master enable. */ ++ pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ ++ pciercx_cfg001.s.see = 1; /* SERR# enable */ ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), ++ pciercx_cfg001.u32); ++ ++ /* Advanced Error Recovery Message Enables */ ++ /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0); ++ /* Use CVMX_PCIERCX_CFG067 hardware default */ ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); ++ ++ /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ ++ pciercx_cfg032.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); ++ pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), ++ pciercx_cfg032.u32); ++ ++ /* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */ ++ ++ /* ++ * Link Width Mode (PCIERCn_CFG452[LME]) - Set during ++ * cvmx_pcie_rc_initialize_link() ++ * ++ * Primary Bus Number (PCIERCn_CFG006[PBNUM]) ++ * ++ * We set the primary bus number to 1 so IDT bridges are ++ * happy. They don't like zero. ++ */ ++ pciercx_cfg006.u32 = 0; ++ pciercx_cfg006.s.pbnum = 1; ++ pciercx_cfg006.s.sbnum = 1; ++ pciercx_cfg006.s.subbnum = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), ++ pciercx_cfg006.u32); ++ ++ /* ++ * Memory-mapped I/O BAR (PCIERCn_CFG008) ++ * Most applications should disable the memory-mapped I/O BAR by ++ * setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR] ++ */ ++ pciercx_cfg008.u32 = 0; ++ pciercx_cfg008.s.mb_addr = 0x100; ++ pciercx_cfg008.s.ml_addr = 0; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), ++ pciercx_cfg008.u32); ++ ++ /* ++ * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) ++ * Most applications should disable the prefetchable BAR by setting ++ * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < ++ * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] ++ */ ++ pciercx_cfg009.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); ++ pciercx_cfg010.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); ++ pciercx_cfg011.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); ++ pciercx_cfg009.s.lmem_base = 0x100; ++ pciercx_cfg009.s.lmem_limit = 0; ++ pciercx_cfg010.s.umem_base = 0x100; ++ pciercx_cfg011.s.umem_limit = 0; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), ++ pciercx_cfg009.u32); ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), ++ pciercx_cfg010.u32); ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), ++ pciercx_cfg011.u32); ++ ++ /* ++ * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) ++ * PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) ++ */ ++ pciercx_cfg035.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); ++ /* System error on correctable error enable. */ ++ pciercx_cfg035.s.secee = 1; ++ /* System error on fatal error enable. */ ++ pciercx_cfg035.s.sefee = 1; ++ /* System error on non-fatal error enable. */ ++ pciercx_cfg035.s.senfee = 1; ++ /* PME interrupt enable. */ ++ pciercx_cfg035.s.pmeie = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), ++ pciercx_cfg035.u32); ++ ++ /* ++ * Advanced Error Recovery Interrupt Enables ++ * (PCIERCn_CFG075[CERE,NFERE,FERE]) ++ */ ++ pciercx_cfg075.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); ++ /* Correctable error reporting enable. */ ++ pciercx_cfg075.s.cere = 1; ++ /* Non-fatal error reporting enable. */ ++ pciercx_cfg075.s.nfere = 1; ++ /* Fatal error reporting enable. */ ++ pciercx_cfg075.s.fere = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), ++ pciercx_cfg075.u32); ++ ++ /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], ++ * PCIERCn_CFG034[DLLS_EN,CCINT_EN]) ++ */ ++ pciercx_cfg034.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); ++ /* Hot-plug interrupt enable. */ ++ pciercx_cfg034.s.hpint_en = 1; ++ /* Data Link Layer state changed enable */ ++ pciercx_cfg034.s.dlls_en = 1; ++ /* Command completed interrupt enable. */ ++ pciercx_cfg034.s.ccint_en = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), ++ pciercx_cfg034.u32); ++} ++ ++/** ++ * Initialize a host mode PCIe link. This function takes a PCIe ++ * port from reset to a link up state. Software can then begin ++ * configuring the rest of the link. ++ * ++ * @pcie_port: PCIe port to initialize ++ * ++ * Returns Zero on success ++ */ ++static int __cvmx_pcie_rc_initialize_link(int pcie_port) ++{ ++ uint64_t start_cycle; ++ union cvmx_pescx_ctl_status pescx_ctl_status; ++ union cvmx_pciercx_cfg452 pciercx_cfg452; ++ union cvmx_pciercx_cfg032 pciercx_cfg032; ++ union cvmx_pciercx_cfg448 pciercx_cfg448; ++ ++ /* Set the lane width */ ++ pciercx_cfg452.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); ++ pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); ++ if (pescx_ctl_status.s.qlm_cfg == 0) { ++ /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ ++ pciercx_cfg452.s.lme = 0xf; ++ } else { ++ /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ ++ pciercx_cfg452.s.lme = 0x7; ++ } ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), ++ pciercx_cfg452.u32); ++ ++ /* ++ * CN52XX pass 1.x has an errata where length mismatches on UR ++ * responses can cause bus errors on 64bit memory ++ * reads. Turning off length error checking fixes this. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { ++ union cvmx_pciercx_cfg455 pciercx_cfg455; ++ pciercx_cfg455.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, ++ CVMX_PCIERCX_CFG455(pcie_port)); ++ pciercx_cfg455.s.m_cpl_len_err = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), ++ pciercx_cfg455.u32); ++ } ++ ++ /* Lane swap needs to be manually enabled for CN52XX */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) { ++ pescx_ctl_status.s.lane_swp = 1; ++ cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), ++ pescx_ctl_status.u64); ++ } ++ ++ /* Bring up the link */ ++ pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); ++ pescx_ctl_status.s.lnk_enb = 1; ++ cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); ++ ++ /* ++ * CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to ++ * be disabled. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) ++ __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); ++ ++ /* Wait for the link to come up */ ++ cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port); ++ start_cycle = cvmx_get_cycle(); ++ do { ++ if (cvmx_get_cycle() - start_cycle > ++ 2 * cvmx_sysinfo_get()->cpu_clock_hz) { ++ cvmx_dprintf("PCIe: Port %d link timeout\n", ++ pcie_port); ++ return -1; ++ } ++ cvmx_wait(10000); ++ pciercx_cfg032.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, ++ CVMX_PCIERCX_CFG032(pcie_port)); ++ } while (pciercx_cfg032.s.dlla == 0); ++ ++ /* Display the link status */ ++ cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, ++ pciercx_cfg032.s.nlw); ++ ++ /* ++ * Update the Replay Time Limit. Empirically, some PCIe ++ * devices take a little longer to respond than expected under ++ * load. As a workaround for this we configure the Replay Time ++ * Limit to the value expected for a 512 byte MPS instead of ++ * our actual 256 byte MPS. The numbers below are directly ++ * from the PCIe spec table 3-4. ++ */ ++ pciercx_cfg448.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); ++ switch (pciercx_cfg032.s.nlw) { ++ case 1: /* 1 lane */ ++ pciercx_cfg448.s.rtl = 1677; ++ break; ++ case 2: /* 2 lanes */ ++ pciercx_cfg448.s.rtl = 867; ++ break; ++ case 4: /* 4 lanes */ ++ pciercx_cfg448.s.rtl = 462; ++ break; ++ case 8: /* 8 lanes */ ++ pciercx_cfg448.s.rtl = 258; ++ break; ++ } ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), ++ pciercx_cfg448.u32); ++ ++ return 0; ++} ++ ++/** ++ * Initialize a PCIe port for use in host(RC) mode. It doesn't ++ * enumerate the bus. ++ * ++ * @pcie_port: PCIe port to initialize ++ * ++ * Returns Zero on success ++ */ ++int cvmx_pcie_rc_initialize(int pcie_port) ++{ ++ int i; ++ union cvmx_ciu_soft_prst ciu_soft_prst; ++ union cvmx_pescx_bist_status pescx_bist_status; ++ union cvmx_pescx_bist_status2 pescx_bist_status2; ++ union cvmx_npei_ctl_status npei_ctl_status; ++ union cvmx_npei_mem_access_ctl npei_mem_access_ctl; ++ union cvmx_npei_mem_access_subidx mem_access_subid; ++ union cvmx_npei_dbg_data npei_dbg_data; ++ union cvmx_pescx_ctl_status2 pescx_ctl_status2; ++ ++ /* ++ * Make sure we aren't trying to setup a target mode interface ++ * in host mode. ++ */ ++ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); ++ if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) { ++ cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called " ++ "on port0, but port0 is not in host mode\n"); ++ return -1; ++ } ++ ++ /* ++ * Make sure a CN52XX isn't trying to bring up port 1 when it ++ * is disabled. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); ++ if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) { ++ cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() " ++ "called on port1, but port1 is disabled\n"); ++ return -1; ++ } ++ } ++ ++ /* ++ * PCIe switch arbitration mode. '0' == fixed priority NPEI, ++ * PCIe0, then PCIe1. '1' == round robin. ++ */ ++ npei_ctl_status.s.arb = 1; ++ /* Allow up to 0x20 config retries */ ++ npei_ctl_status.s.cfg_rtry = 0x20; ++ /* ++ * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS ++ * don't reset. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { ++ npei_ctl_status.s.p0_ntags = 0x20; ++ npei_ctl_status.s.p1_ntags = 0x20; ++ } ++ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); ++ ++ /* Bring the PCIe out of reset */ ++ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) { ++ /* ++ * The EBH5200 board swapped the PCIe reset lines on ++ * the board. As a workaround for this bug, we bring ++ * both PCIe ports out of reset at the same time ++ * instead of on separate calls. So for port 0, we ++ * bring both out of reset and do nothing on port 1. ++ */ ++ if (pcie_port == 0) { ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ /* ++ * After a chip reset the PCIe will also be in ++ * reset. If it isn't, most likely someone is ++ * trying to init it again without a proper ++ * PCIe reset. ++ */ ++ if (ciu_soft_prst.s.soft_prst == 0) { ++ /* Reset the ports */ ++ ciu_soft_prst.s.soft_prst = 1; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ++ ciu_soft_prst.u64); ++ ciu_soft_prst.u64 = ++ cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ++ ciu_soft_prst.s.soft_prst = 1; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ++ ciu_soft_prst.u64); ++ /* Wait until pcie resets the ports. */ ++ udelay(2000); ++ } ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ++ ciu_soft_prst.s.soft_prst = 0; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ ciu_soft_prst.s.soft_prst = 0; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); ++ } ++ } else { ++ /* ++ * The normal case: The PCIe ports are completely ++ * separate and can be brought out of reset ++ * independently. ++ */ ++ if (pcie_port) ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ++ else ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ /* ++ * After a chip reset the PCIe will also be in ++ * reset. If it isn't, most likely someone is trying ++ * to init it again without a proper PCIe reset. ++ */ ++ if (ciu_soft_prst.s.soft_prst == 0) { ++ /* Reset the port */ ++ ciu_soft_prst.s.soft_prst = 1; ++ if (pcie_port) ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ++ ciu_soft_prst.u64); ++ else ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ++ ciu_soft_prst.u64); ++ /* Wait until pcie resets the ports. */ ++ udelay(2000); ++ } ++ if (pcie_port) { ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ++ ciu_soft_prst.s.soft_prst = 0; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); ++ } else { ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ ciu_soft_prst.s.soft_prst = 0; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); ++ } ++ } ++ ++ /* ++ * Wait for PCIe reset to complete. Due to errata PCIE-700, we ++ * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a ++ * fixed number of cycles. ++ */ ++ cvmx_wait(400000); ++ ++ /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and ++ CN52XX, so we only probe it on newer chips */ ++ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) ++ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { ++ /* Clear PCLK_RUN so we can check if the clock is running */ ++ pescx_ctl_status2.u64 = ++ cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); ++ pescx_ctl_status2.s.pclk_run = 1; ++ cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), ++ pescx_ctl_status2.u64); ++ /* ++ * Now that we cleared PCLK_RUN, wait for it to be set ++ * again telling us the clock is running. ++ */ ++ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), ++ union cvmx_pescx_ctl_status2, ++ pclk_run, ==, 1, 10000)) { ++ cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", ++ pcie_port); ++ return -1; ++ } ++ } ++ ++ /* ++ * Check and make sure PCIe came out of reset. If it doesn't ++ * the board probably hasn't wired the clocks up and the ++ * interface should be skipped. ++ */ ++ pescx_ctl_status2.u64 = ++ cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); ++ if (pescx_ctl_status2.s.pcierst) { ++ cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", ++ pcie_port); ++ return -1; ++ } ++ ++ /* ++ * Check BIST2 status. If any bits are set skip this interface. This ++ * is an attempt to catch PCIE-813 on pass 1 parts. ++ */ ++ pescx_bist_status2.u64 = ++ cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); ++ if (pescx_bist_status2.u64) { ++ cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this " ++ "port isn't hooked up, skipping.\n", ++ pcie_port); ++ return -1; ++ } ++ ++ /* Check BIST status */ ++ pescx_bist_status.u64 = ++ cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); ++ if (pescx_bist_status.u64) ++ cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", ++ pcie_port, CAST64(pescx_bist_status.u64)); ++ ++ /* Initialize the config space CSRs */ ++ __cvmx_pcie_rc_initialize_config_space(pcie_port); ++ ++ /* Bring the link up */ ++ if (__cvmx_pcie_rc_initialize_link(pcie_port)) { ++ cvmx_dprintf ++ ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n"); ++ return -1; ++ } ++ ++ /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ ++ npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); ++ /* Allow 16 words to combine */ ++ npei_mem_access_ctl.s.max_word = 0; ++ /* Wait up to 127 cycles for more data */ ++ npei_mem_access_ctl.s.timer = 127; ++ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); ++ ++ /* Setup Mem access SubDIDs */ ++ mem_access_subid.u64 = 0; ++ /* Port the request is sent to. */ ++ mem_access_subid.s.port = pcie_port; ++ /* Due to an errata on pass 1 chips, no merging is allowed. */ ++ mem_access_subid.s.nmerge = 1; ++ /* Endian-swap for Reads. */ ++ mem_access_subid.s.esr = 1; ++ /* Endian-swap for Writes. */ ++ mem_access_subid.s.esw = 1; ++ /* No Snoop for Reads. */ ++ mem_access_subid.s.nsr = 1; ++ /* No Snoop for Writes. */ ++ mem_access_subid.s.nsw = 1; ++ /* Disable Relaxed Ordering for Reads. */ ++ mem_access_subid.s.ror = 0; ++ /* Disable Relaxed Ordering for Writes. */ ++ mem_access_subid.s.row = 0; ++ /* PCIe Adddress Bits <63:34>. */ ++ mem_access_subid.s.ba = 0; ++ ++ /* ++ * Setup mem access 12-15 for port 0, 16-19 for port 1, ++ * supplying 36 bits of address space. ++ */ ++ for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) { ++ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), ++ mem_access_subid.u64); ++ /* Set each SUBID to extend the addressable range */ ++ mem_access_subid.s.ba += 1; ++ } ++ ++ /* ++ * Disable the peer to peer forwarding register. This must be ++ * setup by the OS after it enumerates the bus and assigns ++ * addresses to the PCIe busses. ++ */ ++ for (i = 0; i < 4; i++) { ++ cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1); ++ cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1); ++ } ++ ++ /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ ++ cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); ++ ++ /* ++ * Disable Octeon's BAR1. It isn't needed in RC mode since ++ * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into ++ * the 2nd 256MB of memory. ++ */ ++ cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); ++ ++ /* ++ * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take ++ * precedence where they overlap. It also overlaps with the ++ * device addresses, so make sure the peer to peer forwarding ++ * is set right. ++ */ ++ cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0); ++ ++ /* ++ * Setup BAR2 attributes ++ * ++ * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) ++ * - PTLP_RO,CTLP_RO should normally be set (except for debug). ++ * - WAIT_COM=0 will likely work for all applications. ++ * ++ * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]). ++ */ ++ if (pcie_port) { ++ union cvmx_npei_ctl_port1 npei_ctl_port; ++ npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1); ++ npei_ctl_port.s.bar2_enb = 1; ++ npei_ctl_port.s.bar2_esx = 1; ++ npei_ctl_port.s.bar2_cax = 0; ++ npei_ctl_port.s.ptlp_ro = 1; ++ npei_ctl_port.s.ctlp_ro = 1; ++ npei_ctl_port.s.wait_com = 0; ++ npei_ctl_port.s.waitl_com = 0; ++ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64); ++ } else { ++ union cvmx_npei_ctl_port0 npei_ctl_port; ++ npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0); ++ npei_ctl_port.s.bar2_enb = 1; ++ npei_ctl_port.s.bar2_esx = 1; ++ npei_ctl_port.s.bar2_cax = 0; ++ npei_ctl_port.s.ptlp_ro = 1; ++ npei_ctl_port.s.ctlp_ro = 1; ++ npei_ctl_port.s.wait_com = 0; ++ npei_ctl_port.s.waitl_com = 0; ++ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); ++ } ++ return 0; ++} ++ ++/** ++ * Shutdown a PCIe port and put it in reset ++ * ++ * @pcie_port: PCIe port to shutdown ++ * ++ * Returns Zero on success ++ */ ++int cvmx_pcie_rc_shutdown(int pcie_port) ++{ ++ /* Wait for all pending operations to complete */ ++ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CPL_LUT_VALID(pcie_port), ++ union cvmx_pescx_cpl_lut_valid, ++ tag, ==, 0, 2000)) ++ cvmx_dprintf("PCIe: Port %d shutdown timeout\n", pcie_port); ++ ++ /* Force reset */ ++ if (pcie_port) { ++ union cvmx_ciu_soft_prst ciu_soft_prst; ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ++ ciu_soft_prst.s.soft_prst = 1; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); ++ } else { ++ union cvmx_ciu_soft_prst ciu_soft_prst; ++ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ ciu_soft_prst.s.soft_prst = 1; ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); ++ } ++ return 0; ++} ++ ++/** ++ * Build a PCIe config space request address for a device ++ * ++ * @pcie_port: PCIe port to access ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns 64bit Octeon IO address ++ */ ++static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, ++ int dev, int fn, int reg) ++{ ++ union cvmx_pcie_address pcie_addr; ++ union cvmx_pciercx_cfg006 pciercx_cfg006; ++ ++ pciercx_cfg006.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port)); ++ if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0)) ++ return 0; ++ ++ pcie_addr.u64 = 0; ++ pcie_addr.config.upper = 2; ++ pcie_addr.config.io = 1; ++ pcie_addr.config.did = 3; ++ pcie_addr.config.subdid = 1; ++ pcie_addr.config.es = 1; ++ pcie_addr.config.port = pcie_port; ++ pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum); ++ pcie_addr.config.bus = bus; ++ pcie_addr.config.dev = dev; ++ pcie_addr.config.func = fn; ++ pcie_addr.config.reg = reg; ++ return pcie_addr.u64; ++} ++ ++/** ++ * Read 8bits from a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns Result of the read ++ */ ++uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, ++ int fn, int reg) ++{ ++ uint64_t address = ++ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); ++ if (address) ++ return cvmx_read64_uint8(address); ++ else ++ return 0xff; ++} ++ ++/** ++ * Read 16bits from a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns Result of the read ++ */ ++uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, ++ int reg) ++{ ++ uint64_t address = ++ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); ++ if (address) ++ return le16_to_cpu(cvmx_read64_uint16(address)); ++ else ++ return 0xffff; ++} ++ ++/** ++ * Read 32bits from a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns Result of the read ++ */ ++uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, ++ int reg) ++{ ++ uint64_t address = ++ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); ++ if (address) ++ return le32_to_cpu(cvmx_read64_uint32(address)); ++ else ++ return 0xffffffff; ++} ++ ++/** ++ * Write 8bits to a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * @val: Value to write ++ */ ++void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, ++ int reg, uint8_t val) ++{ ++ uint64_t address = ++ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); ++ if (address) ++ cvmx_write64_uint8(address, val); ++} ++ ++/** ++ * Write 16bits to a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * @val: Value to write ++ */ ++void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, ++ int reg, uint16_t val) ++{ ++ uint64_t address = ++ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); ++ if (address) ++ cvmx_write64_uint16(address, cpu_to_le16(val)); ++} ++ ++/** ++ * Write 32bits to a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * @val: Value to write ++ */ ++void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, ++ int reg, uint32_t val) ++{ ++ uint64_t address = ++ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); ++ if (address) ++ cvmx_write64_uint32(address, cpu_to_le32(val)); ++} ++ ++/** ++ * Read a PCIe config space register indirectly. This is used for ++ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. ++ * ++ * @pcie_port: PCIe port to read from ++ * @cfg_offset: Address to read ++ * ++ * Returns Value read ++ */ ++uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) ++{ ++ union cvmx_pescx_cfg_rd pescx_cfg_rd; ++ pescx_cfg_rd.u64 = 0; ++ pescx_cfg_rd.s.addr = cfg_offset; ++ cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); ++ pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); ++ return pescx_cfg_rd.s.data; ++} ++ ++/** ++ * Write a PCIe config space register indirectly. This is used for ++ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. ++ * ++ * @pcie_port: PCIe port to write to ++ * @cfg_offset: Address to write ++ * @val: Value to write ++ */ ++void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val) ++{ ++ union cvmx_pescx_cfg_wr pescx_cfg_wr; ++ pescx_cfg_wr.u64 = 0; ++ pescx_cfg_wr.s.addr = cfg_offset; ++ pescx_cfg_wr.s.data = val; ++ cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); ++} ++ ++/** ++ * Initialize a PCIe port for use in target(EP) mode. ++ * ++ * Returns Zero on success ++ */ ++int cvmx_pcie_ep_initialize(void) ++{ ++ int pcie_port = 0; ++ union cvmx_npei_ctl_status npei_ctl_status; ++ union cvmx_pciercx_cfg030 pciercx_cfg030; ++ union cvmx_npei_ctl_status2 npei_ctl_status2; ++ union cvmx_npei_mem_access_subidx mem_access_subid; ++ ++ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); ++ if (npei_ctl_status.s.host_mode) ++ return -1; ++ ++ /* Enable bus master and memory */ ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIEEP_CFG001, 0x6); ++ ++ /* ++ * Max Payload Size (PCIE*_CFG030[MPS]) ++ * Max Read Request Size (PCIE*_CFG030[MRRS]) ++ * Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] ++ * Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) ++ */ ++ pciercx_cfg030.u32 = ++ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); ++ /* Max payload size = 128 bytes (Limit of most PCs) */ ++ pciercx_cfg030.s.mps = 0; ++ /* ++ * Max read request size = 128 bytes for best Octeon DMA ++ * performance. ++ */ ++ pciercx_cfg030.s.mrrs = 0; ++ /* Enable relaxed ordering. */ ++ pciercx_cfg030.s.ro_en = 1; ++ /* Enable no snoop. */ ++ pciercx_cfg030.s.ns_en = 1; ++ /* Correctable error reporting enable. */ ++ pciercx_cfg030.s.ce_en = 1; ++ /* Non-fatal error reporting enable. */ ++ pciercx_cfg030.s.nfe_en = 1; ++ /* Fatal error reporting enable. */ ++ pciercx_cfg030.s.fe_en = 1; ++ /* Unsupported request reporting enable. */ ++ pciercx_cfg030.s.ur_en = 1; ++ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), ++ pciercx_cfg030.u32); ++ ++ /* ++ * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match ++ * PCIE*_CFG030[MPS] ++ * ++ * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not ++ * exceed PCIE*_CFG030[MRRS] ++ */ ++ npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); ++ /* Max payload size = 128 bytes (Limit of most PCs) */ ++ npei_ctl_status2.s.mps = 0; ++ /* Max read request size = 128 bytes for best Octeon DMA performance */ ++ npei_ctl_status2.s.mrrs = 0; ++ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); ++ ++ /* Setup Mem access SubDID 12 to access Host memory */ ++ mem_access_subid.u64 = 0; ++ /* Port the request is sent to. */ ++ mem_access_subid.s.port = pcie_port; ++ /* Merging is allowed in this window. */ ++ mem_access_subid.s.nmerge = 1; ++ /* Endian-swap for Reads. */ ++ mem_access_subid.s.esr = 0; ++ /* Endian-swap for Writes. */ ++ mem_access_subid.s.esw = 0; ++ /* No Snoop for Reads. */ ++ mem_access_subid.s.nsr = 1; ++ /* No Snoop for Writes. */ ++ mem_access_subid.s.nsw = 1; ++ /* Disable Relaxed Ordering for Reads. */ ++ mem_access_subid.s.ror = 0; ++ /* Disable Relaxed Ordering for Writes. */ ++ mem_access_subid.s.row = 0; ++ /* PCIe Adddress Bits <63:34>. */ ++ mem_access_subid.s.ba = 0; ++ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(12), ++ mem_access_subid.u64); ++ return 0; ++} +--- /dev/null ++++ b/arch/mips/cavium-octeon/msi.c +@@ -0,0 +1,288 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2005-2007 Cavium Networks ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pci-common.h" ++ ++/* ++ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is ++ * in use. ++ */ ++static uint64_t msi_free_irq_bitmask; ++ ++/* ++ * Each bit in msi_multiple_irq_bitmask tells that the device using ++ * this bit in msi_free_irq_bitmask is also using the next bit. This ++ * is used so we can disable all of the MSI interrupts when a device ++ * uses multiple. ++ */ ++static uint64_t msi_multiple_irq_bitmask; ++ ++/* ++ * This lock controls updates to msi_free_irq_bitmask and ++ * msi_multiple_irq_bitmask. ++ */ ++static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); ++ ++ ++/** ++ * Called when a driver request MSI interrupts instead of the ++ * legacy INT A-D. This routine will allocate multiple interrupts ++ * for MSI devices that support them. A device can override this by ++ * programming the MSI control bits [6:4] before calling ++ * pci_enable_msi(). ++ * ++ * @param dev Device requesting MSI interrupts ++ * @param desc MSI descriptor ++ * ++ * Returns 0 on success. ++ */ ++int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) ++{ ++ struct msi_msg msg; ++ uint16_t control; ++ int configured_private_bits; ++ int request_private_bits; ++ int irq; ++ int irq_step; ++ uint64_t search_mask; ++ ++ /* ++ * Read the MSI config to figure out how many IRQs this device ++ * wants. Most devices only want 1, which will give ++ * configured_private_bits and request_private_bits equal 0. ++ */ ++ pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, ++ &control); ++ ++ /* ++ * If the number of private bits has been configured then use ++ * that value instead of the requested number. This gives the ++ * driver the chance to override the number of interrupts ++ * before calling pci_enable_msi(). ++ */ ++ configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4; ++ if (configured_private_bits == 0) { ++ /* Nothing is configured, so use the hardware requested size */ ++ request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1; ++ } else { ++ /* ++ * Use the number of configured bits, assuming the ++ * driver wanted to override the hardware request ++ * value. ++ */ ++ request_private_bits = configured_private_bits; ++ } ++ ++ /* ++ * The PCI 2.3 spec mandates that there are at most 32 ++ * interrupts. If this device asks for more, only give it one. ++ */ ++ if (request_private_bits > 5) ++ request_private_bits = 0; ++ ++try_only_one: ++ /* ++ * The IRQs have to be aligned on a power of two based on the ++ * number being requested. ++ */ ++ irq_step = 1 << request_private_bits; ++ ++ /* Mask with one bit for each IRQ */ ++ search_mask = (1 << irq_step) - 1; ++ ++ /* ++ * We're going to search msi_free_irq_bitmask_lock for zero ++ * bits. This represents an MSI interrupt number that isn't in ++ * use. ++ */ ++ spin_lock(&msi_free_irq_bitmask_lock); ++ for (irq = 0; irq < 64; irq += irq_step) { ++ if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) { ++ msi_free_irq_bitmask |= search_mask << irq; ++ msi_multiple_irq_bitmask |= (search_mask >> 1) << irq; ++ break; ++ } ++ } ++ spin_unlock(&msi_free_irq_bitmask_lock); ++ ++ /* Make sure the search for available interrupts didn't fail */ ++ if (irq >= 64) { ++ if (request_private_bits) { ++ pr_err("arch_setup_msi_irq: Unable to find %d free " ++ "interrupts, trying just one", ++ 1 << request_private_bits); ++ request_private_bits = 0; ++ goto try_only_one; ++ } else ++ panic("arch_setup_msi_irq: Unable to find a free MSI " ++ "interrupt"); ++ } ++ ++ /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */ ++ irq += OCTEON_IRQ_MSI_BIT0; ++ ++ switch (octeon_dma_bar_type) { ++ case OCTEON_DMA_BAR_TYPE_SMALL: ++ /* When not using big bar, Bar 0 is based at 128MB */ ++ msg.address_lo = ++ ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff; ++ msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32; ++ case OCTEON_DMA_BAR_TYPE_BIG: ++ /* When using big bar, Bar 0 is based at 0 */ ++ msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff; ++ msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32; ++ break; ++ case OCTEON_DMA_BAR_TYPE_PCIE: ++ /* When using PCIe, Bar 0 is based at 0 */ ++ /* FIXME CVMX_NPEI_MSI_RCV* other than 0? */ ++ msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; ++ msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; ++ break; ++ default: ++ panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n"); ++ } ++ msg.data = irq - OCTEON_IRQ_MSI_BIT0; ++ ++ /* Update the number of IRQs the device has available to it */ ++ control &= ~PCI_MSI_FLAGS_QSIZE; ++ control |= request_private_bits << 4; ++ pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, ++ control); ++ ++ set_irq_msi(irq, desc); ++ write_msi_msg(irq, &msg); ++ return 0; ++} ++ ++ ++/** ++ * Called when a device no longer needs its MSI interrupts. All ++ * MSI interrupts for the device are freed. ++ * ++ * @irq: The devices first irq number. There may be multple in sequence. ++ */ ++void arch_teardown_msi_irq(unsigned int irq) ++{ ++ int number_irqs; ++ uint64_t bitmask; ++ ++ if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63)) ++ panic("arch_teardown_msi_irq: Attempted to teardown illegal " ++ "MSI interrupt (%d)", irq); ++ irq -= OCTEON_IRQ_MSI_BIT0; ++ ++ /* ++ * Count the number of IRQs we need to free by looking at the ++ * msi_multiple_irq_bitmask. Each bit set means that the next ++ * IRQ is also owned by this device. ++ */ ++ number_irqs = 0; ++ while ((irq+number_irqs < 64) && ++ (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs)))) ++ number_irqs++; ++ number_irqs++; ++ /* Mask with one bit for each IRQ */ ++ bitmask = (1 << number_irqs) - 1; ++ /* Shift the mask to the correct bit location */ ++ bitmask <<= irq; ++ if ((msi_free_irq_bitmask & bitmask) != bitmask) ++ panic("arch_teardown_msi_irq: Attempted to teardown MSI " ++ "interrupt (%d) not in use", irq); ++ ++ /* Checks are done, update the in use bitmask */ ++ spin_lock(&msi_free_irq_bitmask_lock); ++ msi_free_irq_bitmask &= ~bitmask; ++ msi_multiple_irq_bitmask &= ~bitmask; ++ spin_unlock(&msi_free_irq_bitmask_lock); ++} ++ ++ ++/** ++ * Called by the interrupt handling code when an MSI interrupt ++ * occurs. ++ * ++ * @param cpl ++ * @param dev_id ++ * ++ * @return ++ */ ++static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) ++{ ++ uint64_t msi_bits; ++ int irq; ++ ++ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) ++ msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0); ++ else ++ msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV); ++ irq = fls64(msi_bits); ++ if (irq) { ++ irq += OCTEON_IRQ_MSI_BIT0 - 1; ++ if (irq_desc[irq].action) { ++ do_IRQ(irq); ++ return IRQ_HANDLED; ++ } else { ++ pr_err("Spurious MSI interrupt %d\n", irq); ++ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { ++ /* These chips have PCIe */ ++ cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, ++ 1ull << (irq - ++ OCTEON_IRQ_MSI_BIT0)); ++ } else { ++ /* These chips have PCI */ ++ cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, ++ 1ull << (irq - ++ OCTEON_IRQ_MSI_BIT0)); ++ } ++ } ++ } ++ return IRQ_NONE; ++} ++ ++ ++/** ++ * Initializes the MSI interrupt handling code ++ * ++ * @return ++ */ ++int octeon_msi_initialize(void) ++{ ++ int r; ++ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { ++ r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, ++ IRQF_SHARED, ++ "MSI[0:63]", octeon_msi_interrupt); ++ } else if (octeon_is_pci_host()) { ++ r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, ++ IRQF_SHARED, ++ "MSI[0:15]", octeon_msi_interrupt); ++ r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, ++ IRQF_SHARED, ++ "MSI[16:31]", octeon_msi_interrupt); ++ r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, ++ IRQF_SHARED, ++ "MSI[32:47]", octeon_msi_interrupt); ++ r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, ++ IRQF_SHARED, ++ "MSI[48:63]", octeon_msi_interrupt); ++ } ++ return 0; ++} ++ ++subsys_initcall(octeon_msi_initialize); +--- a/arch/mips/cavium-octeon/octeon-irq.c ++++ b/arch/mips/cavium-octeon/octeon-irq.c +@@ -10,6 +10,8 @@ + #include + + #include ++#include ++#include + + DEFINE_RWLOCK(octeon_irq_ciu0_rwlock); + DEFINE_RWLOCK(octeon_irq_ciu1_rwlock); +--- /dev/null ++++ b/arch/mips/cavium-octeon/pci-common.c +@@ -0,0 +1,137 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2005-2007 Cavium Networks ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pci-common.h" ++ ++typeof(pcibios_map_irq) *octeon_pcibios_map_irq; ++enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; ++ ++/** ++ * Map a PCI device to the appropriate interrupt line ++ * ++ * @param dev The Linux PCI device structure for the device to map ++ * @param slot The slot number for this device on __BUS 0__. Linux ++ * enumerates through all the bridges and figures out the ++ * slot on Bus 0 where this device eventually hooks to. ++ * @param pin The PCI interrupt pin read from the device, then swizzled ++ * as it goes through each bridge. ++ * @return Interrupt number for the device ++ */ ++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if (octeon_pcibios_map_irq) ++ return octeon_pcibios_map_irq(dev, slot, pin); ++ else ++ panic("octeon_pcibios_map_irq doesn't point to a " ++ "pcibios_map_irq() function"); ++} ++ ++ ++/** ++ * Called to perform platform specific PCI setup ++ * ++ * @param dev ++ * @return ++ */ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ uint16_t config; ++ uint32_t dconfig; ++ int pos; ++ /* ++ * Force the Cache line setting to 64 bytes. The standard ++ * Linux bus scan doesn't seem to set it. Octeon really has ++ * 128 byte lines, but Intel bridges get really upset if you ++ * try and set values above 64 bytes. Value is specified in ++ * 32bit words. ++ */ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); ++ /* Set latency timers for all devices */ ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); ++ ++ /* Enable reporting System errors and parity errors on all devices */ ++ /* Enable parity checking and error reporting */ ++ pci_read_config_word(dev, PCI_COMMAND, &config); ++ config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; ++ pci_write_config_word(dev, PCI_COMMAND, config); ++ ++ if (dev->subordinate) { ++ /* Set latency timers on sub bridges */ ++ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); ++ /* More bridge error detection */ ++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); ++ config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; ++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config); ++ } ++ ++ /* Enable the PCIe normal error reporting */ ++ pos = pci_find_capability(dev, PCI_CAP_ID_EXP); ++ if (pos) { ++ /* Update Device Control */ ++ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); ++ /* Correctable Error Reporting */ ++ config |= PCI_EXP_DEVCTL_CERE; ++ /* Non-Fatal Error Reporting */ ++ config |= PCI_EXP_DEVCTL_NFERE; ++ /* Fatal Error Reporting */ ++ config |= PCI_EXP_DEVCTL_FERE; ++ /* Unsupported Request */ ++ config |= PCI_EXP_DEVCTL_URRE; ++ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); ++ } ++ ++ /* Find the Advanced Error Reporting capability */ ++ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); ++ if (pos) { ++ /* Clear Uncorrectable Error Status */ ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, ++ &dconfig); ++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, ++ dconfig); ++ /* Enable reporting of all uncorrectable errors */ ++ /* Uncorrectable Error Mask - turned on bits disable errors */ ++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0); ++ /* ++ * Leave severity at HW default. This only controls if ++ * errors are reported as uncorrectable or ++ * correctable, not if the error is reported. ++ */ ++ /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */ ++ /* Clear Correctable Error Status */ ++ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig); ++ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig); ++ /* Enable reporting of all correctable errors */ ++ /* Correctable Error Mask - turned on bits disable errors */ ++ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0); ++ /* Advanced Error Capabilities */ ++ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig); ++ /* ECRC Generation Enable */ ++ if (config & PCI_ERR_CAP_ECRC_GENC) ++ config |= PCI_ERR_CAP_ECRC_GENE; ++ /* ECRC Check Enable */ ++ if (config & PCI_ERR_CAP_ECRC_CHKC) ++ config |= PCI_ERR_CAP_ECRC_CHKE; ++ pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig); ++ /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */ ++ /* Report all errors to the root complex */ ++ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ++ PCI_ERR_ROOT_CMD_COR_EN | ++ PCI_ERR_ROOT_CMD_NONFATAL_EN | ++ PCI_ERR_ROOT_CMD_FATAL_EN); ++ /* Clear the Root status register */ ++ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig); ++ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig); ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/arch/mips/cavium-octeon/pci-common.h +@@ -0,0 +1,39 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2005-2007 Cavium Networks ++ */ ++#ifndef __OCTEON_PCI_COMMON_H__ ++#define __OCTEON_PCI_COMMON_H__ ++ ++#include ++ ++/* Some PCI cards require delays when accessing config space. */ ++#define PCI_CONFIG_SPACE_DELAY 10000 ++ ++/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the ++ Octeon specific version pointed to by this variable. This function needs to ++ change for PCI or PCIe based hosts */ ++extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq; ++ ++/* The following defines are only used when octeon_dma_bar_type = ++ OCTEON_DMA_BAR_TYPE_BIG */ ++#define OCTEON_PCI_BAR1_HOLE_BITS 5 ++#define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3)) ++ ++enum octeon_dma_bar_type { ++ OCTEON_DMA_BAR_TYPE_INVALID, ++ OCTEON_DMA_BAR_TYPE_SMALL, ++ OCTEON_DMA_BAR_TYPE_BIG, ++ OCTEON_DMA_BAR_TYPE_PCIE ++}; ++ ++/** ++ * This is a variable to tell the DMA mapping system in dma-octeon.c ++ * how to map PCI DMA addresses. ++ */ ++extern enum octeon_dma_bar_type octeon_dma_bar_type; ++ ++#endif +--- /dev/null ++++ b/arch/mips/cavium-octeon/pci.c +@@ -0,0 +1,568 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2005-2007 Cavium Networks ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "pci-common.h" ++ ++#define USE_OCTEON_INTERNAL_ARBITER ++ ++/* ++ * Octeon's PCI controller uses did=3, subdid=2 for PCI IO ++ * addresses. Use PCI endian swapping 1 so no address swapping is ++ * necessary. The Linux io routines will endian swap the data. ++ */ ++#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull ++#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32) ++ ++/* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */ ++#define OCTEON_PCI_MEMSPACE_OFFSET (0x00011b0000000000ull) ++ ++/** ++ * This is the bit decoding used for the Octeon PCI controller addresses ++ */ ++union octeon_pci_address { ++ uint64_t u64; ++ struct { ++ uint64_t upper:2; ++ uint64_t reserved:13; ++ uint64_t io:1; ++ uint64_t did:5; ++ uint64_t subdid:3; ++ uint64_t reserved2:4; ++ uint64_t endian_swap:2; ++ uint64_t reserved3:10; ++ uint64_t bus:8; ++ uint64_t dev:5; ++ uint64_t func:3; ++ uint64_t reg:8; ++ } s; ++}; ++ ++/** ++ * Return the mapping of PCI device number to IRQ line. Each ++ * character in the return string represents the interrupt ++ * line for the device at that position. Device 1 maps to the ++ * first character, etc. The characters A-D are used for PCI ++ * interrupts. ++ * ++ * Returns PCI interrupt mapping ++ */ ++const char *octeon_get_pci_interrupts(void) ++{ ++ /* ++ * Returning an empty string causes the interrupts to be ++ * routed based on the PCI specification. From the PCI spec: ++ * ++ * INTA# of Device Number 0 is connected to IRQW on the system ++ * board. (Device Number has no significance regarding being ++ * located on the system board or in a connector.) INTA# of ++ * Device Number 1 is connected to IRQX on the system ++ * board. INTA# of Device Number 2 is connected to IRQY on the ++ * system board. INTA# of Device Number 3 is connected to IRQZ ++ * on the system board. The table below describes how each ++ * agent's INTx# lines are connected to the system board ++ * interrupt lines. The following equation can be used to ++ * determine to which INTx# signal on the system board a given ++ * device's INTx# line(s) is connected. ++ * ++ * MB = (D + I) MOD 4 MB = System board Interrupt (IRQW = 0, ++ * IRQX = 1, IRQY = 2, and IRQZ = 3) D = Device Number I = ++ * Interrupt Number (INTA# = 0, INTB# = 1, INTC# = 2, and ++ * INTD# = 3) ++ */ ++ switch (octeon_bootinfo->board_type) { ++ case CVMX_BOARD_TYPE_NAO38: ++ /* This is really the NAC38 */ ++ return "AAAAADABAAAAAAAAAAAAAAAAAAAAAAAA"; ++ case CVMX_BOARD_TYPE_THUNDER: ++ return ""; ++ case CVMX_BOARD_TYPE_EBH3000: ++ return ""; ++ case CVMX_BOARD_TYPE_EBH3100: ++ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: ++ return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; ++ case CVMX_BOARD_TYPE_BBGW_REF: ++ return "AABCD"; ++ default: ++ return ""; ++ } ++} ++ ++/** ++ * Map a PCI device to the appropriate interrupt line ++ * ++ * @dev: The Linux PCI device structure for the device to map ++ * @slot: The slot number for this device on __BUS 0__. Linux ++ * enumerates through all the bridges and figures out the ++ * slot on Bus 0 where this device eventually hooks to. ++ * @pin: The PCI interrupt pin read from the device, then swizzled ++ * as it goes through each bridge. ++ * Returns Interrupt number for the device ++ */ ++int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev, ++ u8 slot, u8 pin) ++{ ++ int irq_num; ++ const char *interrupts; ++ int dev_num; ++ ++ /* Get the board specific interrupt mapping */ ++ interrupts = octeon_get_pci_interrupts(); ++ ++ dev_num = dev->devfn >> 3; ++ if (dev_num < strlen(interrupts)) ++ irq_num = ((interrupts[dev_num] - 'A' + pin - 1) & 3) + ++ OCTEON_IRQ_PCI_INT0; ++ else ++ irq_num = ((slot + pin - 3) & 3) + OCTEON_IRQ_PCI_INT0; ++ return irq_num; ++} ++ ++ ++/** ++ * Read a value from configuration space ++ * ++ */ ++static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, ++ int reg, int size, u32 *val) ++{ ++ union octeon_pci_address pci_addr; ++ ++ pci_addr.u64 = 0; ++ pci_addr.s.upper = 2; ++ pci_addr.s.io = 1; ++ pci_addr.s.did = 3; ++ pci_addr.s.subdid = 1; ++ pci_addr.s.endian_swap = 1; ++ pci_addr.s.bus = bus->number; ++ pci_addr.s.dev = devfn >> 3; ++ pci_addr.s.func = devfn & 0x7; ++ pci_addr.s.reg = reg; ++ ++#if PCI_CONFIG_SPACE_DELAY ++ udelay(PCI_CONFIG_SPACE_DELAY); ++#endif ++ switch (size) { ++ case 4: ++ *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64)); ++ return PCIBIOS_SUCCESSFUL; ++ case 2: ++ *val = le16_to_cpu(cvmx_read64_uint16(pci_addr.u64)); ++ return PCIBIOS_SUCCESSFUL; ++ case 1: ++ *val = cvmx_read64_uint8(pci_addr.u64); ++ return PCIBIOS_SUCCESSFUL; ++ } ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++} ++ ++ ++/** ++ * Write a value to PCI configuration space ++ * ++ * @bus: ++ * @devfn: ++ * @reg: ++ * @size: ++ * @val: ++ * Returns ++ */ ++static int octeon_write_config(struct pci_bus *bus, unsigned int devfn, ++ int reg, int size, u32 val) ++{ ++ union octeon_pci_address pci_addr; ++ ++ pci_addr.u64 = 0; ++ pci_addr.s.upper = 2; ++ pci_addr.s.io = 1; ++ pci_addr.s.did = 3; ++ pci_addr.s.subdid = 1; ++ pci_addr.s.endian_swap = 1; ++ pci_addr.s.bus = bus->number; ++ pci_addr.s.dev = devfn >> 3; ++ pci_addr.s.func = devfn & 0x7; ++ pci_addr.s.reg = reg; ++ ++#if PCI_CONFIG_SPACE_DELAY ++ udelay(PCI_CONFIG_SPACE_DELAY); ++#endif ++ switch (size) { ++ case 4: ++ cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val)); ++ return PCIBIOS_SUCCESSFUL; ++ case 2: ++ cvmx_write64_uint16(pci_addr.u64, cpu_to_le16(val)); ++ return PCIBIOS_SUCCESSFUL; ++ case 1: ++ cvmx_write64_uint8(pci_addr.u64, val); ++ return PCIBIOS_SUCCESSFUL; ++ } ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++} ++ ++ ++static struct pci_ops octeon_pci_ops = { ++ octeon_read_config, ++ octeon_write_config, ++}; ++ ++static struct resource octeon_pci_mem_resource = { ++ .start = 0, ++ .end = 0, ++ .name = "Octeon PCI MEM", ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * PCI ports must be above 16KB so the ISA bus filtering in the PCI-X to PCI ++ * bridge ++ */ ++static struct resource octeon_pci_io_resource = { ++ .start = 0x4000, ++ .end = OCTEON_PCI_IOSPACE_SIZE - 1, ++ .name = "Octeon PCI IO", ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller octeon_pci_controller = { ++ .pci_ops = &octeon_pci_ops, ++ .mem_resource = &octeon_pci_mem_resource, ++ .mem_offset = OCTEON_PCI_MEMSPACE_OFFSET, ++ .io_resource = &octeon_pci_io_resource, ++ .io_offset = 0, ++ .io_map_base = OCTEON_PCI_IOSPACE_BASE, ++}; ++ ++ ++/** ++ * Low level initialize the Octeon PCI controller ++ * ++ * Returns ++ */ ++static void octeon_pci_initialize(void) ++{ ++ union cvmx_pci_cfg01 cfg01; ++ union cvmx_npi_ctl_status ctl_status; ++ union cvmx_pci_ctl_status_2 ctl_status_2; ++ union cvmx_pci_cfg19 cfg19; ++ union cvmx_pci_cfg16 cfg16; ++ union cvmx_pci_cfg22 cfg22; ++ union cvmx_pci_cfg56 cfg56; ++ ++ /* Reset the PCI Bus */ ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1); ++ cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ ++ udelay(2000); /* Hold PCI reset for 2 ms */ ++ ++ ctl_status.u64 = 0; /* cvmx_read_csr(CVMX_NPI_CTL_STATUS); */ ++ ctl_status.s.max_word = 1; ++ ctl_status.s.timer = 1; ++ cvmx_write_csr(CVMX_NPI_CTL_STATUS, ctl_status.u64); ++ ++ /* Deassert PCI reset and advertize PCX Host Mode Device Capability ++ (64b) */ ++ cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4); ++ cvmx_read_csr(CVMX_CIU_SOFT_PRST); ++ ++ udelay(2000); /* Wait 2 ms after deasserting PCI reset */ ++ ++ ctl_status_2.u32 = 0; ++ ctl_status_2.s.tsr_hwm = 1; /* Initializes to 0. Must be set ++ before any PCI reads. */ ++ ctl_status_2.s.bar2pres = 1; /* Enable BAR2 */ ++ ctl_status_2.s.bar2_enb = 1; ++ ctl_status_2.s.bar2_cax = 1; /* Don't use L2 */ ++ ctl_status_2.s.bar2_esx = 1; ++ ctl_status_2.s.pmo_amod = 1; /* Round robin priority */ ++ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { ++ /* BAR1 hole */ ++ ctl_status_2.s.bb1_hole = OCTEON_PCI_BAR1_HOLE_BITS; ++ ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */ ++ ctl_status_2.s.bb_ca = 1; /* Don't use L2 with big bars */ ++ ctl_status_2.s.bb_es = 1; /* Big bar in byte swap mode */ ++ ctl_status_2.s.bb1 = 1; /* BAR1 is big */ ++ ctl_status_2.s.bb0 = 1; /* BAR0 is big */ ++ } ++ ++ octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32); ++ udelay(2000); /* Wait 2 ms before doing PCI reads */ ++ ++ ctl_status_2.u32 = octeon_npi_read32(CVMX_NPI_PCI_CTL_STATUS_2); ++ pr_notice("PCI Status: %s %s-bit\n", ++ ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI", ++ ctl_status_2.s.ap_64ad ? "64" : "32"); ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ union cvmx_pci_cnt_reg cnt_reg_start; ++ union cvmx_pci_cnt_reg cnt_reg_end; ++ unsigned long cycles, pci_clock; ++ ++ cnt_reg_start.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); ++ cycles = read_c0_cvmcount(); ++ udelay(1000); ++ cnt_reg_end.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); ++ cycles = read_c0_cvmcount() - cycles; ++ pci_clock = (cnt_reg_end.s.pcicnt - cnt_reg_start.s.pcicnt) / ++ (cycles / (mips_hpt_frequency / 1000000)); ++ pr_notice("PCI Clock: %lu MHz\n", pci_clock); ++ } ++ ++ /* ++ * TDOMC must be set to one in PCI mode. TDOMC should be set to 4 ++ * in PCI-X mode to allow four oustanding splits. Otherwise, ++ * should not change from its reset value. Don't write PCI_CFG19 ++ * in PCI mode (0x82000001 reset value), write it to 0x82000004 ++ * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero. ++ * MRBCM -> must be one. ++ */ ++ if (ctl_status_2.s.ap_pcix) { ++ cfg19.u32 = 0; ++ /* ++ * Target Delayed/Split request outstanding maximum ++ * count. [1..31] and 0=32. NOTE: If the user ++ * programs these bits beyond the Designed Maximum ++ * outstanding count, then the designed maximum table ++ * depth will be used instead. No additional ++ * Deferred/Split transactions will be accepted if ++ * this outstanding maximum count is ++ * reached. Furthermore, no additional deferred/split ++ * transactions will be accepted if the I/O delay/ I/O ++ * Split Request outstanding maximum is reached. ++ */ ++ cfg19.s.tdomc = 4; ++ /* ++ * Master Deferred Read Request Outstanding Max Count ++ * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC ++ * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101 ++ * 5 2 110 6 3 111 7 3 For example, if these bits are ++ * programmed to 100, the core can support 2 DAC ++ * cycles, 4 SAC cycles or a combination of 1 DAC and ++ * 2 SAC cycles. NOTE: For the PCI-X maximum ++ * outstanding split transactions, refer to ++ * CRE0[22:20]. ++ */ ++ cfg19.s.mdrrmc = 2; ++ /* ++ * Master Request (Memory Read) Byte Count/Byte Enable ++ * select. 0 = Byte Enables valid. In PCI mode, a ++ * burst transaction cannot be performed using Memory ++ * Read command=4?h6. 1 = DWORD Byte Count valid ++ * (default). In PCI Mode, the memory read byte ++ * enables are automatically generated by the ++ * core. Note: N3 Master Request transaction sizes are ++ * always determined through the ++ * am_attr[<35:32>|<7:0>] field. ++ */ ++ cfg19.s.mrbcm = 1; ++ octeon_npi_write32(CVMX_NPI_PCI_CFG19, cfg19.u32); ++ } ++ ++ ++ cfg01.u32 = 0; ++ cfg01.s.msae = 1; /* Memory Space Access Enable */ ++ cfg01.s.me = 1; /* Master Enable */ ++ cfg01.s.pee = 1; /* PERR# Enable */ ++ cfg01.s.see = 1; /* System Error Enable */ ++ cfg01.s.fbbe = 1; /* Fast Back to Back Transaction Enable */ ++ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); ++ ++#ifdef USE_OCTEON_INTERNAL_ARBITER ++ /* ++ * When OCTEON is a PCI host, most systems will use OCTEON's ++ * internal arbiter, so must enable it before any PCI/PCI-X ++ * traffic can occur. ++ */ ++ { ++ union cvmx_npi_pci_int_arb_cfg pci_int_arb_cfg; ++ ++ pci_int_arb_cfg.u64 = 0; ++ pci_int_arb_cfg.s.en = 1; /* Internal arbiter enable */ ++ cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64); ++ } ++#endif /* USE_OCTEON_INTERNAL_ARBITER */ ++ ++ /* ++ * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE, ++ * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to ++ * 1..7. ++ */ ++ cfg16.u32 = 0; ++ cfg16.s.mltd = 1; /* Master Latency Timer Disable */ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG16, cfg16.u32); ++ ++ /* ++ * Should be written to 0x4ff00. MTTV -> must be zero. ++ * FLUSH -> must be 1. MRV -> should be 0xFF. ++ */ ++ cfg22.u32 = 0; ++ /* Master Retry Value [1..255] and 0=infinite */ ++ cfg22.s.mrv = 0xff; ++ /* ++ * AM_DO_FLUSH_I control NOTE: This bit MUST BE ONE for proper ++ * N3K operation. ++ */ ++ cfg22.s.flush = 1; ++ octeon_npi_write32(CVMX_NPI_PCI_CFG22, cfg22.u32); ++ ++ /* ++ * MOST Indicates the maximum number of outstanding splits (in -1 ++ * notation) when OCTEON is in PCI-X mode. PCI-X performance is ++ * affected by the MOST selection. Should generally be written ++ * with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807, ++ * depending on the desired MOST of 3, 2, 1, or 0, respectively. ++ */ ++ cfg56.u32 = 0; ++ cfg56.s.pxcid = 7; /* RO - PCI-X Capability ID */ ++ cfg56.s.ncp = 0xe8; /* RO - Next Capability Pointer */ ++ cfg56.s.dpere = 1; /* Data Parity Error Recovery Enable */ ++ cfg56.s.roe = 1; /* Relaxed Ordering Enable */ ++ cfg56.s.mmbc = 1; /* Maximum Memory Byte Count ++ [0=512B,1=1024B,2=2048B,3=4096B] */ ++ cfg56.s.most = 3; /* Maximum outstanding Split transactions [0=1 ++ .. 7=32] */ ++ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG56, cfg56.u32); ++ ++ /* ++ * Affects PCI performance when OCTEON services reads to its ++ * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are ++ * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and ++ * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700, ++ * these values need to be changed so they won't possibly prefetch off ++ * of the end of memory if PCI is DMAing a buffer at the end of ++ * memory. Note that these values differ from their reset values. ++ */ ++ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_6, 0x21); ++ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_C, 0x31); ++ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_E, 0x31); ++} ++ ++ ++/** ++ * Initialize the Octeon PCI controller ++ * ++ * Returns ++ */ ++static int __init octeon_pci_setup(void) ++{ ++ union cvmx_npi_mem_access_subidx mem_access; ++ int index; ++ ++ /* Only these chips have PCI */ ++ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) ++ return 0; ++ ++ /* Point pcibios_map_irq() to the PCI version of it */ ++ octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq; ++ ++ /* Only use the big bars on chips that support it */ ++ if (OCTEON_IS_MODEL(OCTEON_CN31XX) || ++ OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) || ++ OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) ++ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_SMALL; ++ else ++ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG; ++ ++ /* PCI I/O and PCI MEM values */ ++ set_io_port_base(OCTEON_PCI_IOSPACE_BASE); ++ ioport_resource.start = 0; ++ ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; ++ if (!octeon_is_pci_host()) { ++ pr_notice("Not in host mode, PCI Controller not initialized\n"); ++ return 0; ++ } ++ ++ pr_notice("%s Octeon big bar support\n", ++ (octeon_dma_bar_type == ++ OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling"); ++ ++ octeon_pci_initialize(); ++ ++ mem_access.u64 = 0; ++ mem_access.s.esr = 1; /* Endian-Swap on read. */ ++ mem_access.s.esw = 1; /* Endian-Swap on write. */ ++ mem_access.s.nsr = 0; /* No-Snoop on read. */ ++ mem_access.s.nsw = 0; /* No-Snoop on write. */ ++ mem_access.s.ror = 0; /* Relax Read on read. */ ++ mem_access.s.row = 0; /* Relax Order on write. */ ++ mem_access.s.ba = 0; /* PCI Address bits [63:36]. */ ++ cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, mem_access.u64); ++ ++ /* ++ * Remap the Octeon BAR 2 above all 32 bit devices ++ * (0x8000000000ul). This is done here so it is remapped ++ * before the readl()'s below. We don't want BAR2 overlapping ++ * with BAR0/BAR1 during these reads. ++ */ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0); ++ octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80); ++ ++ /* Disable the BAR1 movable mappings */ ++ for (index = 0; index < 32; index++) ++ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); ++ ++ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { ++ /* Remap the Octeon BAR 0 to 0-2GB */ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG04, 0); ++ octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); ++ ++ /* ++ * Remap the Octeon BAR 1 to map 2GB-4GB (minus the ++ * BAR 1 hole). ++ */ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30); ++ octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); ++ ++ /* Devices go after BAR1 */ ++ octeon_pci_mem_resource.start = ++ OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) - ++ (OCTEON_PCI_BAR1_HOLE_SIZE << 20); ++ octeon_pci_mem_resource.end = ++ octeon_pci_mem_resource.start + (1ul << 30); ++ } else { ++ /* Remap the Octeon BAR 0 to map 128MB-(128MB+4KB) */ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG04, 128ul << 20); ++ octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); ++ ++ /* Remap the Octeon BAR 1 to map 0-128MB */ ++ octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0); ++ octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); ++ ++ /* Devices go after BAR0 */ ++ octeon_pci_mem_resource.start = ++ OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) + ++ (4ul << 10); ++ octeon_pci_mem_resource.end = ++ octeon_pci_mem_resource.start + (1ul << 30); ++ } ++ ++ register_pci_controller(&octeon_pci_controller); ++ ++ /* ++ * Clear any errors that might be pending from before the bus ++ * was setup properly. ++ */ ++ cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1); ++ return 0; ++} ++ ++arch_initcall(octeon_pci_setup); +--- /dev/null ++++ b/arch/mips/cavium-octeon/pcie.c +@@ -0,0 +1,441 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2007, 2008 Cavium Networks ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "pci-common.h" ++ ++/** ++ * Map a PCI device to the appropriate interrupt line ++ * ++ * @param dev The Linux PCI device structure for the device to map ++ * @param slot The slot number for this device on __BUS 0__. Linux ++ * enumerates through all the bridges and figures out the ++ * slot on Bus 0 where this device eventually hooks to. ++ * @param pin The PCI interrupt pin read from the device, then swizzled ++ * as it goes through each bridge. ++ * @return Interrupt number for the device ++ */ ++int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, ++ u8 slot, u8 pin) ++{ ++ /* ++ * The EBH5600 board with the PCI to PCIe bridge mistakenly ++ * wires the first slot for both device id 2 and interrupt ++ * A. According to the PCI spec, device id 2 should be C. The ++ * following kludge attempts to fix this. ++ */ ++ if (strstr(octeon_board_type_string(), "EBH5600") && ++ dev->bus && dev->bus->parent) { ++ /* ++ * Iterate all the way up the device chain and find ++ * the root bus. ++ */ ++ while (dev->bus && dev->bus->parent) ++ dev = to_pci_dev(dev->bus->bridge); ++ /* If the root bus is number 0 and the PEX 8114 is the ++ * root, assume we are behind the miswired bus. We ++ * need to correct the swizzle level by two. Yuck. ++ */ ++ if ((dev->bus->number == 0) && ++ (dev->vendor == 0x10b5) && (dev->device == 0x8114)) { ++ /* ++ * The pin field is one based, not zero. We ++ * need to swizzle it by minus two. ++ */ ++ pin = ((pin - 3) & 3) + 1; ++ } ++ } ++ /* ++ * The -1 is because pin starts with one, not zero. It might ++ * be that this equation needs to include the slot number, but ++ * I don't have hardware to check that against. ++ */ ++ return pin - 1 + OCTEON_IRQ_PCI_INT0; ++} ++ ++/** ++ * Read a value from configuration space ++ * ++ * @param bus ++ * @param devfn ++ * @param reg ++ * @param size ++ * @param val ++ * @return ++ */ ++static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, ++ unsigned int devfn, int reg, int size, ++ u32 *val) ++{ ++ union octeon_cvmemctl cvmmemctl; ++ union octeon_cvmemctl cvmmemctl_save; ++ int bus_number = bus->number; ++ ++ /* ++ * We need to force the bus number to be zero on the root ++ * bus. Linux numbers the 2nd root bus to start after all ++ * buses on root 0. ++ */ ++ if (bus->parent == NULL) ++ bus_number = 0; ++ ++ /* ++ * PCIe only has a single device connected to Octeon. It is ++ * always device ID 0. Don't bother doing reads for other ++ * device IDs on the first segment. ++ */ ++ if ((bus_number == 0) && (devfn >> 3 != 0)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ ++ /* ++ * The following is a workaround for the CN57XX, CN56XX, ++ * CN55XX, and CN54XX errata with PCIe config reads from non ++ * existent devices. These chips will hang the PCIe link if a ++ * config read is performed that causes a UR response. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || ++ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) { ++ /* ++ * For our EBH5600 board, port 0 has a bridge with two ++ * PCI-X slots. We need a new special checks to make ++ * sure we only probe valid stuff. The PCIe->PCI-X ++ * bridge only respondes to device ID 0, function ++ * 0-1 ++ */ ++ if ((bus_number == 0) && (devfn >= 2)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ /* ++ * The PCI-X slots are device ID 2,3. Choose one of ++ * the below "if" blocks based on what is plugged into ++ * the board. ++ */ ++#if 1 ++ /* Use this option if you aren't using either slot */ ++ if (bus_number == 1) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++#elif 0 ++ /* ++ * Use this option if you are using the first slot but ++ * not the second. ++ */ ++ if ((bus_number == 1) && (devfn >> 3 != 2)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++#elif 0 ++ /* ++ * Use this option if you are using the second slot ++ * but not the first. ++ */ ++ if ((bus_number == 1) && (devfn >> 3 != 3)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++#elif 0 ++ /* Use this opion if you are using both slots */ ++ if ((bus_number == 1) && ++ !((devfn == (2 << 3)) || (devfn == (3 << 3)))) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++#endif ++ ++ /* ++ * The following #if gives a more complicated ++ * example. This is the required checks for running a ++ * Nitrox CN16XX-NHBX in the slot of the EBH5600. This ++ * card has a PLX PCIe bridge with four Nitrox PLX ++ * parts behind it. ++ */ ++#if 0 ++ /* PLX bridge with 4 ports */ ++ if ((bus_number == 3) && ++ !((devfn >> 3 >= 1) && (devfn >> 3 <= 4))) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ /* Nitrox behind PLX 1 */ ++ if ((bus_number == 4) && (devfn >> 3 != 0)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ /* Nitrox behind PLX 2 */ ++ if ((bus_number == 5) && (devfn >> 3 != 0)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ /* Nitrox behind PLX 3 */ ++ if ((bus_number == 6) && (devfn >> 3 != 0)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ /* Nitrox behind PLX 4 */ ++ if ((bus_number == 7) && (devfn >> 3 != 0)) ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++#endif ++ /* ++ * Shorten the DID timeout so bus errors for PCIe ++ * config reads from non existent devices happen ++ * faster. This allows us to continue booting even if ++ * the above "if" checks are wrong. Once one of these ++ * errors happens, the PCIe port is dead. ++ */ ++ cvmmemctl_save.u64 = __read_64bit_c0_register($11, 7); ++ cvmmemctl.u64 = cvmmemctl_save.u64; ++ cvmmemctl.s.didtto = 2; ++ __write_64bit_c0_register($11, 7, cvmmemctl.u64); ++ } ++ ++ switch (size) { ++ case 4: ++ *val = cvmx_pcie_config_read32(pcie_port, bus_number, ++ devfn >> 3, devfn & 0x7, reg); ++ break; ++ case 2: ++ *val = cvmx_pcie_config_read16(pcie_port, bus_number, ++ devfn >> 3, devfn & 0x7, reg); ++ break; ++ case 1: ++ *val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3, ++ devfn & 0x7, reg); ++ break; ++ default: ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++ } ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || ++ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) ++ __write_64bit_c0_register($11, 7, cvmmemctl_save.u64); ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int octeon_pcie0_read_config(struct pci_bus *bus, unsigned int devfn, ++ int reg, int size, u32 *val) ++{ ++ return octeon_pcie_read_config(0, bus, devfn, reg, size, val); ++} ++ ++static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn, ++ int reg, int size, u32 *val) ++{ ++ return octeon_pcie_read_config(1, bus, devfn, reg, size, val); ++} ++ ++ ++ ++/** ++ * Write a value to PCI configuration space ++ * ++ * @param bus ++ * @param devfn ++ * @param reg ++ * @param size ++ * @param val ++ * @return ++ */ ++static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus, ++ unsigned int devfn, int reg, ++ int size, u32 val) ++{ ++ int bus_number = bus->number; ++ /* ++ * We need to force the bus number to be zero on the root ++ * bus. Linux numbers the 2nd root bus to start after all ++ * busses on root 0. ++ */ ++ if (bus->parent == NULL) ++ bus_number = 0; ++ ++ switch (size) { ++ case 4: ++ cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3, ++ devfn & 0x7, reg, val); ++ return PCIBIOS_SUCCESSFUL; ++ case 2: ++ cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3, ++ devfn & 0x7, reg, val); ++ return PCIBIOS_SUCCESSFUL; ++ case 1: ++ cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3, ++ devfn & 0x7, reg, val); ++ return PCIBIOS_SUCCESSFUL; ++ } ++#if PCI_CONFIG_SPACE_DELAY ++ udelay(PCI_CONFIG_SPACE_DELAY); ++#endif ++ return PCIBIOS_FUNC_NOT_SUPPORTED; ++} ++ ++static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn, ++ int reg, int size, u32 val) ++{ ++ return octeon_pcie_write_config(0, bus, devfn, reg, size, val); ++} ++ ++static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn, ++ int reg, int size, u32 val) ++{ ++ return octeon_pcie_write_config(1, bus, devfn, reg, size, val); ++} ++ ++static struct pci_ops octeon_pcie0_ops = { ++ octeon_pcie0_read_config, ++ octeon_pcie0_write_config, ++}; ++ ++static struct resource octeon_pcie0_mem_resource = { ++ .name = "Octeon PCIe0 MEM", ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct resource octeon_pcie0_io_resource = { ++ .name = "Octeon PCIe0 IO", ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller octeon_pcie0_controller = { ++ .pci_ops = &octeon_pcie0_ops, ++ .mem_resource = &octeon_pcie0_mem_resource, ++ .io_resource = &octeon_pcie0_io_resource, ++}; ++ ++static struct pci_ops octeon_pcie1_ops = { ++ octeon_pcie1_read_config, ++ octeon_pcie1_write_config, ++}; ++ ++static struct resource octeon_pcie1_mem_resource = { ++ .name = "Octeon PCIe1 MEM", ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct resource octeon_pcie1_io_resource = { ++ .name = "Octeon PCIe1 IO", ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller octeon_pcie1_controller = { ++ .pci_ops = &octeon_pcie1_ops, ++ .mem_resource = &octeon_pcie1_mem_resource, ++ .io_resource = &octeon_pcie1_io_resource, ++}; ++ ++ ++/** ++ * Initialize the Octeon PCIe controllers ++ * ++ * @return ++ */ ++static int __init octeon_pcie_setup(void) ++{ ++ union cvmx_npei_ctl_status npei_ctl_status; ++ int result; ++ ++ /* These chips don't have PCIe */ ++ if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) ++ return 0; ++ ++ /* Point pcibios_map_irq() to the PCIe version of it */ ++ octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq; ++ ++ /* Use the PCIe based DMA mappings */ ++ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE; ++ ++ /* ++ * PCIe I/O range. It is based on port 0 but includes up until ++ * port 1's end. ++ */ ++ set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0))); ++ ioport_resource.start = 0; ++ ioport_resource.end = ++ cvmx_pcie_get_io_base_address(1) - ++ cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1; ++ ++ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); ++ if (npei_ctl_status.s.host_mode) { ++ pr_notice("PCIe: Initializing port 0\n"); ++ result = cvmx_pcie_rc_initialize(0); ++ if (result == 0) { ++ /* Memory offsets are physical addresses */ ++ octeon_pcie0_controller.mem_offset = ++ cvmx_pcie_get_mem_base_address(0); ++ /* IO offsets are Mips virtual addresses */ ++ octeon_pcie0_controller.io_map_base = ++ CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address ++ (0)); ++ octeon_pcie0_controller.io_offset = 0; ++ /* ++ * To keep things similar to PCI, we start ++ * device addresses at the same place as PCI ++ * uisng big bar support. This normally ++ * translates to 4GB-256MB, which is the same ++ * as most x86 PCs. ++ */ ++ octeon_pcie0_controller.mem_resource->start = ++ cvmx_pcie_get_mem_base_address(0) + ++ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); ++ octeon_pcie0_controller.mem_resource->end = ++ cvmx_pcie_get_mem_base_address(0) + ++ cvmx_pcie_get_mem_size(0) - 1; ++ /* ++ * Ports must be above 16KB for the ISA bus ++ * filtering in the PCI-X to PCI bridge. ++ */ ++ octeon_pcie0_controller.io_resource->start = 4 << 10; ++ octeon_pcie0_controller.io_resource->end = ++ cvmx_pcie_get_io_size(0) - 1; ++ register_pci_controller(&octeon_pcie0_controller); ++ } ++ } else { ++ pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n"); ++ } ++ ++ /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ union cvmx_npei_dbg_data npei_dbg_data; ++ npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); ++ if (npei_dbg_data.cn52xx.qlm0_link_width) ++ return 0; ++ } ++ ++ pr_notice("PCIe: Initializing port 1\n"); ++ result = cvmx_pcie_rc_initialize(1); ++ if (result == 0) { ++ /* Memory offsets are physical addresses */ ++ octeon_pcie1_controller.mem_offset = ++ cvmx_pcie_get_mem_base_address(1); ++ /* IO offsets are Mips virtual addresses */ ++ octeon_pcie1_controller.io_map_base = ++ CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1)); ++ octeon_pcie1_controller.io_offset = ++ cvmx_pcie_get_io_base_address(1) - ++ cvmx_pcie_get_io_base_address(0); ++ /* ++ * To keep things similar to PCI, we start device ++ * addresses at the same place as PCI uisng big bar ++ * support. This normally translates to 4GB-256MB, ++ * which is the same as most x86 PCs. ++ */ ++ octeon_pcie1_controller.mem_resource->start = ++ cvmx_pcie_get_mem_base_address(1) + (4ul << 30) - ++ (OCTEON_PCI_BAR1_HOLE_SIZE << 20); ++ octeon_pcie1_controller.mem_resource->end = ++ cvmx_pcie_get_mem_base_address(1) + ++ cvmx_pcie_get_mem_size(1) - 1; ++ /* ++ * Ports must be above 16KB for the ISA bus filtering ++ * in the PCI-X to PCI bridge. ++ */ ++ octeon_pcie1_controller.io_resource->start = ++ cvmx_pcie_get_io_base_address(1) - ++ cvmx_pcie_get_io_base_address(0); ++ octeon_pcie1_controller.io_resource->end = ++ octeon_pcie1_controller.io_resource->start + ++ cvmx_pcie_get_io_size(1) - 1; ++ register_pci_controller(&octeon_pcie1_controller); ++ } ++ return 0; ++} ++ ++arch_initcall(octeon_pcie_setup); +--- a/arch/mips/include/asm/octeon/cvmx-asm.h ++++ b/arch/mips/include/asm/octeon/cvmx-asm.h +@@ -119,7 +119,8 @@ + asm ("pop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) + #define CVMX_DPOP(result, input) \ + asm ("dpop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) +- ++#define CVMX_CLZ(result, input) \ ++ asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) + /* some new cop0-like stuff */ + #define CVMX_RDHWR(result, regstr) \ + asm volatile ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result)) +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-helper-errata.h +@@ -0,0 +1,92 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Fixes and workaround for Octeon chip errata. This file ++ * contains functions called by cvmx-helper to workaround known ++ * chip errata. For the most part, code doesn't need to call ++ * these functions directly. ++ * ++ */ ++#ifndef __CVMX_HELPER_ERRATA_H__ ++#define __CVMX_HELPER_ERRATA_H__ ++ ++ ++#include "cvmx-wqe.h" ++ ++/** ++ * @INTERNAL ++ * Function to adjust internal IPD pointer alignments ++ * ++ * Returns 0 on success ++ * !0 on failure ++ */ ++extern int __cvmx_helper_errata_fix_ipd_ptr_alignment(void); ++ ++/** ++ * @INTERNAL ++ * Workaround ASX setup errata with CN38XX pass1 ++ * ++ * @interface: Interface to setup ++ * @port: Port to setup (0..3) ++ * @cpu_clock_hz: ++ * Chip frequency in Hertz ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_errata_asx_pass1(int interface, int port, ++ int cpu_clock_hz); ++ ++/** ++ * This function needs to be called on all Octeon chips with ++ * errata PKI-100. ++ * ++ * The Size field is 8 too large in WQE and next pointers ++ * ++ * The Size field generated by IPD is 8 larger than it should ++ * be. The Size field is <55:40> of both: ++ * - WORD3 in the work queue entry, and ++ * - the next buffer pointer (which precedes the packet data ++ * in each buffer). ++ * ++ * @work: Work queue entry to fix ++ * Returns Zero on success. Negative on failure ++ */ ++extern int cvmx_helper_fix_ipd_packet_chain(struct cvmx_wqe *work); ++ ++/** ++ * Due to errata G-720, the 2nd order CDR circuit on CN52XX pass ++ * 1 doesn't work properly. The following code disables 2nd order ++ * CDR for the specified QLM. ++ * ++ * @qlm: QLM to disable 2nd order CDR for. ++ */ ++extern void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm); ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-helper-util.h +@@ -0,0 +1,266 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Small helper utilities. ++ * ++ */ ++ ++#ifndef __CVMX_HELPER_UTIL_H__ ++#define __CVMX_HELPER_UTIL_H__ ++ ++#ifdef CVMX_ENABLE_HELPER_FUNCTIONS ++ ++/** ++ * Convert a interface mode into a human readable string ++ * ++ * @mode: Mode to convert ++ * ++ * Returns String ++ */ ++extern const char ++ *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode); ++ ++/** ++ * Debug routine to dump the packet structure to the console ++ * ++ * @work: Work queue entry containing the packet to dump ++ * Returns ++ */ ++extern int cvmx_helper_dump_packet(cvmx_wqe_t *work); ++ ++/** ++ * Setup Random Early Drop on a specific input queue ++ * ++ * @queue: Input queue to setup RED on (0-7) ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++extern int cvmx_helper_setup_red_queue(int queue, int pass_thresh, ++ int drop_thresh); ++ ++/** ++ * Setup Random Early Drop to automatically begin dropping packets. ++ * ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++extern int cvmx_helper_setup_red(int pass_thresh, int drop_thresh); ++ ++/** ++ * Get the version of the CVMX libraries. ++ * ++ * Returns Version string. Note this buffer is allocated statically ++ * and will be shared by all callers. ++ */ ++extern const char *cvmx_helper_get_version(void); ++ ++/** ++ * @INTERNAL ++ * Setup the common GMX settings that determine the number of ++ * ports. These setting apply to almost all configurations of all ++ * chips. ++ * ++ * @interface: Interface to configure ++ * @num_ports: Number of ports on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_setup_gmx(int interface, int num_ports); ++ ++/** ++ * Returns the IPD/PKO port number for a port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * @port: Port on the interface ++ * ++ * Returns IPD/PKO port number ++ */ ++extern int cvmx_helper_get_ipd_port(int interface, int port); ++ ++/** ++ * Returns the IPD/PKO port number for the first port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * ++ * Returns IPD/PKO port number ++ */ ++static inline int cvmx_helper_get_first_ipd_port(int interface) ++{ ++ return cvmx_helper_get_ipd_port(interface, 0); ++} ++ ++/** ++ * Returns the IPD/PKO port number for the last port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * ++ * Returns IPD/PKO port number ++ */ ++static inline int cvmx_helper_get_last_ipd_port(int interface) ++{ ++ extern int cvmx_helper_ports_on_interface(int interface); ++ ++ return cvmx_helper_get_first_ipd_port(interface) + ++ cvmx_helper_ports_on_interface(interface) - 1; ++} ++ ++/** ++ * Free the packet buffers contained in a work queue entry. ++ * The work queue entry is not freed. ++ * ++ * @work: Work queue entry with packet to free ++ */ ++static inline void cvmx_helper_free_packet_data(cvmx_wqe_t *work) ++{ ++ uint64_t number_buffers; ++ cvmx_buf_ptr_t buffer_ptr; ++ cvmx_buf_ptr_t next_buffer_ptr; ++ uint64_t start_of_buffer; ++ ++ number_buffers = work->word2.s.bufs; ++ if (number_buffers == 0) ++ return; ++ buffer_ptr = work->packet_ptr; ++ ++ /* ++ * Since the number of buffers is not zero, we know this is ++ * not a dynamic short packet. We need to check if it is a ++ * packet received with IPD_CTL_STATUS[NO_WPTR]. If this is ++ * true, we need to free all buffers except for the first ++ * one. The caller doesn't expect their WQE pointer to be ++ * freed. ++ */ ++ start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; ++ if (cvmx_ptr_to_phys(work) == start_of_buffer) { ++ next_buffer_ptr = ++ *(cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); ++ buffer_ptr = next_buffer_ptr; ++ number_buffers--; ++ } ++ ++ while (number_buffers--) { ++ /* ++ * Remember the back pointer is in cache lines, not ++ * 64bit words. ++ */ ++ start_of_buffer = ++ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; ++ /* ++ * Read pointer to next buffer before we free the ++ * current buffer. ++ */ ++ next_buffer_ptr = ++ *(cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); ++ cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer), ++ buffer_ptr.s.pool, 0); ++ buffer_ptr = next_buffer_ptr; ++ } ++} ++ ++#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ ++ ++/** ++ * Returns the interface number for an IPD/PKO port number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface number ++ */ ++extern int cvmx_helper_get_interface_num(int ipd_port); ++ ++/** ++ * Returns the interface index number for an IPD/PKO port ++ * number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface index number ++ */ ++extern int cvmx_helper_get_interface_index_num(int ipd_port); ++ ++/** ++ * Initialize the internal QLM JTAG logic to allow programming ++ * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions. ++ * These functions should only be used at the direction of Cavium ++ * Networks. Programming incorrect values into the JTAG chain ++ * can cause chip damage. ++ */ ++extern void cvmx_helper_qlm_jtag_init(void); ++ ++/** ++ * Write up to 32bits into the QLM jtag chain. Bits are shifted ++ * into the MSB and out the LSB, so you should shift in the low ++ * order bits followed by the high order bits. The JTAG chain is ++ * 4 * 268 bits long, or 1072. ++ * ++ * @qlm: QLM to shift value into ++ * @bits: Number of bits to shift in (1-32). ++ * @data: Data to shift in. Bit 0 enters the chain first, followed by ++ * bit 1, etc. ++ * ++ * Returns The low order bits of the JTAG chain that shifted out of the ++ * circle. ++ */ ++extern uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data); ++ ++/** ++ * Shift long sequences of zeros into the QLM JTAG chain. It is ++ * common to need to shift more than 32 bits of zeros into the ++ * chain. This function is a convience wrapper around ++ * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of ++ * zeros at a time. ++ * ++ * @qlm: QLM to shift zeros into ++ * @bits: ++ */ ++extern void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits); ++ ++/** ++ * Program the QLM JTAG chain into all lanes of the QLM. You must ++ * have already shifted in 268*4, or 1072 bits into the JTAG ++ * chain. Updating invalid values can possibly cause chip damage. ++ * ++ * @qlm: QLM to program ++ */ ++extern void cvmx_helper_qlm_jtag_update(int qlm); ++ ++#endif /* __CVMX_HELPER_H__ */ +--- a/arch/mips/include/asm/octeon/cvmx-packet.h ++++ b/arch/mips/include/asm/octeon/cvmx-packet.h +@@ -25,7 +25,8 @@ + * Contact Cavium Networks for more information + ***********************license end**************************************/ + +-/* ++/** ++ * + * Packet buffer defines. + */ + +@@ -39,18 +40,23 @@ union cvmx_buf_ptr { + void *ptr; + uint64_t u64; + struct { +- /* if set, invert the "free" pick of the overall ++ /* ++ * If set, invert the "free" pick of the overall + * packet. HW always sets this bit to 0 on inbound +- * packet */ ++ * packet. ++ */ + uint64_t i:1; + +- /* Indicates the amount to back up to get to the ++ /* ++ * Indicates the amount to back up to get to the + * buffer start in cache lines. In most cases this is + * less than one complete cache line, so the value is +- * zero */ ++ * zero. ++ */ + uint64_t back:4; + /* The pool that the buffer came from / goes to */ + uint64_t pool:3; ++ + /* The size of the segment pointed to by addr (in bytes) */ + uint64_t size:16; + /* Pointer to the first byte of the data, NOT buffer */ +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-pcie.h +@@ -0,0 +1,284 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Interface to PCIe as a host(RC) or target(EP) ++ * ++ */ ++ ++#ifndef __CVMX_PCIE_H__ ++#define __CVMX_PCIE_H__ ++ ++union cvmx_pcie_address { ++ uint64_t u64; ++ struct { ++ uint64_t upper:2; /* Normally 2 for XKPHYS */ ++ uint64_t reserved_49_61:13; /* Must be zero */ ++ uint64_t io:1; /* 1 for IO space access */ ++ uint64_t did:5; /* PCIe DID = 3 */ ++ uint64_t subdid:3; /* PCIe SubDID = 1 */ ++ uint64_t reserved_36_39:4; /* Must be zero */ ++ uint64_t es:2; /* Endian swap = 1 */ ++ uint64_t port:2; /* PCIe port 0,1 */ ++ uint64_t reserved_29_31:3; /* Must be zero */ ++ /* ++ * Selects the type of the configuration request (0 = type 0, ++ * 1 = type 1). ++ */ ++ uint64_t ty:1; ++ /* Target bus number sent in the ID in the request. */ ++ uint64_t bus:8; ++ /* ++ * Target device number sent in the ID in the ++ * request. Note that Dev must be zero for type 0 ++ * configuration requests. ++ */ ++ uint64_t dev:5; ++ /* Target function number sent in the ID in the request. */ ++ uint64_t func:3; ++ /* ++ * Selects a register in the configuration space of ++ * the target. ++ */ ++ uint64_t reg:12; ++ } config; ++ struct { ++ uint64_t upper:2; /* Normally 2 for XKPHYS */ ++ uint64_t reserved_49_61:13; /* Must be zero */ ++ uint64_t io:1; /* 1 for IO space access */ ++ uint64_t did:5; /* PCIe DID = 3 */ ++ uint64_t subdid:3; /* PCIe SubDID = 2 */ ++ uint64_t reserved_36_39:4; /* Must be zero */ ++ uint64_t es:2; /* Endian swap = 1 */ ++ uint64_t port:2; /* PCIe port 0,1 */ ++ uint64_t address:32; /* PCIe IO address */ ++ } io; ++ struct { ++ uint64_t upper:2; /* Normally 2 for XKPHYS */ ++ uint64_t reserved_49_61:13; /* Must be zero */ ++ uint64_t io:1; /* 1 for IO space access */ ++ uint64_t did:5; /* PCIe DID = 3 */ ++ uint64_t subdid:3; /* PCIe SubDID = 3-6 */ ++ uint64_t reserved_36_39:4; /* Must be zero */ ++ uint64_t address:36; /* PCIe Mem address */ ++ } mem; ++}; ++ ++/** ++ * Return the Core virtual base address for PCIe IO access. IOs are ++ * read/written as an offset from this address. ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns 64bit Octeon IO base address for read/write ++ */ ++uint64_t cvmx_pcie_get_io_base_address(int pcie_port); ++ ++/** ++ * Size of the IO address region returned at address ++ * cvmx_pcie_get_io_base_address() ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns Size of the IO window ++ */ ++uint64_t cvmx_pcie_get_io_size(int pcie_port); ++ ++/** ++ * Return the Core virtual base address for PCIe MEM access. Memory is ++ * read/written as an offset from this address. ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns 64bit Octeon IO base address for read/write ++ */ ++uint64_t cvmx_pcie_get_mem_base_address(int pcie_port); ++ ++/** ++ * Size of the Mem address region returned at address ++ * cvmx_pcie_get_mem_base_address() ++ * ++ * @pcie_port: PCIe port the IO is for ++ * ++ * Returns Size of the Mem window ++ */ ++uint64_t cvmx_pcie_get_mem_size(int pcie_port); ++ ++/** ++ * Initialize a PCIe port for use in host(RC) mode. It doesn't ++ * enumerate the bus. ++ * ++ * @pcie_port: PCIe port to initialize ++ * ++ * Returns Zero on success ++ */ ++int cvmx_pcie_rc_initialize(int pcie_port); ++ ++/** ++ * Shutdown a PCIe port and put it in reset ++ * ++ * @pcie_port: PCIe port to shutdown ++ * ++ * Returns Zero on success ++ */ ++int cvmx_pcie_rc_shutdown(int pcie_port); ++ ++/** ++ * Read 8bits from a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns Result of the read ++ */ ++uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, int fn, ++ int reg); ++ ++/** ++ * Read 16bits from a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns Result of the read ++ */ ++uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, ++ int reg); ++ ++/** ++ * Read 32bits from a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * ++ * Returns Result of the read ++ */ ++uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, ++ int reg); ++ ++/** ++ * Write 8bits to a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * @val: Value to write ++ */ ++void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, int reg, ++ uint8_t val); ++ ++/** ++ * Write 16bits to a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * @val: Value to write ++ */ ++void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, int reg, ++ uint16_t val); ++ ++/** ++ * Write 32bits to a Device's config space ++ * ++ * @pcie_port: PCIe port the device is on ++ * @bus: Sub bus ++ * @dev: Device ID ++ * @fn: Device sub function ++ * @reg: Register to access ++ * @val: Value to write ++ */ ++void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, int reg, ++ uint32_t val); ++ ++/** ++ * Read a PCIe config space register indirectly. This is used for ++ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. ++ * ++ * @pcie_port: PCIe port to read from ++ * @cfg_offset: Address to read ++ * ++ * Returns Value read ++ */ ++uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset); ++ ++/** ++ * Write a PCIe config space register indirectly. This is used for ++ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. ++ * ++ * @pcie_port: PCIe port to write to ++ * @cfg_offset: Address to write ++ * @val: Value to write ++ */ ++void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val); ++ ++/** ++ * Write a 32bit value to the Octeon NPEI register space ++ * ++ * @address: Address to write to ++ * @val: Value to write ++ */ ++static inline void cvmx_pcie_npei_write32(uint64_t address, uint32_t val) ++{ ++ cvmx_write64_uint32(address ^ 4, val); ++ cvmx_read64_uint32(address ^ 4); ++} ++ ++/** ++ * Read a 32bit value from the Octeon NPEI register space ++ * ++ * @address: Address to read ++ * Returns The result ++ */ ++static inline uint32_t cvmx_pcie_npei_read32(uint64_t address) ++{ ++ return cvmx_read64_uint32(address ^ 4); ++} ++ ++/** ++ * Initialize a PCIe port for use in target(EP) mode. ++ * ++ * Returns Zero on success ++ */ ++int cvmx_pcie_ep_initialize(void); ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-wqe.h +@@ -0,0 +1,422 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * This header file defines the work queue entry (wqe) data structure. ++ * Since this is a commonly used structure that depends on structures ++ * from several hardware blocks, those definitions have been placed ++ * in this file to create a single point of definition of the wqe ++ * format. ++ * ++ * Data structures are still named according to the block that they ++ * relate to. ++ * ++ */ ++ ++#ifndef __CVMX_WQE_H__ ++#define __CVMX_WQE_H__ ++ ++#include "cvmx-packet.h" ++ ++#define OCT_TAG_TYPE_STRING(x) ( \ ++ { \ ++ const char *r; \ ++ switch (x) { \ ++ case CVMX_POW_TAG_TYPE_ORDERED: \ ++ r = "ORDERED"; \ ++ break; \ ++ case CVMX_POW_TAG_TYPE_ATOMIC: \ ++ r = "ATOMIC"; \ ++ break; \ ++ case CVMX_POW_TAG_TYPE_NULL: \ ++ r = "NULL"; \ ++ break; \ ++ default: \ ++ r = "NULL_NULL"; \ ++ break; \ ++ } \ ++ r; \ ++ }) ++ ++/** ++ * HW decode / err_code in work queue entry ++ */ ++union cvmx_pip_wqe_word2{ ++ uint64_t u64; ++ ++ /* Use this struct if the hardware determines that the packet is IP */ ++ struct { ++ /* HW sets this to the number of buffers used by this packet */ ++ uint64_t bufs:8; ++ /* HW sets to the number of L2 bytes prior to the IP */ ++ uint64_t ip_offset:8; ++ /* Set to 1 if we found VLAN in the L2 */ ++ uint64_t vlan_valid:1; ++ uint64_t unassigned:2; ++ /* HW sets to the VLAN CFI flag (valid when vlan_valid) */ ++ uint64_t vlan_cfi:1; ++ /* HW sets to the VLAN_ID field (valid when vlan_valid) */ ++ uint64_t vlan_id:12; ++ ++ uint64_t unassigned2:12; ++ /* The packet needs to be decompressed */ ++ uint64_t dec_ipcomp:1; ++ /* The packet is either TCP or UDP */ ++ uint64_t tcp_or_udp:1; ++ /* The packet needs to be decrypted (ESP or AH) */ ++ uint64_t dec_ipsec:1; ++ /* The packet is IPv6 */ ++ uint64_t is_v6:1; ++ ++ /* ++ * rcv_error, not_IP, IP_exc, is_frag, L4_error, ++ * software, etc. ++ */ ++ ++ /* ++ * Reserved for software use, hardware will clear on ++ * packet creation. ++ */ ++ uint64_t software:1; ++ /* exceptional conditions below. */ ++ ++ /* ++ * The receive interface hardware detected an L4 error ++ * (only applies if !is_frag) (only applies if ++ * !rcv_error && !not_IP && !IP_exc && !is_frag) ++ * failure indicated in err_code below, decode: ++ * ++ * - 1 = Malformed L4 ++ * ++ * - 2 = L4 Checksum Error: the L4 checksum value is ++ * ++ * - 3 = UDP Length Error: The UDP length field would ++ * make the UDP data longer than what remains in ++ * the IP packet (as defined by the IP header ++ * length field). ++ * ++ * - 4 = Bad L4 Port: either the source or destination ++ * TCP/UDP port is 0. ++ * ++ * - 8 = TCP FIN Only: the packet is TCP and only the ++ * FIN flag set. ++ * ++ * - 9 = TCP No Flags: the packet is TCP and no flags ++ * are set. ++ * ++ * - 10 = TCP FIN RST: the packet is TCP and both FIN ++ * and RST are set. ++ * ++ * - 11 = TCP SYN URG: the packet is TCP and both SYN ++ * and URG are set. ++ * ++ * - 12 = TCP SYN RST: the packet is TCP and both SYN ++ * and RST are set. ++ * ++ * - 13 = TCP SYN FIN: the packet is TCP and both SYN ++ * and FIN are set. ++ * ++ */ ++ uint64_t L4_error:1; ++ /* Set if the packet is a fragment */ ++ uint64_t is_frag:1; ++ ++ /* ++ * The receive interface hardware detected an IP error ++ * / exception (only applies if !rcv_error && !not_IP) ++ * failure indicated in err_code below, decode: ++ * ++ * - 1 = Not IP: the IP version field is neither 4 nor ++ * 6. ++ * ++ * - 2 = IPv4 Header Checksum Error: the IPv4 header ++ * has a checksum violation. ++ * ++ * - 3 = IP Malformed Header: the packet is not long ++ * enough to contain the IP header. ++ * ++ * - 4 = IP Malformed: the packet is not long enough ++ * to contain the bytes indicated by the IP ++ * header. Pad is allowed. ++ * ++ * - 5 = IP TTL Hop: the IPv4 TTL field or the IPv6 ++ * Hop Count field are zero. ++ * ++ * - 6 = IP Options. ++ */ ++ uint64_t IP_exc:1; ++ /* ++ * Set if the hardware determined that the packet is a ++ * broadcast. ++ */ ++ uint64_t is_bcast:1; ++ /* ++ * Set if the hardware determined that the packet is a ++ * multi-cast. ++ */ ++ uint64_t is_mcast:1; ++ /* ++ * Set if the packet may not be IP (must be zero in ++ * this case). ++ */ ++ uint64_t not_IP:1; ++ /* ++ * The receive interface hardware detected a receive ++ * error (must be zero in this case) ++ * ++ * lower err_code = first-level descriptor of the work ++ * ++ * zero for packet submitted by hardware that isn't on ++ * the slow path. ++ */ ++ uint64_t rcv_error:1; ++ ++ /* Type is cvmx_pip_err_t */ ++ uint64_t err_code:8; ++ } s; ++ ++ /* Use this to get at the 16 vlan bits */ ++ struct { ++ uint64_t unused1:16; ++ uint64_t vlan:16; ++ uint64_t unused2:32; ++ } svlan; ++ ++ /* ++ * Use this struct if the hardware could not determine that ++ * the packet is ip. ++ */ ++ struct { ++ /* HW sets this to the number of buffers used by this packet. */ ++ uint64_t bufs:8; ++ uint64_t unused:8; ++ /* Set to 1 if we found VLAN in the L2. */ ++ uint64_t vlan_valid:1; ++ uint64_t unassigned:2; ++ /* HW sets to the VLAN CFI flag (valid when vlan_valid). */ ++ uint64_t vlan_cfi:1; ++ /* HW sets to the VLAN_ID field (valid when vlan_valid). */ ++ uint64_t vlan_id:12; ++ ++ uint64_t unassigned2:16; ++ /* ++ * Reserved for software use, hardware will clear on ++ * packet creation. ++ */ ++ uint64_t software:1; ++ uint64_t unassigned3:1; ++ /* Set if the hardware determined that the packet is rarp. */ ++ uint64_t is_rarp:1; ++ /* Set if the hardware determined that the packet is arp. */ ++ uint64_t is_arp:1; ++ /* ++ * Set if the hardware determined that the packet is a ++ * broadcast. ++ */ ++ uint64_t is_bcast:1; ++ /* ++ * Set if the hardware determined that the packet is a ++ * multi-cast. ++ */ ++ uint64_t is_mcast:1; ++ /* ++ * Set if the packet may not be IP (must be one in ++ * this case). ++ */ ++ uint64_t not_IP:1; ++ /* ++ * The receive interface hardware detected a receive ++ * error. Failure indicated in err_code below, decode: ++ * ++ * - 1 = partial error: a packet was partially ++ * received, but internal buffering / bandwidth ++ * was not adequate to receive the entire ++ * packet. ++ * ++ * - 2 = jabber error: the RGMII packet was too large ++ * and is truncated. ++ * ++ * - 3 = overrun error: the RGMII packet is longer ++ * than allowed and had an FCS error. ++ * ++ * - 4 = oversize error: the RGMII packet is longer ++ * than allowed. ++ * ++ * - 5 = alignment error: the RGMII packet is not an ++ * integer number of bytes and had an FCS error ++ * (100M and 10M only). ++ * ++ * - 6 = fragment error: the RGMII packet is shorter ++ * than allowed and had an FCS error. ++ * ++ * - 7 = GMX FCS error: the RGMII packet had an FCS ++ * error. ++ * ++ * - 8 = undersize error: the RGMII packet is shorter ++ * than allowed. ++ * ++ * - 9 = extend error: the RGMII packet had an extend ++ * error. ++ * ++ * - 10 = length mismatch error: the RGMII packet had ++ * a length that did not match the length field ++ * in the L2 HDR. ++ * ++ * - 11 = RGMII RX error/SPI4 DIP4 Error: the RGMII ++ * packet had one or more data reception errors ++ * (RXERR) or the SPI4 packet had one or more ++ * DIP4 errors. ++ * ++ * - 12 = RGMII skip error/SPI4 Abort Error: the RGMII ++ * packet was not large enough to cover the ++ * skipped bytes or the SPI4 packet was ++ * terminated with an About EOPS. ++ * ++ * - 13 = RGMII nibble error/SPI4 Port NXA Error: the ++ * RGMII packet had a studder error (data not ++ * repeated - 10/100M only) or the SPI4 packet ++ * was sent to an NXA. ++ * ++ * - 16 = FCS error: a SPI4.2 packet had an FCS error. ++ * ++ * - 17 = Skip error: a packet was not large enough to ++ * cover the skipped bytes. ++ * ++ * - 18 = L2 header malformed: the packet is not long ++ * enough to contain the L2 ++ */ ++ ++ /* ++ * lower err_code = first-level descriptor of the ++ * work. ++ * ++ * zero for packet submitted by hardware that isn't on ++ * the slow path. ++ */ ++ uint64_t rcv_error:1; ++ ++ /* Type is cvmx_pip_err_t (union, so can't use directly. */ ++ uint64_t err_code:8; ++ } snoip; ++ ++}; ++ ++/** ++ * Work queue entry format ++ * ++ * must be 8-byte aligned ++ */ ++struct cvmx_wqe { ++ ++ /***************************************************************** ++ * WORD 0 ++ * HW WRITE: the following 64 bits are filled by HW when a packet arrives ++ */ ++ ++ /** ++ * raw chksum result generated by the HW ++ */ ++ uint16_t hw_chksum; ++ /** ++ * Field unused by hardware - available for software ++ */ ++ uint8_t unused; ++ /** ++ * Next pointer used by hardware for list maintenance. ++ * May be written/read by HW before the work queue ++ * entry is scheduled to a PP ++ * (Only 36 bits used in Octeon 1) ++ */ ++ uint64_t next_ptr:40; ++ ++ /***************************************************************** ++ * WORD 1 ++ * HW WRITE: the following 64 bits are filled by HW when a packet arrives ++ */ ++ ++ /** ++ * HW sets to the total number of bytes in the packet ++ */ ++ uint64_t len:16; ++ /** ++ * HW sets this to input physical port ++ */ ++ uint64_t ipprt:6; ++ ++ /** ++ * HW sets this to what it thought the priority of the input packet was ++ */ ++ uint64_t qos:3; ++ ++ /** ++ * the group that the work queue entry will be scheduled to ++ */ ++ uint64_t grp:4; ++ /** ++ * the type of the tag (ORDERED, ATOMIC, NULL) ++ */ ++ uint64_t tag_type:3; ++ /** ++ * the synchronization/ordering tag ++ */ ++ uint64_t tag:32; ++ ++ /** ++ * WORD 2 HW WRITE: the following 64-bits are filled in by ++ * hardware when a packet arrives This indicates a variety of ++ * status and error conditions. ++ */ ++ union cvmx_pip_wqe_word2 word2; ++ ++ /** ++ * Pointer to the first segment of the packet. ++ */ ++ union cvmx_buf_ptr packet_ptr; ++ ++ /** ++ * HW WRITE: octeon will fill in a programmable amount from the ++ * packet, up to (at most, but perhaps less) the amount ++ * needed to fill the work queue entry to 128 bytes ++ * If the packet is recognized to be IP, the hardware starts (except that ++ * the IPv4 header is padded for appropriate alignment) writing here where ++ * the IP header starts. ++ * If the packet is not recognized to be IP, the hardware starts writing ++ * the beginning of the packet here. ++ */ ++ uint8_t packet_data[96]; ++ ++ /** ++ * If desired, SW can make the work Q entry any length. For the ++ * purposes of discussion here, Assume 128B always, as this is all that ++ * the hardware deals with. ++ * ++ */ ++ ++} CVMX_CACHE_LINE_ALIGNED; ++ ++#endif /* __CVMX_WQE_H__ */ +--- a/arch/mips/include/asm/octeon/cvmx.h ++++ b/arch/mips/include/asm/octeon/cvmx.h +@@ -376,6 +376,18 @@ static inline uint64_t cvmx_get_cycle(vo + } + + /** ++ * Wait for the specified number of cycle ++ * ++ */ ++static inline void cvmx_wait(uint64_t cycles) ++{ ++ uint64_t done = cvmx_get_cycle() + cycles; ++ ++ while (cvmx_get_cycle() < done) ++ ; /* Spin */ ++} ++ ++/** + * Reads a chip global cycle counter. This counts CPU cycles since + * chip reset. The counter is 64 bit. + * This register does not exist on CN38XX pass 1 silicion +--- a/arch/mips/include/asm/octeon/octeon.h ++++ b/arch/mips/include/asm/octeon/octeon.h +@@ -245,4 +245,6 @@ static inline uint32_t octeon_npi_read32 + return cvmx_read64_uint32(address ^ 4); + } + ++extern struct cvmx_bootinfo *octeon_bootinfo; ++ + #endif /* __ASM_OCTEON_OCTEON_H */ diff --git a/target/linux/octeon/patches-2.6.30/004-named_alloc_function.patch b/target/linux/octeon/patches-2.6.30/004-named_alloc_function.patch new file mode 100644 index 0000000000..a3135f0a8a --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/004-named_alloc_function.patch @@ -0,0 +1,223 @@ +The MGMT ethernet driver uses these new functions. + +Signed-off-by: David Daney +--- + arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 101 ++++++++++++++++++++++ + arch/mips/include/asm/octeon/cvmx-bootmem.h | 85 ++++++++++++++++++ + 2 files changed, 186 insertions(+), 0 deletions(-) + +--- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c +@@ -97,6 +97,32 @@ void *cvmx_bootmem_alloc(uint64_t size, + return cvmx_bootmem_alloc_range(size, alignment, 0, 0); + } + ++void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, ++ uint64_t max_addr, uint64_t align, ++ char *name) ++{ ++ int64_t addr; ++ ++ addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, ++ align, name, 0); ++ if (addr >= 0) ++ return cvmx_phys_to_ptr(addr); ++ else ++ return NULL; ++} ++ ++void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, ++ char *name) ++{ ++ return cvmx_bootmem_alloc_named_range(size, address, address + size, ++ 0, name); ++} ++ ++void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name) ++{ ++ return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name); ++} ++ + int cvmx_bootmem_free_named(char *name) + { + return cvmx_bootmem_phy_named_block_free(name, 0); +@@ -584,3 +610,78 @@ int cvmx_bootmem_phy_named_block_free(ch + cvmx_bootmem_unlock(); + return named_block_ptr != NULL; /* 0 on failure, 1 on success */ + } ++ ++int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, ++ uint64_t max_addr, ++ uint64_t alignment, ++ char *name, ++ uint32_t flags) ++{ ++ int64_t addr_allocated; ++ struct cvmx_bootmem_named_block_desc *named_block_desc_ptr; ++ ++#ifdef DEBUG ++ cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: " ++ "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n", ++ (unsigned long long)size, ++ (unsigned long long)min_addr, ++ (unsigned long long)max_addr, ++ (unsigned long long)alignment, ++ name); ++#endif ++ if (cvmx_bootmem_desc->major_version != 3) { ++ cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: " ++ "%d.%d at addr: %p\n", ++ (int)cvmx_bootmem_desc->major_version, ++ (int)cvmx_bootmem_desc->minor_version, ++ cvmx_bootmem_desc); ++ return -1; ++ } ++ ++ /* ++ * Take lock here, as name lookup/block alloc/name add need to ++ * be atomic. ++ */ ++ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) ++ cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); ++ ++ /* Get pointer to first available named block descriptor */ ++ named_block_desc_ptr = ++ cvmx_bootmem_phy_named_block_find(NULL, ++ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING); ++ ++ /* ++ * Check to see if name already in use, return error if name ++ * not available or no more room for blocks. ++ */ ++ if (cvmx_bootmem_phy_named_block_find(name, ++ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) { ++ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) ++ cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); ++ return -1; ++ } ++ ++ ++ /* ++ * Round size up to mult of minimum alignment bytes We need ++ * the actual size allocated to allow for blocks to be ++ * coallesced when they are freed. The alloc routine does the ++ * same rounding up on all allocations. ++ */ ++ size = __ALIGN_MASK(size, (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)); ++ ++ addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr, ++ alignment, ++ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING); ++ if (addr_allocated >= 0) { ++ named_block_desc_ptr->base_addr = addr_allocated; ++ named_block_desc_ptr->size = size; ++ strncpy(named_block_desc_ptr->name, name, ++ cvmx_bootmem_desc->named_block_name_len); ++ named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0; ++ } ++ ++ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) ++ cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); ++ return addr_allocated; ++} +--- a/arch/mips/include/asm/octeon/cvmx-bootmem.h ++++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h +@@ -183,6 +183,64 @@ extern void *cvmx_bootmem_alloc_range(ui + * Returns 0 on failure, + * !0 on success + */ ++ ++ ++/** ++ * Allocate a block of memory from the free list that was passed ++ * to the application by the bootloader, and assign it a name in the ++ * global named block table. (part of the cvmx_bootmem_descriptor_t structure) ++ * Named blocks can later be freed. ++ * ++ * @size: Size in bytes of block to allocate ++ * @alignment: Alignment required - must be power of 2 ++ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes ++ * ++ * Returns a pointer to block of memory, NULL on error ++ */ ++extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, ++ char *name); ++ ++ ++ ++/** ++ * Allocate a block of memory from the free list that was passed ++ * to the application by the bootloader, and assign it a name in the ++ * global named block table. (part of the cvmx_bootmem_descriptor_t structure) ++ * Named blocks can later be freed. ++ * ++ * @size: Size in bytes of block to allocate ++ * @address: Physical address to allocate memory at. If this ++ * memory is not available, the allocation fails. ++ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN ++ * bytes ++ * ++ * Returns a pointer to block of memory, NULL on error ++ */ ++extern void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, ++ char *name); ++ ++ ++ ++/** ++ * Allocate a block of memory from a specific range of the free list ++ * that was passed to the application by the bootloader, and assign it ++ * a name in the global named block table. (part of the ++ * cvmx_bootmem_descriptor_t structure) Named blocks can later be ++ * freed. If request cannot be satisfied within the address range ++ * specified, NULL is returned ++ * ++ * @size: Size in bytes of block to allocate ++ * @min_addr: minimum address of range ++ * @max_addr: maximum address of range ++ * @align: Alignment of memory to be allocated. (must be a power of 2) ++ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes ++ * ++ * Returns a pointer to block of memory, NULL on error ++ */ ++extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, ++ uint64_t max_addr, uint64_t align, ++ char *name); ++ + extern int cvmx_bootmem_free_named(char *name); + + /** +@@ -224,6 +282,33 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t + uint32_t flags); + + /** ++ * Allocates a named block of physical memory from the free list, at ++ * (optional) requested address and alignment. ++ * ++ * @param size size of region to allocate. All requests are rounded ++ * up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE ++ * bytes size ++ * @param min_addr Minimum address that block can occupy. ++ * @param max_addr Specifies the maximum address_min (inclusive) that ++ * the allocation can use. ++ * @param alignment Requested alignment of the block. If this ++ * alignment cannot be met, the allocation fails. ++ * This must be a power of 2. (Note: Alignment of ++ * CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and ++ * internally enforced. Requested alignments of less ++ * than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to ++ * CVMX_BOOTMEM_ALIGNMENT_SIZE.) ++ * @param name name to assign to named block ++ * @param flags Flags to control options for the allocation. ++ * ++ * @return physical address of block allocated, or -1 on failure ++ */ ++int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, ++ uint64_t max_addr, ++ uint64_t alignment, ++ char *name, uint32_t flags); ++ ++/** + * Finds a named memory block by name. + * Also used for finding an unused entry in the named block table. + * diff --git a/target/linux/octeon/patches-2.6.30/005-register_defs_octeon_mgmt.patch b/target/linux/octeon/patches-2.6.30/005-register_defs_octeon_mgmt.patch new file mode 100644 index 0000000000..5169f6cf65 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/005-register_defs_octeon_mgmt.patch @@ -0,0 +1,1642 @@ +The MGMT ethernet driver uses the AGL, MIXX and SMIX blocks, so we add +definitions for them. + +Signed-off-by: David Daney +--- + arch/mips/include/asm/octeon/cvmx-agl-defs.h | 1194 +++++++++++++++++++++++++ + arch/mips/include/asm/octeon/cvmx-mixx-defs.h | 248 +++++ + arch/mips/include/asm/octeon/cvmx-smix-defs.h | 178 ++++ + 3 files changed, 1620 insertions(+), 0 deletions(-) + create mode 100644 arch/mips/include/asm/octeon/cvmx-agl-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-mixx-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-smix-defs.h + +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-agl-defs.h +@@ -0,0 +1,1194 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_AGL_DEFS_H__ ++#define __CVMX_AGL_DEFS_H__ ++ ++#define CVMX_AGL_GMX_BAD_REG \ ++ CVMX_ADD_IO_SEG(0x00011800E0000518ull) ++#define CVMX_AGL_GMX_BIST \ ++ CVMX_ADD_IO_SEG(0x00011800E0000400ull) ++#define CVMX_AGL_GMX_DRV_CTL \ ++ CVMX_ADD_IO_SEG(0x00011800E00007F0ull) ++#define CVMX_AGL_GMX_INF_MODE \ ++ CVMX_ADD_IO_SEG(0x00011800E00007F8ull) ++#define CVMX_AGL_GMX_PRTX_CFG(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000010ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM0(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000180ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM1(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000188ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM2(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000190ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM3(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000198ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM4(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00001A0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM5(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00001A8ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CAM_EN(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000108ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_ADR_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000100ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_DECISION(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000040ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_FRM_CHK(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000020ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_FRM_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000018ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_FRM_MAX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000030ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_FRM_MIN(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000028ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_IFG(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000058ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_INT_EN(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000008ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_INT_REG(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000000ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_JABBER(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000038ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_PAUSE_DROP_TIME(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000068ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000050ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_OCTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000088ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_OCTS_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000098ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_OCTS_DMAC(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00000A8ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_OCTS_DRP(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00000B8ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_PKTS(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000080ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00000C0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_PKTS_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000090ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_PKTS_DMAC(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00000A0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00000B0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RXX_UDD_SKP(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000048ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_RX_BP_DROPX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000420ull + (((offset) & 1) * 8)) ++#define CVMX_AGL_GMX_RX_BP_OFFX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000460ull + (((offset) & 1) * 8)) ++#define CVMX_AGL_GMX_RX_BP_ONX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000440ull + (((offset) & 1) * 8)) ++#define CVMX_AGL_GMX_RX_PRT_INFO \ ++ CVMX_ADD_IO_SEG(0x00011800E00004E8ull) ++#define CVMX_AGL_GMX_RX_TX_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011800E00007E8ull) ++#define CVMX_AGL_GMX_SMACX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000230ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_STAT_BP \ ++ CVMX_ADD_IO_SEG(0x00011800E0000520ull) ++#define CVMX_AGL_GMX_TXX_APPEND(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000218ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000270ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_MIN_PKT(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000240ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_PAUSE_PKT_INTERVAL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000248ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_PAUSE_PKT_TIME(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000238ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_PAUSE_TOGO(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000258ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_PAUSE_ZERO(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000260ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_SOFT_PAUSE(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000250ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT0(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000280ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT1(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000288ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT2(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000290ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT3(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000298ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT4(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00002A0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT5(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00002A8ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT6(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00002B0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT7(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00002B8ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT8(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00002C0ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STAT9(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E00002C8ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_STATS_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000268ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TXX_THRESH(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800E0000210ull + (((offset) & 1) * 2048)) ++#define CVMX_AGL_GMX_TX_BP \ ++ CVMX_ADD_IO_SEG(0x00011800E00004D0ull) ++#define CVMX_AGL_GMX_TX_COL_ATTEMPT \ ++ CVMX_ADD_IO_SEG(0x00011800E0000498ull) ++#define CVMX_AGL_GMX_TX_IFG \ ++ CVMX_ADD_IO_SEG(0x00011800E0000488ull) ++#define CVMX_AGL_GMX_TX_INT_EN \ ++ CVMX_ADD_IO_SEG(0x00011800E0000508ull) ++#define CVMX_AGL_GMX_TX_INT_REG \ ++ CVMX_ADD_IO_SEG(0x00011800E0000500ull) ++#define CVMX_AGL_GMX_TX_JAM \ ++ CVMX_ADD_IO_SEG(0x00011800E0000490ull) ++#define CVMX_AGL_GMX_TX_LFSR \ ++ CVMX_ADD_IO_SEG(0x00011800E00004F8ull) ++#define CVMX_AGL_GMX_TX_OVR_BP \ ++ CVMX_ADD_IO_SEG(0x00011800E00004C8ull) ++#define CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC \ ++ CVMX_ADD_IO_SEG(0x00011800E00004A0ull) ++#define CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE \ ++ CVMX_ADD_IO_SEG(0x00011800E00004A8ull) ++ ++union cvmx_agl_gmx_bad_reg { ++ uint64_t u64; ++ struct cvmx_agl_gmx_bad_reg_s { ++ uint64_t reserved_38_63:26; ++ uint64_t txpsh1:1; ++ uint64_t txpop1:1; ++ uint64_t ovrflw1:1; ++ uint64_t txpsh:1; ++ uint64_t txpop:1; ++ uint64_t ovrflw:1; ++ uint64_t reserved_27_31:5; ++ uint64_t statovr:1; ++ uint64_t reserved_23_25:3; ++ uint64_t loststat:1; ++ uint64_t reserved_4_21:18; ++ uint64_t out_ovr:2; ++ uint64_t reserved_0_1:2; ++ } s; ++ struct cvmx_agl_gmx_bad_reg_s cn52xx; ++ struct cvmx_agl_gmx_bad_reg_s cn52xxp1; ++ struct cvmx_agl_gmx_bad_reg_cn56xx { ++ uint64_t reserved_35_63:29; ++ uint64_t txpsh:1; ++ uint64_t txpop:1; ++ uint64_t ovrflw:1; ++ uint64_t reserved_27_31:5; ++ uint64_t statovr:1; ++ uint64_t reserved_23_25:3; ++ uint64_t loststat:1; ++ uint64_t reserved_3_21:19; ++ uint64_t out_ovr:1; ++ uint64_t reserved_0_1:2; ++ } cn56xx; ++ struct cvmx_agl_gmx_bad_reg_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_bist { ++ uint64_t u64; ++ struct cvmx_agl_gmx_bist_s { ++ uint64_t reserved_10_63:54; ++ uint64_t status:10; ++ } s; ++ struct cvmx_agl_gmx_bist_s cn52xx; ++ struct cvmx_agl_gmx_bist_s cn52xxp1; ++ struct cvmx_agl_gmx_bist_s cn56xx; ++ struct cvmx_agl_gmx_bist_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_drv_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_drv_ctl_s { ++ uint64_t reserved_49_63:15; ++ uint64_t byp_en1:1; ++ uint64_t reserved_45_47:3; ++ uint64_t pctl1:5; ++ uint64_t reserved_37_39:3; ++ uint64_t nctl1:5; ++ uint64_t reserved_17_31:15; ++ uint64_t byp_en:1; ++ uint64_t reserved_13_15:3; ++ uint64_t pctl:5; ++ uint64_t reserved_5_7:3; ++ uint64_t nctl:5; ++ } s; ++ struct cvmx_agl_gmx_drv_ctl_s cn52xx; ++ struct cvmx_agl_gmx_drv_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_drv_ctl_cn56xx { ++ uint64_t reserved_17_63:47; ++ uint64_t byp_en:1; ++ uint64_t reserved_13_15:3; ++ uint64_t pctl:5; ++ uint64_t reserved_5_7:3; ++ uint64_t nctl:5; ++ } cn56xx; ++ struct cvmx_agl_gmx_drv_ctl_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_inf_mode { ++ uint64_t u64; ++ struct cvmx_agl_gmx_inf_mode_s { ++ uint64_t reserved_2_63:62; ++ uint64_t en:1; ++ uint64_t reserved_0_0:1; ++ } s; ++ struct cvmx_agl_gmx_inf_mode_s cn52xx; ++ struct cvmx_agl_gmx_inf_mode_s cn52xxp1; ++ struct cvmx_agl_gmx_inf_mode_s cn56xx; ++ struct cvmx_agl_gmx_inf_mode_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_prtx_cfg { ++ uint64_t u64; ++ struct cvmx_agl_gmx_prtx_cfg_s { ++ uint64_t reserved_6_63:58; ++ uint64_t tx_en:1; ++ uint64_t rx_en:1; ++ uint64_t slottime:1; ++ uint64_t duplex:1; ++ uint64_t speed:1; ++ uint64_t en:1; ++ } s; ++ struct cvmx_agl_gmx_prtx_cfg_s cn52xx; ++ struct cvmx_agl_gmx_prtx_cfg_s cn52xxp1; ++ struct cvmx_agl_gmx_prtx_cfg_s cn56xx; ++ struct cvmx_agl_gmx_prtx_cfg_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam0 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam0_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam1 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam1_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam2 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam2_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam3 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam3_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam4 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam4_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam5 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam5_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_cam_en { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_cam_en_s { ++ uint64_t reserved_8_63:56; ++ uint64_t en:8; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_adr_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_adr_ctl_s { ++ uint64_t reserved_4_63:60; ++ uint64_t cam_mode:1; ++ uint64_t mcst:2; ++ uint64_t bcst:1; ++ } s; ++ struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xx; ++ struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xx; ++ struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_decision { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_decision_s { ++ uint64_t reserved_5_63:59; ++ uint64_t cnt:5; ++ } s; ++ struct cvmx_agl_gmx_rxx_decision_s cn52xx; ++ struct cvmx_agl_gmx_rxx_decision_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_decision_s cn56xx; ++ struct cvmx_agl_gmx_rxx_decision_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_frm_chk { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_frm_chk_s { ++ uint64_t reserved_9_63:55; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t reserved_1_1:1; ++ uint64_t minerr:1; ++ } s; ++ struct cvmx_agl_gmx_rxx_frm_chk_s cn52xx; ++ struct cvmx_agl_gmx_rxx_frm_chk_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_frm_chk_s cn56xx; ++ struct cvmx_agl_gmx_rxx_frm_chk_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_frm_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_frm_ctl_s { ++ uint64_t reserved_10_63:54; ++ uint64_t pre_align:1; ++ uint64_t pad_len:1; ++ uint64_t vlan_len:1; ++ uint64_t pre_free:1; ++ uint64_t ctl_smac:1; ++ uint64_t ctl_mcst:1; ++ uint64_t ctl_bck:1; ++ uint64_t ctl_drp:1; ++ uint64_t pre_strp:1; ++ uint64_t pre_chk:1; ++ } s; ++ struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xx; ++ struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xx; ++ struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_frm_max { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_frm_max_s { ++ uint64_t reserved_16_63:48; ++ uint64_t len:16; ++ } s; ++ struct cvmx_agl_gmx_rxx_frm_max_s cn52xx; ++ struct cvmx_agl_gmx_rxx_frm_max_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_frm_max_s cn56xx; ++ struct cvmx_agl_gmx_rxx_frm_max_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_frm_min { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_frm_min_s { ++ uint64_t reserved_16_63:48; ++ uint64_t len:16; ++ } s; ++ struct cvmx_agl_gmx_rxx_frm_min_s cn52xx; ++ struct cvmx_agl_gmx_rxx_frm_min_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_frm_min_s cn56xx; ++ struct cvmx_agl_gmx_rxx_frm_min_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_ifg { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_ifg_s { ++ uint64_t reserved_4_63:60; ++ uint64_t ifg:4; ++ } s; ++ struct cvmx_agl_gmx_rxx_ifg_s cn52xx; ++ struct cvmx_agl_gmx_rxx_ifg_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_ifg_s cn56xx; ++ struct cvmx_agl_gmx_rxx_ifg_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_int_en { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_int_en_s { ++ uint64_t reserved_20_63:44; ++ uint64_t pause_drp:1; ++ uint64_t reserved_16_18:3; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t reserved_9_9:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t reserved_1_1:1; ++ uint64_t minerr:1; ++ } s; ++ struct cvmx_agl_gmx_rxx_int_en_s cn52xx; ++ struct cvmx_agl_gmx_rxx_int_en_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_int_en_s cn56xx; ++ struct cvmx_agl_gmx_rxx_int_en_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_int_reg { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_int_reg_s { ++ uint64_t reserved_20_63:44; ++ uint64_t pause_drp:1; ++ uint64_t reserved_16_18:3; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t reserved_9_9:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t reserved_1_1:1; ++ uint64_t minerr:1; ++ } s; ++ struct cvmx_agl_gmx_rxx_int_reg_s cn52xx; ++ struct cvmx_agl_gmx_rxx_int_reg_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_int_reg_s cn56xx; ++ struct cvmx_agl_gmx_rxx_int_reg_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_jabber { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_jabber_s { ++ uint64_t reserved_16_63:48; ++ uint64_t cnt:16; ++ } s; ++ struct cvmx_agl_gmx_rxx_jabber_s cn52xx; ++ struct cvmx_agl_gmx_rxx_jabber_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_jabber_s cn56xx; ++ struct cvmx_agl_gmx_rxx_jabber_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_pause_drop_time { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_pause_drop_time_s { ++ uint64_t reserved_16_63:48; ++ uint64_t status:16; ++ } s; ++ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xx; ++ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xx; ++ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_ctl_s { ++ uint64_t reserved_1_63:63; ++ uint64_t rd_clr:1; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_octs { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_octs_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_octs_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_octs_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_octs_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_octs_dmac { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_octs_drp { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_octs_drp_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_pkts { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_pkts_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_pkts_bad { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_pkts_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_pkts_dmac { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_stats_pkts_drp { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xx; ++ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rxx_udd_skp { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rxx_udd_skp_s { ++ uint64_t reserved_9_63:55; ++ uint64_t fcssel:1; ++ uint64_t reserved_7_7:1; ++ uint64_t len:7; ++ } s; ++ struct cvmx_agl_gmx_rxx_udd_skp_s cn52xx; ++ struct cvmx_agl_gmx_rxx_udd_skp_s cn52xxp1; ++ struct cvmx_agl_gmx_rxx_udd_skp_s cn56xx; ++ struct cvmx_agl_gmx_rxx_udd_skp_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rx_bp_dropx { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rx_bp_dropx_s { ++ uint64_t reserved_6_63:58; ++ uint64_t mark:6; ++ } s; ++ struct cvmx_agl_gmx_rx_bp_dropx_s cn52xx; ++ struct cvmx_agl_gmx_rx_bp_dropx_s cn52xxp1; ++ struct cvmx_agl_gmx_rx_bp_dropx_s cn56xx; ++ struct cvmx_agl_gmx_rx_bp_dropx_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rx_bp_offx { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rx_bp_offx_s { ++ uint64_t reserved_6_63:58; ++ uint64_t mark:6; ++ } s; ++ struct cvmx_agl_gmx_rx_bp_offx_s cn52xx; ++ struct cvmx_agl_gmx_rx_bp_offx_s cn52xxp1; ++ struct cvmx_agl_gmx_rx_bp_offx_s cn56xx; ++ struct cvmx_agl_gmx_rx_bp_offx_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rx_bp_onx { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rx_bp_onx_s { ++ uint64_t reserved_9_63:55; ++ uint64_t mark:9; ++ } s; ++ struct cvmx_agl_gmx_rx_bp_onx_s cn52xx; ++ struct cvmx_agl_gmx_rx_bp_onx_s cn52xxp1; ++ struct cvmx_agl_gmx_rx_bp_onx_s cn56xx; ++ struct cvmx_agl_gmx_rx_bp_onx_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rx_prt_info { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rx_prt_info_s { ++ uint64_t reserved_18_63:46; ++ uint64_t drop:2; ++ uint64_t reserved_2_15:14; ++ uint64_t commit:2; ++ } s; ++ struct cvmx_agl_gmx_rx_prt_info_s cn52xx; ++ struct cvmx_agl_gmx_rx_prt_info_s cn52xxp1; ++ struct cvmx_agl_gmx_rx_prt_info_cn56xx { ++ uint64_t reserved_17_63:47; ++ uint64_t drop:1; ++ uint64_t reserved_1_15:15; ++ uint64_t commit:1; ++ } cn56xx; ++ struct cvmx_agl_gmx_rx_prt_info_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_rx_tx_status { ++ uint64_t u64; ++ struct cvmx_agl_gmx_rx_tx_status_s { ++ uint64_t reserved_6_63:58; ++ uint64_t tx:2; ++ uint64_t reserved_2_3:2; ++ uint64_t rx:2; ++ } s; ++ struct cvmx_agl_gmx_rx_tx_status_s cn52xx; ++ struct cvmx_agl_gmx_rx_tx_status_s cn52xxp1; ++ struct cvmx_agl_gmx_rx_tx_status_cn56xx { ++ uint64_t reserved_5_63:59; ++ uint64_t tx:1; ++ uint64_t reserved_1_3:3; ++ uint64_t rx:1; ++ } cn56xx; ++ struct cvmx_agl_gmx_rx_tx_status_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_smacx { ++ uint64_t u64; ++ struct cvmx_agl_gmx_smacx_s { ++ uint64_t reserved_48_63:16; ++ uint64_t smac:48; ++ } s; ++ struct cvmx_agl_gmx_smacx_s cn52xx; ++ struct cvmx_agl_gmx_smacx_s cn52xxp1; ++ struct cvmx_agl_gmx_smacx_s cn56xx; ++ struct cvmx_agl_gmx_smacx_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_stat_bp { ++ uint64_t u64; ++ struct cvmx_agl_gmx_stat_bp_s { ++ uint64_t reserved_17_63:47; ++ uint64_t bp:1; ++ uint64_t cnt:16; ++ } s; ++ struct cvmx_agl_gmx_stat_bp_s cn52xx; ++ struct cvmx_agl_gmx_stat_bp_s cn52xxp1; ++ struct cvmx_agl_gmx_stat_bp_s cn56xx; ++ struct cvmx_agl_gmx_stat_bp_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_append { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_append_s { ++ uint64_t reserved_4_63:60; ++ uint64_t force_fcs:1; ++ uint64_t fcs:1; ++ uint64_t pad:1; ++ uint64_t preamble:1; ++ } s; ++ struct cvmx_agl_gmx_txx_append_s cn52xx; ++ struct cvmx_agl_gmx_txx_append_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_append_s cn56xx; ++ struct cvmx_agl_gmx_txx_append_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_ctl_s { ++ uint64_t reserved_2_63:62; ++ uint64_t xsdef_en:1; ++ uint64_t xscol_en:1; ++ } s; ++ struct cvmx_agl_gmx_txx_ctl_s cn52xx; ++ struct cvmx_agl_gmx_txx_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_ctl_s cn56xx; ++ struct cvmx_agl_gmx_txx_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_min_pkt { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_min_pkt_s { ++ uint64_t reserved_8_63:56; ++ uint64_t min_size:8; ++ } s; ++ struct cvmx_agl_gmx_txx_min_pkt_s cn52xx; ++ struct cvmx_agl_gmx_txx_min_pkt_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_min_pkt_s cn56xx; ++ struct cvmx_agl_gmx_txx_min_pkt_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_pause_pkt_interval { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_pause_pkt_interval_s { ++ uint64_t reserved_16_63:48; ++ uint64_t interval:16; ++ } s; ++ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xx; ++ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xx; ++ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_pause_pkt_time { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_pause_pkt_time_s { ++ uint64_t reserved_16_63:48; ++ uint64_t time:16; ++ } s; ++ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xx; ++ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xx; ++ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_pause_togo { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_pause_togo_s { ++ uint64_t reserved_16_63:48; ++ uint64_t time:16; ++ } s; ++ struct cvmx_agl_gmx_txx_pause_togo_s cn52xx; ++ struct cvmx_agl_gmx_txx_pause_togo_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_pause_togo_s cn56xx; ++ struct cvmx_agl_gmx_txx_pause_togo_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_pause_zero { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_pause_zero_s { ++ uint64_t reserved_1_63:63; ++ uint64_t send:1; ++ } s; ++ struct cvmx_agl_gmx_txx_pause_zero_s cn52xx; ++ struct cvmx_agl_gmx_txx_pause_zero_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_pause_zero_s cn56xx; ++ struct cvmx_agl_gmx_txx_pause_zero_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_soft_pause { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_soft_pause_s { ++ uint64_t reserved_16_63:48; ++ uint64_t time:16; ++ } s; ++ struct cvmx_agl_gmx_txx_soft_pause_s cn52xx; ++ struct cvmx_agl_gmx_txx_soft_pause_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_soft_pause_s cn56xx; ++ struct cvmx_agl_gmx_txx_soft_pause_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat0 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat0_s { ++ uint64_t xsdef:32; ++ uint64_t xscol:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat0_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat0_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat0_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat0_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat1 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat1_s { ++ uint64_t scol:32; ++ uint64_t mcol:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat1_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat1_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat1_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat1_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat2 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat2_s { ++ uint64_t reserved_48_63:16; ++ uint64_t octs:48; ++ } s; ++ struct cvmx_agl_gmx_txx_stat2_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat2_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat2_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat2_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat3 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat3_s { ++ uint64_t reserved_32_63:32; ++ uint64_t pkts:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat3_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat3_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat3_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat3_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat4 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat4_s { ++ uint64_t hist1:32; ++ uint64_t hist0:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat4_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat4_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat4_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat4_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat5 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat5_s { ++ uint64_t hist3:32; ++ uint64_t hist2:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat5_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat5_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat5_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat5_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat6 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat6_s { ++ uint64_t hist5:32; ++ uint64_t hist4:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat6_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat6_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat6_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat6_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat7 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat7_s { ++ uint64_t hist7:32; ++ uint64_t hist6:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat7_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat7_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat7_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat7_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat8 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat8_s { ++ uint64_t mcst:32; ++ uint64_t bcst:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat8_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat8_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat8_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat8_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stat9 { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stat9_s { ++ uint64_t undflw:32; ++ uint64_t ctl:32; ++ } s; ++ struct cvmx_agl_gmx_txx_stat9_s cn52xx; ++ struct cvmx_agl_gmx_txx_stat9_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stat9_s cn56xx; ++ struct cvmx_agl_gmx_txx_stat9_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_stats_ctl { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_stats_ctl_s { ++ uint64_t reserved_1_63:63; ++ uint64_t rd_clr:1; ++ } s; ++ struct cvmx_agl_gmx_txx_stats_ctl_s cn52xx; ++ struct cvmx_agl_gmx_txx_stats_ctl_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_stats_ctl_s cn56xx; ++ struct cvmx_agl_gmx_txx_stats_ctl_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_txx_thresh { ++ uint64_t u64; ++ struct cvmx_agl_gmx_txx_thresh_s { ++ uint64_t reserved_6_63:58; ++ uint64_t cnt:6; ++ } s; ++ struct cvmx_agl_gmx_txx_thresh_s cn52xx; ++ struct cvmx_agl_gmx_txx_thresh_s cn52xxp1; ++ struct cvmx_agl_gmx_txx_thresh_s cn56xx; ++ struct cvmx_agl_gmx_txx_thresh_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_bp { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_bp_s { ++ uint64_t reserved_2_63:62; ++ uint64_t bp:2; ++ } s; ++ struct cvmx_agl_gmx_tx_bp_s cn52xx; ++ struct cvmx_agl_gmx_tx_bp_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_bp_cn56xx { ++ uint64_t reserved_1_63:63; ++ uint64_t bp:1; ++ } cn56xx; ++ struct cvmx_agl_gmx_tx_bp_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_col_attempt { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_col_attempt_s { ++ uint64_t reserved_5_63:59; ++ uint64_t limit:5; ++ } s; ++ struct cvmx_agl_gmx_tx_col_attempt_s cn52xx; ++ struct cvmx_agl_gmx_tx_col_attempt_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_col_attempt_s cn56xx; ++ struct cvmx_agl_gmx_tx_col_attempt_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_ifg { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_ifg_s { ++ uint64_t reserved_8_63:56; ++ uint64_t ifg2:4; ++ uint64_t ifg1:4; ++ } s; ++ struct cvmx_agl_gmx_tx_ifg_s cn52xx; ++ struct cvmx_agl_gmx_tx_ifg_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_ifg_s cn56xx; ++ struct cvmx_agl_gmx_tx_ifg_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_int_en { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_int_en_s { ++ uint64_t reserved_18_63:46; ++ uint64_t late_col:2; ++ uint64_t reserved_14_15:2; ++ uint64_t xsdef:2; ++ uint64_t reserved_10_11:2; ++ uint64_t xscol:2; ++ uint64_t reserved_4_7:4; ++ uint64_t undflw:2; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } s; ++ struct cvmx_agl_gmx_tx_int_en_s cn52xx; ++ struct cvmx_agl_gmx_tx_int_en_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_int_en_cn56xx { ++ uint64_t reserved_17_63:47; ++ uint64_t late_col:1; ++ uint64_t reserved_13_15:3; ++ uint64_t xsdef:1; ++ uint64_t reserved_9_11:3; ++ uint64_t xscol:1; ++ uint64_t reserved_3_7:5; ++ uint64_t undflw:1; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn56xx; ++ struct cvmx_agl_gmx_tx_int_en_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_int_reg { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_int_reg_s { ++ uint64_t reserved_18_63:46; ++ uint64_t late_col:2; ++ uint64_t reserved_14_15:2; ++ uint64_t xsdef:2; ++ uint64_t reserved_10_11:2; ++ uint64_t xscol:2; ++ uint64_t reserved_4_7:4; ++ uint64_t undflw:2; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } s; ++ struct cvmx_agl_gmx_tx_int_reg_s cn52xx; ++ struct cvmx_agl_gmx_tx_int_reg_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_int_reg_cn56xx { ++ uint64_t reserved_17_63:47; ++ uint64_t late_col:1; ++ uint64_t reserved_13_15:3; ++ uint64_t xsdef:1; ++ uint64_t reserved_9_11:3; ++ uint64_t xscol:1; ++ uint64_t reserved_3_7:5; ++ uint64_t undflw:1; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn56xx; ++ struct cvmx_agl_gmx_tx_int_reg_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_jam { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_jam_s { ++ uint64_t reserved_8_63:56; ++ uint64_t jam:8; ++ } s; ++ struct cvmx_agl_gmx_tx_jam_s cn52xx; ++ struct cvmx_agl_gmx_tx_jam_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_jam_s cn56xx; ++ struct cvmx_agl_gmx_tx_jam_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_lfsr { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_lfsr_s { ++ uint64_t reserved_16_63:48; ++ uint64_t lfsr:16; ++ } s; ++ struct cvmx_agl_gmx_tx_lfsr_s cn52xx; ++ struct cvmx_agl_gmx_tx_lfsr_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_lfsr_s cn56xx; ++ struct cvmx_agl_gmx_tx_lfsr_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_ovr_bp { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_ovr_bp_s { ++ uint64_t reserved_10_63:54; ++ uint64_t en:2; ++ uint64_t reserved_6_7:2; ++ uint64_t bp:2; ++ uint64_t reserved_2_3:2; ++ uint64_t ign_full:2; ++ } s; ++ struct cvmx_agl_gmx_tx_ovr_bp_s cn52xx; ++ struct cvmx_agl_gmx_tx_ovr_bp_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_ovr_bp_cn56xx { ++ uint64_t reserved_9_63:55; ++ uint64_t en:1; ++ uint64_t reserved_5_7:3; ++ uint64_t bp:1; ++ uint64_t reserved_1_3:3; ++ uint64_t ign_full:1; ++ } cn56xx; ++ struct cvmx_agl_gmx_tx_ovr_bp_cn56xx cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_pause_pkt_dmac { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s { ++ uint64_t reserved_48_63:16; ++ uint64_t dmac:48; ++ } s; ++ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xx; ++ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xx; ++ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xxp1; ++}; ++ ++union cvmx_agl_gmx_tx_pause_pkt_type { ++ uint64_t u64; ++ struct cvmx_agl_gmx_tx_pause_pkt_type_s { ++ uint64_t reserved_16_63:48; ++ uint64_t type:16; ++ } s; ++ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xx; ++ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xxp1; ++ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xx; ++ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-mixx-defs.h +@@ -0,0 +1,248 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_MIXX_DEFS_H__ ++#define __CVMX_MIXX_DEFS_H__ ++ ++#define CVMX_MIXX_BIST(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100078ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_CTL(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100020ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_INTENA(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100050ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_IRCNT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100030ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_IRHWM(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100028ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_IRING1(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100010ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_IRING2(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100018ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_ISR(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100048ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_ORCNT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100040ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_ORHWM(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100038ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_ORING1(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100000ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_ORING2(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100008ull + (((offset) & 1) * 2048)) ++#define CVMX_MIXX_REMCNT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001070000100058ull + (((offset) & 1) * 2048)) ++ ++union cvmx_mixx_bist { ++ uint64_t u64; ++ struct cvmx_mixx_bist_s { ++ uint64_t reserved_4_63:60; ++ uint64_t mrqdat:1; ++ uint64_t ipfdat:1; ++ uint64_t irfdat:1; ++ uint64_t orfdat:1; ++ } s; ++ struct cvmx_mixx_bist_s cn52xx; ++ struct cvmx_mixx_bist_s cn52xxp1; ++ struct cvmx_mixx_bist_s cn56xx; ++ struct cvmx_mixx_bist_s cn56xxp1; ++}; ++ ++union cvmx_mixx_ctl { ++ uint64_t u64; ++ struct cvmx_mixx_ctl_s { ++ uint64_t reserved_8_63:56; ++ uint64_t crc_strip:1; ++ uint64_t busy:1; ++ uint64_t en:1; ++ uint64_t reset:1; ++ uint64_t lendian:1; ++ uint64_t nbtarb:1; ++ uint64_t mrq_hwm:2; ++ } s; ++ struct cvmx_mixx_ctl_s cn52xx; ++ struct cvmx_mixx_ctl_s cn52xxp1; ++ struct cvmx_mixx_ctl_s cn56xx; ++ struct cvmx_mixx_ctl_s cn56xxp1; ++}; ++ ++union cvmx_mixx_intena { ++ uint64_t u64; ++ struct cvmx_mixx_intena_s { ++ uint64_t reserved_7_63:57; ++ uint64_t orunena:1; ++ uint64_t irunena:1; ++ uint64_t data_drpena:1; ++ uint64_t ithena:1; ++ uint64_t othena:1; ++ uint64_t ivfena:1; ++ uint64_t ovfena:1; ++ } s; ++ struct cvmx_mixx_intena_s cn52xx; ++ struct cvmx_mixx_intena_s cn52xxp1; ++ struct cvmx_mixx_intena_s cn56xx; ++ struct cvmx_mixx_intena_s cn56xxp1; ++}; ++ ++union cvmx_mixx_ircnt { ++ uint64_t u64; ++ struct cvmx_mixx_ircnt_s { ++ uint64_t reserved_20_63:44; ++ uint64_t ircnt:20; ++ } s; ++ struct cvmx_mixx_ircnt_s cn52xx; ++ struct cvmx_mixx_ircnt_s cn52xxp1; ++ struct cvmx_mixx_ircnt_s cn56xx; ++ struct cvmx_mixx_ircnt_s cn56xxp1; ++}; ++ ++union cvmx_mixx_irhwm { ++ uint64_t u64; ++ struct cvmx_mixx_irhwm_s { ++ uint64_t reserved_40_63:24; ++ uint64_t ibplwm:20; ++ uint64_t irhwm:20; ++ } s; ++ struct cvmx_mixx_irhwm_s cn52xx; ++ struct cvmx_mixx_irhwm_s cn52xxp1; ++ struct cvmx_mixx_irhwm_s cn56xx; ++ struct cvmx_mixx_irhwm_s cn56xxp1; ++}; ++ ++union cvmx_mixx_iring1 { ++ uint64_t u64; ++ struct cvmx_mixx_iring1_s { ++ uint64_t reserved_60_63:4; ++ uint64_t isize:20; ++ uint64_t reserved_36_39:4; ++ uint64_t ibase:33; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_mixx_iring1_s cn52xx; ++ struct cvmx_mixx_iring1_s cn52xxp1; ++ struct cvmx_mixx_iring1_s cn56xx; ++ struct cvmx_mixx_iring1_s cn56xxp1; ++}; ++ ++union cvmx_mixx_iring2 { ++ uint64_t u64; ++ struct cvmx_mixx_iring2_s { ++ uint64_t reserved_52_63:12; ++ uint64_t itlptr:20; ++ uint64_t reserved_20_31:12; ++ uint64_t idbell:20; ++ } s; ++ struct cvmx_mixx_iring2_s cn52xx; ++ struct cvmx_mixx_iring2_s cn52xxp1; ++ struct cvmx_mixx_iring2_s cn56xx; ++ struct cvmx_mixx_iring2_s cn56xxp1; ++}; ++ ++union cvmx_mixx_isr { ++ uint64_t u64; ++ struct cvmx_mixx_isr_s { ++ uint64_t reserved_7_63:57; ++ uint64_t orun:1; ++ uint64_t irun:1; ++ uint64_t data_drp:1; ++ uint64_t irthresh:1; ++ uint64_t orthresh:1; ++ uint64_t idblovf:1; ++ uint64_t odblovf:1; ++ } s; ++ struct cvmx_mixx_isr_s cn52xx; ++ struct cvmx_mixx_isr_s cn52xxp1; ++ struct cvmx_mixx_isr_s cn56xx; ++ struct cvmx_mixx_isr_s cn56xxp1; ++}; ++ ++union cvmx_mixx_orcnt { ++ uint64_t u64; ++ struct cvmx_mixx_orcnt_s { ++ uint64_t reserved_20_63:44; ++ uint64_t orcnt:20; ++ } s; ++ struct cvmx_mixx_orcnt_s cn52xx; ++ struct cvmx_mixx_orcnt_s cn52xxp1; ++ struct cvmx_mixx_orcnt_s cn56xx; ++ struct cvmx_mixx_orcnt_s cn56xxp1; ++}; ++ ++union cvmx_mixx_orhwm { ++ uint64_t u64; ++ struct cvmx_mixx_orhwm_s { ++ uint64_t reserved_20_63:44; ++ uint64_t orhwm:20; ++ } s; ++ struct cvmx_mixx_orhwm_s cn52xx; ++ struct cvmx_mixx_orhwm_s cn52xxp1; ++ struct cvmx_mixx_orhwm_s cn56xx; ++ struct cvmx_mixx_orhwm_s cn56xxp1; ++}; ++ ++union cvmx_mixx_oring1 { ++ uint64_t u64; ++ struct cvmx_mixx_oring1_s { ++ uint64_t reserved_60_63:4; ++ uint64_t osize:20; ++ uint64_t reserved_36_39:4; ++ uint64_t obase:33; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_mixx_oring1_s cn52xx; ++ struct cvmx_mixx_oring1_s cn52xxp1; ++ struct cvmx_mixx_oring1_s cn56xx; ++ struct cvmx_mixx_oring1_s cn56xxp1; ++}; ++ ++union cvmx_mixx_oring2 { ++ uint64_t u64; ++ struct cvmx_mixx_oring2_s { ++ uint64_t reserved_52_63:12; ++ uint64_t otlptr:20; ++ uint64_t reserved_20_31:12; ++ uint64_t odbell:20; ++ } s; ++ struct cvmx_mixx_oring2_s cn52xx; ++ struct cvmx_mixx_oring2_s cn52xxp1; ++ struct cvmx_mixx_oring2_s cn56xx; ++ struct cvmx_mixx_oring2_s cn56xxp1; ++}; ++ ++union cvmx_mixx_remcnt { ++ uint64_t u64; ++ struct cvmx_mixx_remcnt_s { ++ uint64_t reserved_52_63:12; ++ uint64_t iremcnt:20; ++ uint64_t reserved_20_31:12; ++ uint64_t oremcnt:20; ++ } s; ++ struct cvmx_mixx_remcnt_s cn52xx; ++ struct cvmx_mixx_remcnt_s cn52xxp1; ++ struct cvmx_mixx_remcnt_s cn56xx; ++ struct cvmx_mixx_remcnt_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-smix-defs.h +@@ -0,0 +1,178 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_SMIX_DEFS_H__ ++#define __CVMX_SMIX_DEFS_H__ ++ ++#define CVMX_SMIX_CLK(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_CMD(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_EN(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_RD_DAT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_WR_DAT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256)) ++ ++union cvmx_smix_clk { ++ uint64_t u64; ++ struct cvmx_smix_clk_s { ++ uint64_t reserved_25_63:39; ++ uint64_t mode:1; ++ uint64_t reserved_21_23:3; ++ uint64_t sample_hi:5; ++ uint64_t sample_mode:1; ++ uint64_t reserved_14_14:1; ++ uint64_t clk_idle:1; ++ uint64_t preamble:1; ++ uint64_t sample:4; ++ uint64_t phase:8; ++ } s; ++ struct cvmx_smix_clk_cn30xx { ++ uint64_t reserved_21_63:43; ++ uint64_t sample_hi:5; ++ uint64_t reserved_14_15:2; ++ uint64_t clk_idle:1; ++ uint64_t preamble:1; ++ uint64_t sample:4; ++ uint64_t phase:8; ++ } cn30xx; ++ struct cvmx_smix_clk_cn30xx cn31xx; ++ struct cvmx_smix_clk_cn30xx cn38xx; ++ struct cvmx_smix_clk_cn30xx cn38xxp2; ++ struct cvmx_smix_clk_cn50xx { ++ uint64_t reserved_25_63:39; ++ uint64_t mode:1; ++ uint64_t reserved_21_23:3; ++ uint64_t sample_hi:5; ++ uint64_t reserved_14_15:2; ++ uint64_t clk_idle:1; ++ uint64_t preamble:1; ++ uint64_t sample:4; ++ uint64_t phase:8; ++ } cn50xx; ++ struct cvmx_smix_clk_s cn52xx; ++ struct cvmx_smix_clk_cn50xx cn52xxp1; ++ struct cvmx_smix_clk_s cn56xx; ++ struct cvmx_smix_clk_cn50xx cn56xxp1; ++ struct cvmx_smix_clk_cn30xx cn58xx; ++ struct cvmx_smix_clk_cn30xx cn58xxp1; ++}; ++ ++union cvmx_smix_cmd { ++ uint64_t u64; ++ struct cvmx_smix_cmd_s { ++ uint64_t reserved_18_63:46; ++ uint64_t phy_op:2; ++ uint64_t reserved_13_15:3; ++ uint64_t phy_adr:5; ++ uint64_t reserved_5_7:3; ++ uint64_t reg_adr:5; ++ } s; ++ struct cvmx_smix_cmd_cn30xx { ++ uint64_t reserved_17_63:47; ++ uint64_t phy_op:1; ++ uint64_t reserved_13_15:3; ++ uint64_t phy_adr:5; ++ uint64_t reserved_5_7:3; ++ uint64_t reg_adr:5; ++ } cn30xx; ++ struct cvmx_smix_cmd_cn30xx cn31xx; ++ struct cvmx_smix_cmd_cn30xx cn38xx; ++ struct cvmx_smix_cmd_cn30xx cn38xxp2; ++ struct cvmx_smix_cmd_s cn50xx; ++ struct cvmx_smix_cmd_s cn52xx; ++ struct cvmx_smix_cmd_s cn52xxp1; ++ struct cvmx_smix_cmd_s cn56xx; ++ struct cvmx_smix_cmd_s cn56xxp1; ++ struct cvmx_smix_cmd_cn30xx cn58xx; ++ struct cvmx_smix_cmd_cn30xx cn58xxp1; ++}; ++ ++union cvmx_smix_en { ++ uint64_t u64; ++ struct cvmx_smix_en_s { ++ uint64_t reserved_1_63:63; ++ uint64_t en:1; ++ } s; ++ struct cvmx_smix_en_s cn30xx; ++ struct cvmx_smix_en_s cn31xx; ++ struct cvmx_smix_en_s cn38xx; ++ struct cvmx_smix_en_s cn38xxp2; ++ struct cvmx_smix_en_s cn50xx; ++ struct cvmx_smix_en_s cn52xx; ++ struct cvmx_smix_en_s cn52xxp1; ++ struct cvmx_smix_en_s cn56xx; ++ struct cvmx_smix_en_s cn56xxp1; ++ struct cvmx_smix_en_s cn58xx; ++ struct cvmx_smix_en_s cn58xxp1; ++}; ++ ++union cvmx_smix_rd_dat { ++ uint64_t u64; ++ struct cvmx_smix_rd_dat_s { ++ uint64_t reserved_18_63:46; ++ uint64_t pending:1; ++ uint64_t val:1; ++ uint64_t dat:16; ++ } s; ++ struct cvmx_smix_rd_dat_s cn30xx; ++ struct cvmx_smix_rd_dat_s cn31xx; ++ struct cvmx_smix_rd_dat_s cn38xx; ++ struct cvmx_smix_rd_dat_s cn38xxp2; ++ struct cvmx_smix_rd_dat_s cn50xx; ++ struct cvmx_smix_rd_dat_s cn52xx; ++ struct cvmx_smix_rd_dat_s cn52xxp1; ++ struct cvmx_smix_rd_dat_s cn56xx; ++ struct cvmx_smix_rd_dat_s cn56xxp1; ++ struct cvmx_smix_rd_dat_s cn58xx; ++ struct cvmx_smix_rd_dat_s cn58xxp1; ++}; ++ ++union cvmx_smix_wr_dat { ++ uint64_t u64; ++ struct cvmx_smix_wr_dat_s { ++ uint64_t reserved_18_63:46; ++ uint64_t pending:1; ++ uint64_t val:1; ++ uint64_t dat:16; ++ } s; ++ struct cvmx_smix_wr_dat_s cn30xx; ++ struct cvmx_smix_wr_dat_s cn31xx; ++ struct cvmx_smix_wr_dat_s cn38xx; ++ struct cvmx_smix_wr_dat_s cn38xxp2; ++ struct cvmx_smix_wr_dat_s cn50xx; ++ struct cvmx_smix_wr_dat_s cn52xx; ++ struct cvmx_smix_wr_dat_s cn52xxp1; ++ struct cvmx_smix_wr_dat_s cn56xx; ++ struct cvmx_smix_wr_dat_s cn56xxp1; ++ struct cvmx_smix_wr_dat_s cn58xx; ++ struct cvmx_smix_wr_dat_s cn58xxp1; ++}; ++ ++#endif diff --git a/target/linux/octeon/patches-2.6.30/006-octeon_mgmt_driver.patch b/target/linux/octeon/patches-2.6.30/006-octeon_mgmt_driver.patch new file mode 100644 index 0000000000..7ea094519e --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/006-octeon_mgmt_driver.patch @@ -0,0 +1,2022 @@ +Signed-off-by: David Daney +--- + arch/mips/include/asm/octeon/cvmx-mdio.h | 577 +++++++++++++++++++++ + drivers/net/Kconfig | 8 + + drivers/net/Makefile | 1 + + drivers/net/octeon/Makefile | 11 + + drivers/net/octeon/cvmx-mgmt-port.c | 818 ++++++++++++++++++++++++++++++ + drivers/net/octeon/cvmx-mgmt-port.h | 168 ++++++ + drivers/net/octeon/octeon-mgmt-port.c | 389 ++++++++++++++ + 7 files changed, 1972 insertions(+), 0 deletions(-) + create mode 100644 arch/mips/include/asm/octeon/cvmx-mdio.h + create mode 100644 drivers/net/octeon/Makefile + create mode 100644 drivers/net/octeon/cvmx-mgmt-port.c + create mode 100644 drivers/net/octeon/cvmx-mgmt-port.h + create mode 100644 drivers/net/octeon/octeon-mgmt-port.c + +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-mdio.h +@@ -0,0 +1,577 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3 ++ * clause 22 and clause 45 operations. ++ * ++ */ ++ ++#ifndef __CVMX_MIO_H__ ++#define __CVMX_MIO_H__ ++ ++#include "cvmx-smix-defs.h" ++ ++/** ++ * PHY register 0 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_CONTROL 0 ++union cvmx_mdio_phy_reg_control { ++ uint16_t u16; ++ struct { ++ uint16_t reset:1; ++ uint16_t loopback:1; ++ uint16_t speed_lsb:1; ++ uint16_t autoneg_enable:1; ++ uint16_t power_down:1; ++ uint16_t isolate:1; ++ uint16_t restart_autoneg:1; ++ uint16_t duplex:1; ++ uint16_t collision_test:1; ++ uint16_t speed_msb:1; ++ uint16_t unidirectional_enable:1; ++ uint16_t reserved_0_4:5; ++ } s; ++}; ++ ++/** ++ * PHY register 1 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_STATUS 1 ++union cvmx_mdio_phy_reg_status { ++ uint16_t u16; ++ struct { ++ uint16_t capable_100base_t4:1; ++ uint16_t capable_100base_x_full:1; ++ uint16_t capable_100base_x_half:1; ++ uint16_t capable_10_full:1; ++ uint16_t capable_10_half:1; ++ uint16_t capable_100base_t2_full:1; ++ uint16_t capable_100base_t2_half:1; ++ uint16_t capable_extended_status:1; ++ uint16_t capable_unidirectional:1; ++ uint16_t capable_mf_preamble_suppression:1; ++ uint16_t autoneg_complete:1; ++ uint16_t remote_fault:1; ++ uint16_t capable_autoneg:1; ++ uint16_t link_status:1; ++ uint16_t jabber_detect:1; ++ uint16_t capable_extended_registers:1; ++ ++ } s; ++}; ++ ++/** ++ * PHY register 2 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_ID1 2 ++union cvmx_mdio_phy_reg_id1 { ++ uint16_t u16; ++ struct { ++ uint16_t oui_bits_3_18; ++ } s; ++}; ++ ++/** ++ * PHY register 3 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_ID2 3 ++union cvmx_mdio_phy_reg_id2 { ++ uint16_t u16; ++ struct { ++ uint16_t oui_bits_19_24:6; ++ uint16_t model:6; ++ uint16_t revision:4; ++ } s; ++}; ++ ++/** ++ * PHY register 4 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4 ++union cvmx_mdio_phy_reg_autoneg_adver { ++ uint16_t u16; ++ struct { ++ uint16_t next_page:1; ++ uint16_t reserved_14:1; ++ uint16_t remote_fault:1; ++ uint16_t reserved_12:1; ++ uint16_t asymmetric_pause:1; ++ uint16_t pause:1; ++ uint16_t advert_100base_t4:1; ++ uint16_t advert_100base_tx_full:1; ++ uint16_t advert_100base_tx_half:1; ++ uint16_t advert_10base_tx_full:1; ++ uint16_t advert_10base_tx_half:1; ++ uint16_t selector:5; ++ } s; ++}; ++ ++/** ++ * PHY register 5 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5 ++union cvmx_mdio_phy_reg_link_partner_ability { ++ uint16_t u16; ++ struct { ++ uint16_t next_page:1; ++ uint16_t ack:1; ++ uint16_t remote_fault:1; ++ uint16_t reserved_12:1; ++ uint16_t asymmetric_pause:1; ++ uint16_t pause:1; ++ uint16_t advert_100base_t4:1; ++ uint16_t advert_100base_tx_full:1; ++ uint16_t advert_100base_tx_half:1; ++ uint16_t advert_10base_tx_full:1; ++ uint16_t advert_10base_tx_half:1; ++ uint16_t selector:5; ++ } s; ++}; ++ ++/** ++ * PHY register 6 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6 ++union cvmx_mdio_phy_reg_autoneg_expansion { ++ uint16_t u16; ++ struct { ++ uint16_t reserved_5_15:11; ++ uint16_t parallel_detection_fault:1; ++ uint16_t link_partner_next_page_capable:1; ++ uint16_t local_next_page_capable:1; ++ uint16_t page_received:1; ++ uint16_t link_partner_autoneg_capable:1; ++ ++ } s; ++}; ++ ++/** ++ * PHY register 9 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_CONTROL_1000 9 ++union cvmx_mdio_phy_reg_control_1000 { ++ uint16_t u16; ++ struct { ++ uint16_t test_mode:3; ++ uint16_t manual_master_slave:1; ++ uint16_t master:1; ++ uint16_t port_type:1; ++ uint16_t advert_1000base_t_full:1; ++ uint16_t advert_1000base_t_half:1; ++ uint16_t reserved_0_7:8; ++ } s; ++}; ++ ++/** ++ * PHY register 10 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_STATUS_1000 10 ++union cvmx_mdio_phy_reg_status_1000 { ++ uint16_t u16; ++ struct { ++ uint16_t master_slave_fault:1; ++ uint16_t is_master:1; ++ uint16_t local_receiver_ok:1; ++ uint16_t remote_receiver_ok:1; ++ uint16_t remote_capable_1000base_t_full:1; ++ uint16_t remote_capable_1000base_t_half:1; ++ uint16_t reserved_8_9:2; ++ uint16_t idle_error_count:8; ++ } s; ++}; ++ ++/** ++ * PHY register 15 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15 ++union cvmx_mdio_phy_reg_extended_status { ++ uint16_t u16; ++ struct { ++ uint16_t capable_1000base_x_full:1; ++ uint16_t capable_1000base_x_half:1; ++ uint16_t capable_1000base_t_full:1; ++ uint16_t capable_1000base_t_half:1; ++ uint16_t reserved_0_11:12; ++ } s; ++}; ++ ++/** ++ * PHY register 13 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13 ++union cvmx_mdio_phy_reg_mmd_control { ++ uint16_t u16; ++ struct { ++ uint16_t function:2; ++ uint16_t reserved_5_13:9; ++ uint16_t devad:5; ++ } s; ++}; ++ ++/** ++ * PHY register 14 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14 ++union cvmx_mdio_phy_reg_mmd_address_data { ++ uint16_t u16; ++ struct { ++ uint16_t address_data:16; ++ } s; ++}; ++ ++/* Operating request encodings. */ ++#define MDIO_CLAUSE_22_WRITE 0 ++#define MDIO_CLAUSE_22_READ 1 ++ ++#define MDIO_CLAUSE_45_ADDRESS 0 ++#define MDIO_CLAUSE_45_WRITE 1 ++#define MDIO_CLAUSE_45_READ_INC 2 ++#define MDIO_CLAUSE_45_READ 3 ++ ++/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */ ++#define CVMX_MMD_DEVICE_PMA_PMD 1 ++#define CVMX_MMD_DEVICE_WIS 2 ++#define CVMX_MMD_DEVICE_PCS 3 ++#define CVMX_MMD_DEVICE_PHY_XS 4 ++#define CVMX_MMD_DEVICE_DTS_XS 5 ++#define CVMX_MMD_DEVICE_TC 6 ++#define CVMX_MMD_DEVICE_CL22_EXT 29 ++#define CVMX_MMD_DEVICE_VENDOR_1 30 ++#define CVMX_MMD_DEVICE_VENDOR_2 31 ++ ++/** ++ * Perform an MII read. This function is used to read PHY ++ * registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @location: Register location to read ++ * ++ * Returns Result from the read or -1 on failure ++ */ ++static inline int cvmx_mdio_read(int bus_id, int phy_id, int location) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_rd_dat smi_rd; ++ int timeout = 1000; ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = location; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); ++ } while (smi_rd.s.pending && timeout--); ++ ++ if (smi_rd.s.val) ++ return smi_rd.s.dat; ++ else ++ return -1; ++} ++ ++/** ++ * Perform an MII write. This function is used to write PHY ++ * registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @location: Register location to write ++ * @val: Value to write ++ * ++ * Returns -1 on error ++ * 0 on success ++ */ ++static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_wr_dat smi_wr; ++ int timeout = 1000; ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = val; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = location; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ return 0; ++} ++ ++/** ++ * Perform an IEEE 802.3 clause 45 MII read using clause 22 operations. This ++ * function is used to read PHY registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @device: MDIO Managable Device (MMD) id ++ * @location: Register location to read ++ * ++ * Returns Result from the read or -1 on failure ++ */ ++ ++static inline int cvmx_mdio_45_via_22_read(int bus_id, int phy_id, int device, ++ int location) ++{ ++ union cvmx_mdio_phy_reg_mmd_control mmd_control; ++ ++ /* ++ * a) To Register 13, write the Function field to 00 (address) ++ * and DEVAD field to the device address value for the ++ * desired MMD; ++ */ ++ mmd_control.u16 = 0; ++ mmd_control.s.function = MDIO_CLAUSE_45_ADDRESS; ++ mmd_control.s.devad = device; ++ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, ++ mmd_control.u16); ++ ++ /* ++ * b) To Register 14, write the desired address value to the ++ * MMD's address register; ++ */ ++ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, ++ location); ++ ++ /* ++ * c) To Register 13, write the Function field to 01 (Data, no ++ * post increment) and DEVAD field to the same device ++ * address value for the desired MMD; ++ */ ++ mmd_control.u16 = 0; ++ mmd_control.s.function = MDIO_CLAUSE_45_READ; ++ mmd_control.s.devad = device; ++ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, ++ mmd_control.u16); ++ ++ /* ++ * d) From Register 14, read the content of the MMD's selected ++ * register. ++ */ ++ return cvmx_mdio_read(bus_id, phy_id, ++ CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA); ++} ++ ++/** ++ * Perform an IEEE 802.3 clause 45 MII write using clause 22 ++ * operations. This function is used to write PHY registers ++ * controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @device: MDIO Managable Device (MMD) id ++ * @location: Register location to write ++ * @val: Value to write ++ * ++ * Returns -1 on error ++ * 0 on success ++ */ ++static inline int cvmx_mdio_45_via_22_write(int bus_id, int phy_id, int device, ++ int location, int val) ++{ ++ union cvmx_mdio_phy_reg_mmd_control mmd_control; ++ ++ /* ++ * a) To Register 13, write the Function field to 00 (address) ++ * and DEVAD field to the device address value for the ++ * desired MMD; ++ */ ++ mmd_control.u16 = 0; ++ mmd_control.s.function = MDIO_CLAUSE_45_ADDRESS; ++ mmd_control.s.devad = device; ++ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, ++ mmd_control.u16); ++ ++ /* ++ * b) To Register 14, write the desired address value to the ++ * MMD's address register; ++ */ ++ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, ++ location); ++ ++ /* ++ * c) To Register 13, write the Function field to 01 (Data, no ++ * post increment) and DEVAD field to the same device ++ * address value for the desired MMD; ++ */ ++ mmd_control.u16 = 0; ++ mmd_control.s.function = MDIO_CLAUSE_45_READ; ++ mmd_control.s.devad = device; ++ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, ++ mmd_control.u16); ++ ++ /* ++ * d) To Register 14, write the content of the MMD's selected ++ * register. ++ */ ++ return cvmx_mdio_write(bus_id, phy_id, ++ CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, val); ++ ++ return 0; ++} ++ ++/** ++ * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY ++ * registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @device: MDIO Managable Device (MMD) id ++ * @location: Register location to read ++ * ++ * Returns Result from the read or -1 on failure ++ */ ++ ++static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, ++ int location) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_rd_dat smi_rd; ++ union cvmx_smix_wr_dat smi_wr; ++ int timeout = 1000; ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = location; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); ++ } while (smi_rd.s.pending && timeout--); ++ ++ if (0 == timeout) ++ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " ++ "device %2d register %2d TIME OUT\n", ++ bus_id, phy_id, device, location); ++ ++ if (smi_rd.s.val) ++ return smi_rd.s.dat; ++ else { ++ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " ++ "device %2d register %2d INVALID READ\n", ++ bus_id, phy_id, device, location); ++ return -1; ++ } ++} ++ ++/** ++ * Perform an IEEE 802.3 clause 45 MII write. This function is used to ++ * write PHY registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @device: MDIO Managable Device (MMD) id ++ * @location: Register location to write ++ * @val: Value to write ++ * ++ * Returns -1 on error ++ * 0 on success ++ */ ++static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, ++ int location, int val) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_wr_dat smi_wr; ++ int timeout = 1000; ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = location; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = val; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ return 0; ++} ++ ++#endif +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -2035,6 +2035,14 @@ config ATL2 + To compile this driver as a module, choose M here. The module + will be called atl2. + ++config OCTEON_MGMT ++ tristate "OCTEON Management port ethernet driver (CN5XXX)" ++ depends on CPU_CAVIUM_OCTEON ++ default y ++ help ++ This option enables the ethernet driver for the management port on ++ CN52XX, CN57XX, CN56XX, CN55XX, and CN54XX chips. ++ + source "drivers/net/fs_enet/Kconfig" + + endif # NET_ETHERNET +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -234,6 +234,7 @@ pasemi_mac_driver-objs := pasemi_mac.o p + obj-$(CONFIG_MLX4_CORE) += mlx4/ + obj-$(CONFIG_ENC28J60) += enc28j60.o + obj-$(CONFIG_ETHOC) += ethoc.o ++obj-$(CONFIG_OCTEON_MGMT) += octeon/ + + obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o + +--- /dev/null ++++ b/drivers/net/octeon/Makefile +@@ -0,0 +1,11 @@ ++# Makefile for the Cavium OCTEON Ethernet drivers. ++# ++# This file is subject to the terms and conditions of the GNU General Public ++# License. See the file "COPYING" in the main directory of this archive ++# for more details. ++# ++# Copyright (C) 2008 Cavium Networks ++ ++obj-$(CONFIG_OCTEON_MGMT) += octeon_mgmt.o ++ ++octeon_mgmt-objs := octeon-mgmt-port.o cvmx-mgmt-port.o +\ No newline at end of file +--- /dev/null ++++ b/drivers/net/octeon/cvmx-mgmt-port.c +@@ -0,0 +1,818 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Support functions for managing the MII management port ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "cvmx-mgmt-port.h" ++ ++#define CVMX_MGMT_PORT_NUM_PORTS 2 ++/* Number of TX ring buffer entries and buffers */ ++#define CVMX_MGMT_PORT_NUM_TX_BUFFERS 16 ++/* Number of RX ring buffer entries and buffers */ ++#define CVMX_MGMT_PORT_NUM_RX_BUFFERS 128 ++ ++#define CVMX_MGMT_PORT_TX_BUFFER_SIZE 12288 ++#define CVMX_MGMT_PORT_RX_BUFFER_SIZE 1536 ++ ++/** ++ * Format of the TX/RX ring buffer entries ++ */ ++union cvmx_mgmt_port_ring_entry { ++ uint64_t u64; ++ struct { ++ uint64_t reserved_62_63:2; ++ /* Length of the buffer/packet in bytes */ ++ uint64_t len:14; ++ /* The RX error code */ ++ uint64_t code:8; ++ /* Physical address of the buffer */ ++ uint64_t addr:40; ++ } s; ++}; ++ ++/** ++ * Per port state required for each mgmt port ++ */ ++struct cvmx_mgmt_port_state { ++ /* Used for exclusive access to this structure */ ++ cvmx_spinlock_t lock; ++ /* Where the next TX will write in the tx_ring and tx_buffers */ ++ int tx_write_index; ++ /* Where the next RX will be in the rx_ring and rx_buffers */ ++ int rx_read_index; ++ /* The SMI/MDIO PHY address */ ++ int phy_id; ++ /* Our MAC address */ ++ uint64_t mac; ++ union cvmx_mgmt_port_ring_entry tx_ring[CVMX_MGMT_PORT_NUM_TX_BUFFERS]; ++ union cvmx_mgmt_port_ring_entry rx_ring[CVMX_MGMT_PORT_NUM_RX_BUFFERS]; ++ char tx_buffers[CVMX_MGMT_PORT_NUM_TX_BUFFERS] ++ [CVMX_MGMT_PORT_TX_BUFFER_SIZE]; ++ char rx_buffers[CVMX_MGMT_PORT_NUM_RX_BUFFERS] ++ [CVMX_MGMT_PORT_RX_BUFFER_SIZE]; ++}; ++ ++/** ++ * Pointers to each mgmt port's state ++ */ ++struct cvmx_mgmt_port_state *cvmx_mgmt_port_state_ptr; ++ ++/** ++ * Return the number of management ports supported by this chip ++ * ++ * Returns Number of ports ++ */ ++int __cvmx_mgmt_port_num_ports(void) ++{ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) ++ return 1; ++ else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ return 2; ++ else ++ return 0; ++} ++ ++/** ++ * Called to initialize a management port for use. Multiple calls ++ * to this function accross applications is safe. ++ * ++ * @port: Port to initialize ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++enum cvmx_mgmt_port_result cvmx_mgmt_port_initialize(int port) ++{ ++ char *alloc_name = "cvmx_mgmt_port"; ++ union cvmx_mixx_oring1 oring1; ++ union cvmx_mixx_ctl mix_ctl; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ cvmx_mgmt_port_state_ptr = ++ cvmx_bootmem_alloc_named(CVMX_MGMT_PORT_NUM_PORTS * ++ sizeof(struct cvmx_mgmt_port_state), 128, ++ alloc_name); ++ if (cvmx_mgmt_port_state_ptr) { ++ memset(cvmx_mgmt_port_state_ptr, 0, ++ CVMX_MGMT_PORT_NUM_PORTS * ++ sizeof(struct cvmx_mgmt_port_state)); ++ } else { ++ struct cvmx_bootmem_named_block_desc *block_desc = ++ cvmx_bootmem_find_named_block(alloc_name); ++ if (block_desc) ++ cvmx_mgmt_port_state_ptr = ++ cvmx_phys_to_ptr(block_desc->base_addr); ++ else { ++ cvmx_dprintf("ERROR: cvmx_mgmt_port_initialize: " ++ "Unable to get named block %s.\n", ++ alloc_name); ++ return CVMX_MGMT_PORT_NO_MEMORY; ++ } ++ } ++ ++ /* ++ * Reset the MIX block if the previous user had a different TX ++ * ring size. ++ */ ++ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); ++ if (!mix_ctl.s.reset) { ++ oring1.u64 = cvmx_read_csr(CVMX_MIXX_ORING1(port)); ++ if (oring1.s.osize != CVMX_MGMT_PORT_NUM_TX_BUFFERS) { ++ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); ++ mix_ctl.s.en = 0; ++ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); ++ do { ++ mix_ctl.u64 = ++ cvmx_read_csr(CVMX_MIXX_CTL(port)); ++ } while (mix_ctl.s.busy); ++ mix_ctl.s.reset = 1; ++ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); ++ cvmx_read_csr(CVMX_MIXX_CTL(port)); ++ memset(cvmx_mgmt_port_state_ptr + port, 0, ++ sizeof(struct cvmx_mgmt_port_state)); ++ } ++ } ++ ++ if (cvmx_mgmt_port_state_ptr[port].tx_ring[0].u64 == 0) { ++ struct cvmx_mgmt_port_state *state = ++ cvmx_mgmt_port_state_ptr + port; ++ int i; ++ union cvmx_mixx_bist mix_bist; ++ union cvmx_agl_gmx_bist agl_gmx_bist; ++ union cvmx_mixx_oring1 oring1; ++ union cvmx_mixx_iring1 iring1; ++ union cvmx_mixx_ctl mix_ctl; ++ ++ /* Make sure BIST passed */ ++ mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(port)); ++ if (mix_bist.u64) ++ cvmx_dprintf("WARNING: cvmx_mgmt_port_initialize: " ++ "Managment port MIX failed BIST " ++ "(0x%016llx)\n", ++ (unsigned long long)mix_bist.u64); ++ ++ agl_gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST); ++ if (agl_gmx_bist.u64) ++ cvmx_dprintf("WARNING: cvmx_mgmt_port_initialize: " ++ "Managment port AGL failed BIST " ++ "(0x%016llx)\n", ++ (unsigned long long)agl_gmx_bist.u64); ++ ++ /* Clear all state information */ ++ memset(state, 0, sizeof(*state)); ++ ++ /* Take the control logic out of reset */ ++ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); ++ mix_ctl.s.reset = 0; ++ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); ++ ++ /* Set the PHY address */ ++ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) ++ state->phy_id = -1; ++ else ++ /* Will need to be change to match the board */ ++ state->phy_id = port; ++ ++ /* Create a default MAC address */ ++ state->mac = 0x000000dead000000ull; ++ state->mac += 0xffffff & CAST64(state); ++ ++ /* Setup the TX ring */ ++ for (i = 0; i < CVMX_MGMT_PORT_NUM_TX_BUFFERS; i++) { ++ state->tx_ring[i].s.len = CVMX_MGMT_PORT_TX_BUFFER_SIZE; ++ state->tx_ring[i].s.addr = ++ cvmx_ptr_to_phys(state->tx_buffers[i]); ++ } ++ ++ /* Tell the HW where the TX ring is */ ++ oring1.u64 = 0; ++ oring1.s.obase = cvmx_ptr_to_phys(state->tx_ring) >> 3; ++ oring1.s.osize = CVMX_MGMT_PORT_NUM_TX_BUFFERS; ++ CVMX_SYNCWS; ++ cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64); ++ ++ /* Setup the RX ring */ ++ for (i = 0; i < CVMX_MGMT_PORT_NUM_RX_BUFFERS; i++) { ++ /* This size is -8 due to an errata for CN56XX pass 1 */ ++ state->rx_ring[i].s.len = ++ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8; ++ state->rx_ring[i].s.addr = ++ cvmx_ptr_to_phys(state->rx_buffers[i]); ++ } ++ ++ /* Tell the HW where the RX ring is */ ++ iring1.u64 = 0; ++ iring1.s.ibase = cvmx_ptr_to_phys(state->rx_ring) >> 3; ++ iring1.s.isize = CVMX_MGMT_PORT_NUM_RX_BUFFERS; ++ CVMX_SYNCWS; ++ cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64); ++ cvmx_write_csr(CVMX_MIXX_IRING2(port), ++ CVMX_MGMT_PORT_NUM_RX_BUFFERS); ++ ++ /* Disable the external input/output */ ++ cvmx_mgmt_port_disable(port); ++ ++ /* Set the MAC address filtering up */ ++ cvmx_mgmt_port_set_mac(port, state->mac); ++ ++ /* ++ * Set the default max size to an MTU of 1500 with L2 ++ * and VLAN. ++ */ ++ cvmx_mgmt_port_set_max_packet_size(port, 1518); ++ ++ /* ++ * Enable the port HW. Packets are not allowed until ++ * cvmx_mgmt_port_enable() is called. ++ */ ++ mix_ctl.u64 = 0; ++ /* Strip the ending CRC */ ++ mix_ctl.s.crc_strip = 1; ++ /* Enable the port */ ++ mix_ctl.s.en = 1; ++ /* Arbitration mode */ ++ mix_ctl.s.nbtarb = 0; ++ /* MII CB-request FIFO programmable high watermark */ ++ mix_ctl.s.mrq_hwm = 1; ++ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) ++ || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { ++ /* ++ * Force compensation values, as they are not ++ * determined properly by HW. ++ */ ++ union cvmx_agl_gmx_drv_ctl drv_ctl; ++ ++ drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL); ++ if (port) { ++ drv_ctl.s.byp_en1 = 1; ++ drv_ctl.s.nctl1 = 6; ++ drv_ctl.s.pctl1 = 6; ++ } else { ++ drv_ctl.s.byp_en = 1; ++ drv_ctl.s.nctl = 6; ++ drv_ctl.s.pctl = 6; ++ } ++ cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64); ++ } ++ } ++ return CVMX_MGMT_PORT_SUCCESS; ++} ++ ++/** ++ * Shutdown a management port. This currently disables packet IO ++ * but leaves all hardware and buffers. Another application can then ++ * call initialize() without redoing the hardware setup. ++ * ++ * @port: Management port ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++enum cvmx_mgmt_port_result cvmx_mgmt_port_shutdown(int port) ++{ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ /* Stop packets from comming in */ ++ cvmx_mgmt_port_disable(port); ++ ++ /* ++ * We don't free any memory so the next intialize can reuse ++ * the HW setup. ++ */ ++ return CVMX_MGMT_PORT_SUCCESS; ++} ++ ++/** ++ * Enable packet IO on a management port ++ * ++ * @port: Management port ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++enum cvmx_mgmt_port_result cvmx_mgmt_port_enable(int port) ++{ ++ struct cvmx_mgmt_port_state *state; ++ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; ++ union cvmx_agl_gmx_inf_mode agl_gmx_inf_mode; ++ union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ ++ rxx_frm_ctl.u64 = 0; ++ rxx_frm_ctl.s.pre_align = 1; ++ /* ++ * When set, disables the length check for non-min sized pkts ++ * with padding in the client data. ++ */ ++ rxx_frm_ctl.s.pad_len = 1; ++ /* When set, disables the length check for VLAN pkts */ ++ rxx_frm_ctl.s.vlan_len = 1; ++ /* When set, PREAMBLE checking is less strict */ ++ rxx_frm_ctl.s.pre_free = 1; ++ /* Control Pause Frames can match station SMAC */ ++ rxx_frm_ctl.s.ctl_smac = 0; ++ /* Control Pause Frames can match globally assign Multicast address */ ++ rxx_frm_ctl.s.ctl_mcst = 1; ++ /* Forward pause information to TX block */ ++ rxx_frm_ctl.s.ctl_bck = 1; ++ /* Drop Control Pause Frames */ ++ rxx_frm_ctl.s.ctl_drp = 1; ++ /* Strip off the preamble */ ++ rxx_frm_ctl.s.pre_strp = 1; ++ /* ++ * This port is configured to send PREAMBLE+SFD to begin every ++ * frame. GMX checks that the PREAMBLE is sent correctly. ++ */ ++ rxx_frm_ctl.s.pre_chk = 1; ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64); ++ ++ /* Enable the AGL block */ ++ agl_gmx_inf_mode.u64 = 0; ++ agl_gmx_inf_mode.s.en = 1; ++ cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64); ++ ++ /* Configure the port duplex and enables */ ++ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); ++ agl_gmx_prtx.s.tx_en = 1; ++ agl_gmx_prtx.s.rx_en = 1; ++ if (cvmx_mgmt_port_get_link(port) < 0) ++ agl_gmx_prtx.s.duplex = 0; ++ else ++ agl_gmx_prtx.s.duplex = 1; ++ agl_gmx_prtx.s.en = 1; ++ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); ++ ++ cvmx_spinlock_unlock(&state->lock); ++ return CVMX_MGMT_PORT_SUCCESS; ++} ++ ++/** ++ * Disable packet IO on a management port ++ * ++ * @port: Management port ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++enum cvmx_mgmt_port_result cvmx_mgmt_port_disable(int port) ++{ ++ struct cvmx_mgmt_port_state *state; ++ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ ++ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); ++ agl_gmx_prtx.s.en = 0; ++ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); ++ ++ cvmx_spinlock_unlock(&state->lock); ++ return CVMX_MGMT_PORT_SUCCESS; ++} ++ ++/** ++ * Send a packet out the management port. The packet is copied so ++ * the input buffer isn't used after this call. ++ * ++ * @port: Management port ++ * @packet_len: Length of the packet to send. It does not include the final CRC ++ * @buffer: Packet data ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++enum cvmx_mgmt_port_result cvmx_mgmt_port_send(int port, int packet_len, ++ void *buffer) ++{ ++ struct cvmx_mgmt_port_state *state; ++ union cvmx_mixx_oring2 mix_oring2; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ /* Max sure the packet size is valid */ ++ if ((packet_len < 1) || (packet_len > CVMX_MGMT_PORT_TX_BUFFER_SIZE)) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ if (buffer == NULL) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ ++ mix_oring2.u64 = cvmx_read_csr(CVMX_MIXX_ORING2(port)); ++ if (mix_oring2.s.odbell >= CVMX_MGMT_PORT_NUM_TX_BUFFERS - 1) { ++ /* No room for another packet */ ++ cvmx_spinlock_unlock(&state->lock); ++ return CVMX_MGMT_PORT_NO_MEMORY; ++ } else { ++ /* Copy the packet into the output buffer */ ++ memcpy(state->tx_buffers[state->tx_write_index], buffer, ++ packet_len); ++ /* Insert the source MAC */ ++ memcpy(state->tx_buffers[state->tx_write_index] + 6, ++ ((char *)&state->mac) + 2, 6); ++ /* Update the TX ring buffer entry size */ ++ state->tx_ring[state->tx_write_index].s.len = packet_len; ++ /* Increment our TX index */ ++ state->tx_write_index = ++ (state->tx_write_index + 1) % CVMX_MGMT_PORT_NUM_TX_BUFFERS; ++ /* Ring the doorbell, send ing the packet */ ++ CVMX_SYNCWS; ++ cvmx_write_csr(CVMX_MIXX_ORING2(port), 1); ++ if (cvmx_read_csr(CVMX_MIXX_ORCNT(port))) ++ cvmx_write_csr(CVMX_MIXX_ORCNT(port), ++ cvmx_read_csr(CVMX_MIXX_ORCNT(port))); ++ ++ cvmx_spinlock_unlock(&state->lock); ++ return CVMX_MGMT_PORT_SUCCESS; ++ } ++} ++ ++/** ++ * Receive a packet from the management port. ++ * ++ * @port: Management port ++ * @buffer_len: Size of the buffer to receive the packet into ++ * @buffer: Buffer to receive the packet into ++ * ++ * Returns The size of the packet, or a negative erorr code on failure. Zero ++ * means that no packets were available. ++ */ ++int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer) ++{ ++ union cvmx_mixx_ircnt mix_ircnt; ++ struct cvmx_mgmt_port_state *state; ++ int result; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ /* Max sure the buffer size is valid */ ++ if (buffer_len < 1) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ if (buffer == NULL) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ ++ /* Find out how many RX packets are pending */ ++ mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port)); ++ if (mix_ircnt.s.ircnt) { ++ void *source = state->rx_buffers[state->rx_read_index]; ++ uint64_t *zero_check = source; ++ /* ++ * CN56XX pass 1 has an errata where packets might ++ * start 8 bytes into the buffer instead of at their ++ * correct location. If the first 8 bytes is zero we ++ * assume this has happened. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) ++ && (*zero_check == 0)) ++ source += 8; ++ /* Start off with zero bytes received */ ++ result = 0; ++ /* ++ * While the completion code signals more data, copy ++ * the buffers into the user's data. ++ */ ++ while (state->rx_ring[state->rx_read_index].s.code == 16) { ++ /* Only copy what will fit in the user's buffer */ ++ int length = state->rx_ring[state->rx_read_index].s.len; ++ if (length > buffer_len) ++ length = buffer_len; ++ memcpy(buffer, source, length); ++ /* ++ * Reduce the size of the buffer to the ++ * remaining space. If we run out we will ++ * signal an error when the code 15 buffer ++ * doesn't fit. ++ */ ++ buffer += length; ++ buffer_len -= length; ++ result += length; ++ /* ++ * Update this buffer for reuse in future ++ * receives. This size is -8 due to an errata ++ * for CN56XX pass 1. ++ */ ++ state->rx_ring[state->rx_read_index].s.code = 0; ++ state->rx_ring[state->rx_read_index].s.len = ++ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8; ++ state->rx_read_index = ++ (state->rx_read_index + ++ 1) % CVMX_MGMT_PORT_NUM_RX_BUFFERS; ++ /* ++ * Zero the beginning of the buffer for use by ++ * the errata check. ++ */ ++ *zero_check = 0; ++ CVMX_SYNCWS; ++ /* Increment the number of RX buffers */ ++ cvmx_write_csr(CVMX_MIXX_IRING2(port), 1); ++ source = state->rx_buffers[state->rx_read_index]; ++ zero_check = source; ++ } ++ ++ /* Check for the final good completion code */ ++ if (state->rx_ring[state->rx_read_index].s.code == 15) { ++ if (buffer_len >= ++ state->rx_ring[state->rx_read_index].s.len) { ++ int length = ++ state->rx_ring[state->rx_read_index].s.len; ++ memcpy(buffer, source, length); ++ result += length; ++ } else { ++ /* Not enough room for the packet */ ++ cvmx_dprintf("ERROR: cvmx_mgmt_port_receive: " ++ "Packet (%d) larger than " ++ "supplied buffer (%d)\n", ++ state->rx_ring[state->rx_read_index].s.len, ++ buffer_len); ++ result = CVMX_MGMT_PORT_NO_MEMORY; ++ } ++ } else { ++ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; ++ cvmx_dprintf("ERROR: cvmx_mgmt_port_receive: Receive " ++ "error code %d. Packet dropped(Len %d)\n", ++ state->rx_ring[state->rx_read_index].s.code, ++ state->rx_ring[state->rx_read_index].s.len + ++ result); ++ result = -state->rx_ring[state->rx_read_index].s.code; ++ ++ /* Check to see if we need to change the duplex. */ ++ agl_gmx_prtx.u64 = ++ cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); ++ if (cvmx_mgmt_port_get_link(port) < 0) ++ agl_gmx_prtx.s.duplex = 0; ++ else ++ agl_gmx_prtx.s.duplex = 1; ++ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), ++ agl_gmx_prtx.u64); ++ } ++ ++ /* ++ * Clean out the ring buffer entry. This size is -8 ++ * due to an errata for CN56XX pass 1. ++ */ ++ state->rx_ring[state->rx_read_index].s.code = 0; ++ state->rx_ring[state->rx_read_index].s.len = ++ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8; ++ state->rx_read_index = ++ (state->rx_read_index + 1) % CVMX_MGMT_PORT_NUM_RX_BUFFERS; ++ /* ++ * Zero the beginning of the buffer for use by the ++ * errata check. ++ */ ++ *zero_check = 0; ++ CVMX_SYNCWS; ++ /* Increment the number of RX buffers */ ++ cvmx_write_csr(CVMX_MIXX_IRING2(port), 1); ++ /* Decrement the pending RX count */ ++ cvmx_write_csr(CVMX_MIXX_IRCNT(port), 1); ++ } else { ++ /* No packets available */ ++ result = 0; ++ } ++ cvmx_spinlock_unlock(&state->lock); ++ return result; ++} ++ ++/** ++ * Get the management port link status: ++ * 100 = 100Mbps, full duplex ++ * 10 = 10Mbps, full duplex ++ * 0 = Link down ++ * -10 = 10Mpbs, half duplex ++ * -100 = 100Mbps, half duplex ++ * ++ * @port: Management port ++ * ++ * Returns ++ */ ++int cvmx_mgmt_port_get_link(int port) ++{ ++ struct cvmx_mgmt_port_state *state; ++ int phy_status; ++ int duplex; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ /* Assume 100Mbps if we don't know the PHY address */ ++ if (state->phy_id == -1) ++ return 100; ++ ++ /* Read the PHY state */ ++ phy_status = ++ cvmx_mdio_read(state->phy_id >> 8, state->phy_id & 0xff, 17); ++ ++ /* Only return a link if the PHY has finished auto negotiation ++ and set the resolved bit (bit 11) */ ++ if (!(phy_status & (1 << 11))) ++ return 0; ++ ++ /* Create multiple factor to represent duplex */ ++ if ((phy_status >> 13) & 1) ++ duplex = 1; ++ else ++ duplex = -1; ++ ++ /* Speed is encoded on bits 15-14 */ ++ switch ((phy_status >> 14) & 3) { ++ case 0: /* 10 Mbps */ ++ return 10 * duplex; ++ case 1: /* 100 Mbps */ ++ return 100 * duplex; ++ default: ++ return 0; ++ } ++} ++ ++/** ++ * Set the MAC address for a management port ++ * ++ * @port: Management port ++ * @mac: New MAC address. The lower 6 bytes are used. ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++enum cvmx_mgmt_port_result cvmx_mgmt_port_set_mac(int port, uint64_t mac) ++{ ++ struct cvmx_mgmt_port_state *state; ++ union cvmx_agl_gmx_rxx_adr_ctl agl_gmx_rxx_adr_ctl; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ ++ agl_gmx_rxx_adr_ctl.u64 = 0; ++ /* Only accept matching MAC addresses */ ++ agl_gmx_rxx_adr_ctl.s.cam_mode = 1; ++ /* Drop multicast */ ++ agl_gmx_rxx_adr_ctl.s.mcst = 0; ++ /* Allow broadcast */ ++ agl_gmx_rxx_adr_ctl.s.bcst = 1; ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), agl_gmx_rxx_adr_ctl.u64); ++ ++ /* Only using one of the CAMs */ ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), (mac >> 40) & 0xff); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), (mac >> 32) & 0xff); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), (mac >> 24) & 0xff); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), (mac >> 16) & 0xff); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), (mac >> 8) & 0xff); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), (mac >> 0) & 0xff); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 1); ++ state->mac = mac; ++ ++ cvmx_spinlock_unlock(&state->lock); ++ return CVMX_MGMT_PORT_SUCCESS; ++} ++ ++/** ++ * Get the MAC address for a management port ++ * ++ * @port: Management port ++ * ++ * Returns MAC address ++ */ ++uint64_t cvmx_mgmt_port_get_mac(int port) ++{ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return CVMX_MGMT_PORT_INVALID_PARAM; ++ ++ return cvmx_mgmt_port_state_ptr[port].mac; ++} ++ ++/** ++ * Set the multicast list. ++ * ++ * @port: Management port ++ * @flags: Interface flags ++ * ++ * Returns ++ */ ++void cvmx_mgmt_port_set_multicast_list(int port, int flags) ++{ ++ struct cvmx_mgmt_port_state *state; ++ union cvmx_agl_gmx_rxx_adr_ctl agl_gmx_rxx_adr_ctl; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ ++ agl_gmx_rxx_adr_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port)); ++ ++ /* Allow broadcast MAC addresses */ ++ if (!agl_gmx_rxx_adr_ctl.s.bcst) ++ agl_gmx_rxx_adr_ctl.s.bcst = 1; ++ ++ if ((flags & CVMX_IFF_ALLMULTI) || (flags & CVMX_IFF_PROMISC)) ++ /* Force accept multicast packets */ ++ agl_gmx_rxx_adr_ctl.s.mcst = 2; ++ else ++ /* Force reject multicast packets */ ++ agl_gmx_rxx_adr_ctl.s.mcst = 1; ++ ++ if (flags & CVMX_IFF_PROMISC) ++ /* ++ * Reject matches if promisc. Since CAM is shut off, ++ * should accept everything. ++ */ ++ agl_gmx_rxx_adr_ctl.s.cam_mode = 0; ++ else ++ /* Filter packets based on the CAM */ ++ agl_gmx_rxx_adr_ctl.s.cam_mode = 1; ++ ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), agl_gmx_rxx_adr_ctl.u64); ++ ++ if (flags & CVMX_IFF_PROMISC) ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 0); ++ else ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 1); ++ ++ cvmx_spinlock_unlock(&state->lock); ++} ++ ++/** ++ * Set the maximum packet allowed in. Size is specified ++ * including L2 but without FCS. A normal MTU would corespond ++ * to 1514 assuming the standard 14 byte L2 header. ++ * ++ * @port: Management port ++ * @size_without_fcs: ++ * Size in bytes without FCS ++ */ ++void cvmx_mgmt_port_set_max_packet_size(int port, int size_without_fcs) ++{ ++ struct cvmx_mgmt_port_state *state; ++ ++ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) ++ return; ++ ++ state = cvmx_mgmt_port_state_ptr + port; ++ ++ cvmx_spinlock_lock(&state->lock); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs); ++ cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port), ++ (size_without_fcs + 7) & 0xfff8); ++ cvmx_spinlock_unlock(&state->lock); ++} +--- /dev/null ++++ b/drivers/net/octeon/cvmx-mgmt-port.h +@@ -0,0 +1,168 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Support functions for managing the MII management port ++ * ++ */ ++ ++#ifndef __CVMX_MGMT_PORT_H__ ++#define __CVMX_MGMT_PORT_H__ ++ ++enum cvmx_mgmt_port_result { ++ CVMX_MGMT_PORT_SUCCESS = 0, ++ CVMX_MGMT_PORT_NO_MEMORY = -1, ++ CVMX_MGMT_PORT_INVALID_PARAM = -2, ++}; ++ ++/* Enumeration of Net Device interface flags. */ ++enum cvmx_mgmt_port_netdevice_flags { ++ CVMX_IFF_PROMISC = 0x100, /* receive all packets */ ++ CVMX_IFF_ALLMULTI = 0x200, /* receive all multicast packets */ ++}; ++ ++/** ++ * Called to initialize a management port for use. Multiple calls ++ * to this function accross applications is safe. ++ * ++ * @port: Port to initialize ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++extern enum cvmx_mgmt_port_result cvmx_mgmt_port_initialize(int port); ++ ++/** ++ * Shutdown a management port. This currently disables packet IO ++ * but leaves all hardware and buffers. Another application can then ++ * call initialize() without redoing the hardware setup. ++ * ++ * @port: Management port ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++extern enum cvmx_mgmt_port_result cvmx_mgmt_port_shutdown(int port); ++ ++/** ++ * Enable packet IO on a management port ++ * ++ * @port: Management port ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++extern enum cvmx_mgmt_port_result cvmx_mgmt_port_enable(int port); ++ ++/** ++ * Disable packet IO on a management port ++ * ++ * @port: Management port ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++extern enum cvmx_mgmt_port_result cvmx_mgmt_port_disable(int port); ++ ++/** ++ * Send a packet out the management port. The packet is copied so ++ * the input buffer isn't used after this call. ++ * ++ * @port: Management port ++ * @packet_len: Length of the packet to send. It does not include the final CRC ++ * @buffer: Packet data ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++extern enum cvmx_mgmt_port_result cvmx_mgmt_port_send(int port, int packet_len, ++ void *buffer); ++ ++/** ++ * Receive a packet from the management port. ++ * ++ * @port: Management port ++ * @buffer_len: Size of the buffer to receive the packet into ++ * @buffer: Buffer to receive the packet into ++ * ++ * Returns The size of the packet, or a negative erorr code on failure. Zero ++ * means that no packets were available. ++ */ ++extern int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer); ++ ++/** ++ * Get the management port link status: ++ * 100 = 100Mbps, full duplex ++ * 10 = 10Mbps, full duplex ++ * 0 = Link down ++ * -10 = 10Mpbs, half duplex ++ * -100 = 100Mbps, half duplex ++ * ++ * @port: Management port ++ * ++ * Returns ++ */ ++extern int cvmx_mgmt_port_get_link(int port); ++ ++/** ++ * Set the MAC address for a management port ++ * ++ * @port: Management port ++ * @mac: New MAC address. The lower 6 bytes are used. ++ * ++ * Returns CVMX_MGMT_PORT_SUCCESS or an error code ++ */ ++extern enum cvmx_mgmt_port_result cvmx_mgmt_port_set_mac(int port, ++ uint64_t mac); ++ ++/** ++ * Get the MAC address for a management port ++ * ++ * @port: Management port ++ * ++ * Returns MAC address ++ */ ++extern uint64_t cvmx_mgmt_port_get_mac(int port); ++ ++/** ++ * Set the multicast list. ++ * ++ * @port: Management port ++ * @flags: Interface flags ++ * ++ * Returns ++ */ ++extern void cvmx_mgmt_port_set_multicast_list(int port, int flags); ++ ++/** ++ * Set the maximum packet allowed in. Size is specified ++ * including L2 but without FCS. A normal MTU would corespond ++ * to 1514 assuming the standard 14 byte L2 header. ++ * ++ * @port: Management port ++ * @size_without_crc: ++ * Size in bytes without FCS ++ */ ++extern void cvmx_mgmt_port_set_max_packet_size(int port, int size_without_fcs); ++ ++#endif /* __CVMX_MGMT_PORT_H__ */ +--- /dev/null ++++ b/drivers/net/octeon/octeon-mgmt-port.c +@@ -0,0 +1,389 @@ ++/* ++ * Octeon Management Port Ethernet Driver ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2007, 2008 Cavium Networks ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "cvmx-mgmt-port.h" ++ ++static struct net_device *global_dev[2] = { NULL, NULL }; ++ ++#define DEBUGPRINT(format, ...) do {if (printk_ratelimit()) \ ++ printk(format, ##__VA_ARGS__); \ ++ } while (0) ++ ++/** ++ * This is the definition of the Ethernet driver's private ++ * driver state stored in dev->priv. ++ */ ++struct device_private { ++ int port; ++ struct net_device_stats stats; /* Device statistics */ ++}; ++ ++ ++/** ++ * Packet transmit ++ * ++ * @param skb Packet to send ++ * @param dev Device info structure ++ * @return Always returns zero ++ */ ++static int packet_transmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ uint64_t flags; ++ struct device_private *priv = netdev_priv(dev); ++ enum cvmx_mgmt_port_result result; ++ local_irq_save(flags); ++ result = cvmx_mgmt_port_send(priv->port, skb->len, skb->data); ++ local_irq_restore(flags); ++ if (result == CVMX_MGMT_PORT_SUCCESS) { ++ priv->stats.tx_packets++; ++ priv->stats.tx_bytes += skb->len; ++ } else { ++ /* DEBUGPRINT("ERROR: cvmx_mgmt_port_send() failed with %d\n", ++ result); ++ */ ++ priv->stats.tx_dropped++; ++ } ++ dev_kfree_skb(skb); ++ return 0; ++} ++ ++ ++/** ++ * Interrupt handler. The interrupt occurs whenever the POW ++ * transitions from 0->1 packets in our group. ++ * ++ * @param cpl ++ * @param dev_id ++ * @param regs ++ * @return ++ */ ++static irqreturn_t do_interrupt(int cpl, void *dev_id) ++{ ++ uint64_t flags; ++ struct sk_buff *skb; ++ int result; ++ char packet[2048]; ++ struct net_device *dev = (struct net_device *) dev_id; ++ struct device_private *priv = netdev_priv(dev); ++ ++ do { ++ local_irq_save(flags); ++ result = cvmx_mgmt_port_receive(priv->port, sizeof(packet), ++ packet); ++ local_irq_restore(flags); ++ ++ /* Silently drop packets if we aren't up */ ++ if ((dev->flags & IFF_UP) == 0) ++ continue; ++ ++ if (result > 0) { ++ skb = dev_alloc_skb(result); ++ if (skb) { ++ memcpy(skb_put(skb, result), packet, result); ++ skb->protocol = eth_type_trans(skb, dev); ++ skb->dev = dev; ++ skb->ip_summed = CHECKSUM_NONE; ++ priv->stats.rx_bytes += skb->len; ++ priv->stats.rx_packets++; ++ netif_rx(skb); ++ } else { ++ DEBUGPRINT("%s: Failed to allocate skbuff, " ++ "packet dropped\n", ++ dev->name); ++ priv->stats.rx_dropped++; ++ } ++ } else if (result < 0) { ++ DEBUGPRINT("%s: Receive error code %d, packet " ++ "dropped\n", ++ dev->name, result); ++ priv->stats.rx_errors++; ++ } ++ } while (result != 0); ++ ++ /* Clear any pending interrupts */ ++ cvmx_write_csr(CVMX_MIXX_ISR(priv->port), ++ cvmx_read_csr(CVMX_MIXX_ISR(priv->port))); ++ cvmx_read_csr(CVMX_MIXX_ISR(priv->port)); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/** ++ * This is called when the kernel needs to manually poll the ++ * device. For Octeon, this is simply calling the interrupt ++ * handler. We actually poll all the devices, not just the ++ * one supplied. ++ * ++ * @param dev Device to poll. Unused ++ */ ++static void device_poll_controller(struct net_device *dev) ++{ ++ do_interrupt(0, dev); ++} ++#endif ++ ++ ++/** ++ * Open a device for use. Device should be able to send and ++ * receive packets after this is called. ++ * ++ * @param dev Device to bring up ++ * @return Zero on success ++ */ ++static int device_open(struct net_device *dev) ++{ ++ /* Clear the statistics whenever the interface is brought up */ ++ struct device_private *priv = netdev_priv(dev); ++ memset(&priv->stats, 0, sizeof(priv->stats)); ++ cvmx_mgmt_port_enable(priv->port); ++ return 0; ++} ++ ++ ++/** ++ * Stop an ethernet device. No more packets should be ++ * received from this device. ++ * ++ * @param dev Device to bring down ++ * @return Zero on success ++ */ ++static int device_close(struct net_device *dev) ++{ ++ struct device_private *priv = netdev_priv(dev); ++ cvmx_mgmt_port_disable(priv->port); ++ return 0; ++} ++ ++ ++/** ++ * Get the low level ethernet statistics ++ * ++ * @param dev Device to get the statistics from ++ * @return Pointer to the statistics ++ */ ++static struct net_device_stats *device_get_stats(struct net_device *dev) ++{ ++ struct device_private *priv = netdev_priv(dev); ++ return &priv->stats; ++} ++ ++/** ++ * Set the multicast list. Currently unimplemented. ++ * ++ * @param dev Device to work on ++ */ ++static void ethernet_mgmt_port_set_multicast_list(struct net_device *dev) ++{ ++ struct device_private *priv = netdev_priv(dev); ++ int port = priv->port; ++ int num_ports; ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ num_ports = 2; ++ else ++ num_ports = 1; ++ if (port < num_ports) ++ cvmx_mgmt_port_set_multicast_list(port, dev->flags); ++} ++ ++/** ++ * Set the hardware MAC address for a management port device ++ * ++ * @param dev Device to change the MAC address for ++ * @param addr Address structure to change it too. MAC address is addr + 2. ++ * @return Zero on success ++ */ ++static int ethernet_mgmt_port_set_mac_address(struct net_device *dev, ++ void *addr) ++{ ++ struct device_private *priv = netdev_priv(dev); ++ union cvmx_agl_gmx_prtx_cfg agl_gmx_cfg; ++ int port = priv->port; ++ int num_ports; ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ num_ports = 2; ++ else ++ num_ports = 1; ++ ++ memcpy(dev->dev_addr, addr + 2, 6); ++ ++ if (port < num_ports) { ++ int i; ++ uint8_t *ptr = addr; ++ uint64_t mac = 0; ++ for (i = 0; i < 6; i++) ++ mac = (mac<<8) | (uint64_t)(ptr[i+2]); ++ ++ agl_gmx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); ++ cvmx_mgmt_port_set_mac(port, mac); ++ ethernet_mgmt_port_set_multicast_list(dev); ++ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_cfg.u64); ++ } ++ return 0; ++} ++ ++/** ++ * Per network device initialization ++ * ++ * @param dev Device to initialize ++ * @return Zero on success ++ */ ++static int device_init(struct net_device *dev) ++{ ++ struct device_private *priv = netdev_priv(dev); ++ uint64_t mac = cvmx_mgmt_port_get_mac(priv->port); ++ ++ dev->hard_start_xmit = packet_transmit; ++ dev->get_stats = device_get_stats; ++ dev->open = device_open; ++ dev->stop = device_close; ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ dev->poll_controller = device_poll_controller; ++#endif ++ dev->dev_addr[0] = (mac >> 40) & 0xff; ++ dev->dev_addr[1] = (mac >> 32) & 0xff; ++ dev->dev_addr[2] = (mac >> 24) & 0xff; ++ dev->dev_addr[3] = (mac >> 16) & 0xff; ++ dev->dev_addr[4] = (mac >> 8) & 0xff; ++ dev->dev_addr[5] = (mac >> 0) & 0xff; ++ return 0; ++} ++ ++ ++/** ++ * Module/ driver initialization. Creates the linux network ++ * devices. ++ * ++ * @return Zero on success ++ */ ++static int __init ethernet_mgmt_port_init(void) ++{ ++ struct net_device *dev; ++ struct device_private *priv; ++ union cvmx_mixx_irhwm mix_irhwm; ++ union cvmx_mixx_intena mix_intena; ++ int num_ports; ++ int port; ++ ++ if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ return 0; ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ num_ports = 2; ++ else ++ num_ports = 1; ++ ++ printk("Octeon management port ethernet driver\n"); ++ ++ for (port = 0; port < num_ports; port++) { ++ if (cvmx_mgmt_port_initialize(port) != CVMX_MGMT_PORT_SUCCESS) { ++ pr_err("ERROR: cvmx_mgmt_port_initialize(%d) " ++ "failed\n", port); ++ return -1; ++ } ++ ++ /* Setup is complete, create the virtual ethernet devices */ ++ dev = alloc_etherdev(sizeof(struct device_private)); ++ if (dev == NULL) { ++ pr_err("ERROR: Failed to allocate ethernet device\n"); ++ return -1; ++ } ++ ++ dev->init = device_init; ++ strcpy(dev->name, "mgmt%d"); ++ ++ /* Initialize the device private structure. */ ++ priv = netdev_priv(dev); ++ memset(priv, 0, sizeof(struct device_private)); ++ priv->port = port; ++ ++ if (register_netdev(dev) < 0) { ++ pr_err("ERROR: Failed to register ethernet device\n"); ++ kfree(dev); ++ return -1; ++ } ++ ++ /* Clear any pending interrupts */ ++ cvmx_write_csr(CVMX_MIXX_ISR(priv->port), ++ cvmx_read_csr(CVMX_MIXX_ISR(priv->port))); ++ ++ /* Register an IRQ hander for to receive interrupts */ ++ dev->irq = ++ (priv->port == 0) ? OCTEON_IRQ_MII0 : OCTEON_IRQ_MII1; ++ if (request_irq(dev->irq, do_interrupt, IRQF_SHARED, dev->name, ++ dev)) ++ pr_err("ethernet-mgmt: Failed to assign " ++ "interrupt %d\n", dev->irq); ++ ++ /* Interrupt every single RX packet */ ++ mix_irhwm.u64 = 0; ++ mix_irhwm.s.irhwm = 0; ++ cvmx_write_csr(CVMX_MIXX_IRHWM(priv->port), mix_irhwm.u64); ++ ++ /* Enable receive interrupts */ ++ mix_intena.u64 = 0; ++ mix_intena.s.ithena = 1; ++ cvmx_write_csr(CVMX_MIXX_INTENA(priv->port), mix_intena.u64); ++ ++ global_dev[priv->port] = dev; ++ ++ dev->set_mac_address = ethernet_mgmt_port_set_mac_address; ++ dev->set_multicast_list = ethernet_mgmt_port_set_multicast_list; ++ } ++ return 0; ++} ++ ++ ++/** ++ * Module / driver shutdown ++ * ++ * @return Zero on success ++ */ ++static void __exit ethernet_mgmt_port_cleanup(void) ++{ ++ int port; ++ for (port = 0; port < 2; port++) { ++ if (global_dev[port]) { ++ struct device_private *priv = ++ netdev_priv(global_dev[port]); ++ /* Disable interrupt */ ++ cvmx_write_csr(CVMX_MIXX_IRHWM(priv->port), 0); ++ cvmx_write_csr(CVMX_MIXX_INTENA(priv->port), 0); ++ cvmx_mgmt_port_shutdown(priv->port); ++ ++ /* Free the interrupt handler */ ++ free_irq(global_dev[port]->irq, global_dev[port]); ++ ++ /* Free the ethernet devices */ ++ unregister_netdev(global_dev[port]); ++ kfree(global_dev[port]); ++ global_dev[port] = NULL; ++ } ++ } ++} ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Cavium Networks "); ++MODULE_DESCRIPTION("Cavium Networks Octeon management port ethernet driver."); ++module_init(ethernet_mgmt_port_init); ++module_exit(ethernet_mgmt_port_cleanup); diff --git a/target/linux/octeon/patches-2.6.30/007-export_cvmx_sysinfo.patch b/target/linux/octeon/patches-2.6.30/007-export_cvmx_sysinfo.patch new file mode 100644 index 0000000000..318916d15b --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/007-export_cvmx_sysinfo.patch @@ -0,0 +1,23 @@ +Signed-off-by: David Daney +--- + arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +--- a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c +@@ -29,6 +29,7 @@ + * This module provides system/board/application information obtained + * by the bootloader. + */ ++#include + + #include + #include +@@ -69,6 +70,7 @@ struct cvmx_sysinfo *cvmx_sysinfo_get(vo + { + return &(state.sysinfo); + } ++EXPORT_SYMBOL(cvmx_sysinfo_get); + + /** + * This function is used in non-simple executive environments (such as diff --git a/target/linux/octeon/patches-2.6.30/008-more_board_types_constraints.patch b/target/linux/octeon/patches-2.6.30/008-more_board_types_constraints.patch new file mode 100644 index 0000000000..bb375852ff --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/008-more_board_types_constraints.patch @@ -0,0 +1,37 @@ +The bootloader now uses additional board type constants. The +octeon-ethernet driver needs some of the new values. + +Signed-off-by: David Daney +--- + arch/mips/include/asm/octeon/cvmx-bootinfo.h | 13 +++++++++++++ + 1 files changed, 13 insertions(+), 0 deletions(-) + +--- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h ++++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h +@@ -157,6 +157,13 @@ enum cvmx_board_types_enum { + CVMX_BOARD_TYPE_NIC_XLE_4G = 21, + CVMX_BOARD_TYPE_EBT5600 = 22, + CVMX_BOARD_TYPE_EBH5201 = 23, ++ CVMX_BOARD_TYPE_EBT5200 = 24, ++ CVMX_BOARD_TYPE_CB5600 = 25, ++ CVMX_BOARD_TYPE_CB5601 = 26, ++ CVMX_BOARD_TYPE_CB5200 = 27, ++ /* Special 'generic' board type, supports many boards */ ++ CVMX_BOARD_TYPE_GENERIC = 28, ++ CVMX_BOARD_TYPE_EBH5610 = 29, + CVMX_BOARD_TYPE_MAX, + + /* +@@ -228,6 +235,12 @@ static inline const char *cvmx_board_typ + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201) ++ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5200) ++ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5600) ++ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5601) ++ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5200) ++ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC) ++ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5610) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX) + + /* Customer boards listed here */ diff --git a/target/linux/octeon/patches-2.6.30/009-more_chip_specific_feature_tests.patch b/target/linux/octeon/patches-2.6.30/009-more_chip_specific_feature_tests.patch new file mode 100644 index 0000000000..63dc4f13de --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/009-more_chip_specific_feature_tests.patch @@ -0,0 +1,51 @@ +The octeon-ethernet driver needs to check for additional chip specific +features, we add them to the octeon_has_feature() framework. + +Signed-off-by: David Daney +--- + arch/mips/include/asm/octeon/octeon-feature.h | 27 +++++++++++++++++++++++++ + 1 files changed, 27 insertions(+), 0 deletions(-) + +--- a/arch/mips/include/asm/octeon/octeon-feature.h ++++ b/arch/mips/include/asm/octeon/octeon-feature.h +@@ -57,6 +57,13 @@ enum octeon_feature { + OCTEON_FEATURE_RAID, + /* Octeon has a builtin USB */ + OCTEON_FEATURE_USB, ++ /* Octeon IPD can run without using work queue entries */ ++ OCTEON_FEATURE_NO_WPTR, ++ /* Octeon has DFA state machines */ ++ OCTEON_FEATURE_DFA, ++ /* Octeon MDIO block supports clause 45 transactions for 10 ++ * Gig support */ ++ OCTEON_FEATURE_MDIO_CLAUSE_45, + }; + + static inline int cvmx_fuse_read(int fuse); +@@ -112,6 +119,26 @@ static inline int octeon_has_feature(enu + case OCTEON_FEATURE_USB: + return !(OCTEON_IS_MODEL(OCTEON_CN38XX) + || OCTEON_IS_MODEL(OCTEON_CN58XX)); ++ case OCTEON_FEATURE_NO_WPTR: ++ return (OCTEON_IS_MODEL(OCTEON_CN56XX) ++ || OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) ++ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X); ++ case OCTEON_FEATURE_DFA: ++ if (!OCTEON_IS_MODEL(OCTEON_CN38XX) ++ && !OCTEON_IS_MODEL(OCTEON_CN31XX) ++ && !OCTEON_IS_MODEL(OCTEON_CN58XX)) ++ return 0; ++ else if (OCTEON_IS_MODEL(OCTEON_CN3020)) ++ return 0; ++ else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) ++ return 1; ++ else ++ return !cvmx_fuse_read(120); ++ case OCTEON_FEATURE_MDIO_CLAUSE_45: ++ return !(OCTEON_IS_MODEL(OCTEON_CN3XXX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)); + } + return 0; + } diff --git a/target/linux/octeon/patches-2.6.30/010-export_erratum_function.patch b/target/linux/octeon/patches-2.6.30/010-export_erratum_function.patch new file mode 100644 index 0000000000..83b09fbede --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/010-export_erratum_function.patch @@ -0,0 +1,21 @@ +Signed-off-by: David Daney +--- + .../cavium-octeon/executive/cvmx-helper-errata.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +--- a/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c +@@ -33,6 +33,8 @@ + * these functions directly. + * + */ ++#include ++ + #include + + #include +@@ -377,3 +379,4 @@ void __cvmx_helper_errata_qlm_disable_2n + } + cvmx_helper_qlm_jtag_update(qlm); + } ++EXPORT_SYMBOL(__cvmx_helper_errata_qlm_disable_2nd_order_cdr); diff --git a/target/linux/octeon/patches-2.6.30/011-octeon_ethernet_driver.patch b/target/linux/octeon/patches-2.6.30/011-octeon_ethernet_driver.patch new file mode 100644 index 0000000000..dec15866b0 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/011-octeon_ethernet_driver.patch @@ -0,0 +1,26533 @@ +The octeon-ethernet driver supports the sgmii, rgmii, spi, and xaui +ports present on the Cavium OCTEON family of SOCs. These SOCs are +multi-core mips64 processors with existing support over in arch/mips. + +The driver files can be categorized into three basic groups: + +1) Register definitions, these are named cvmx-*-defs.h + +2) Main driver code, these have names that don't start cvmx-. + +3) Interface specific functions and other utility code, names starting +with cvmx- + +Signed-off-by: David Daney +--- + drivers/staging/octeon/Kconfig | 12 + + drivers/staging/octeon/Makefile | 30 + + drivers/staging/octeon/cvmx-address.h | 274 +++ + drivers/staging/octeon/cvmx-asxx-defs.h | 475 +++++ + drivers/staging/octeon/cvmx-cmd-queue.c | 306 +++ + drivers/staging/octeon/cvmx-cmd-queue.h | 617 ++++++ + drivers/staging/octeon/cvmx-config.h | 169 ++ + drivers/staging/octeon/cvmx-dbg-defs.h | 72 + + drivers/staging/octeon/cvmx-fau.h | 597 ++++++ + drivers/staging/octeon/cvmx-fpa-defs.h | 403 ++++ + drivers/staging/octeon/cvmx-fpa.c | 183 ++ + drivers/staging/octeon/cvmx-fpa.h | 299 +++ + drivers/staging/octeon/cvmx-gmxx-defs.h | 2529 +++++++++++++++++++++++ + drivers/staging/octeon/cvmx-helper-board.c | 706 +++++++ + drivers/staging/octeon/cvmx-helper-board.h | 180 ++ + drivers/staging/octeon/cvmx-helper-fpa.c | 243 +++ + drivers/staging/octeon/cvmx-helper-fpa.h | 64 + + drivers/staging/octeon/cvmx-helper-loop.c | 85 + + drivers/staging/octeon/cvmx-helper-loop.h | 59 + + drivers/staging/octeon/cvmx-helper-npi.c | 113 + + drivers/staging/octeon/cvmx-helper-npi.h | 60 + + drivers/staging/octeon/cvmx-helper-rgmii.c | 525 +++++ + drivers/staging/octeon/cvmx-helper-rgmii.h | 110 + + drivers/staging/octeon/cvmx-helper-sgmii.c | 550 +++++ + drivers/staging/octeon/cvmx-helper-sgmii.h | 104 + + drivers/staging/octeon/cvmx-helper-spi.c | 195 ++ + drivers/staging/octeon/cvmx-helper-spi.h | 84 + + drivers/staging/octeon/cvmx-helper-util.c | 433 ++++ + drivers/staging/octeon/cvmx-helper-util.h | 215 ++ + drivers/staging/octeon/cvmx-helper-xaui.c | 348 ++++ + drivers/staging/octeon/cvmx-helper-xaui.h | 103 + + drivers/staging/octeon/cvmx-helper.c | 1058 ++++++++++ + drivers/staging/octeon/cvmx-helper.h | 227 ++ + drivers/staging/octeon/cvmx-interrupt-decodes.c | 371 ++++ + drivers/staging/octeon/cvmx-interrupt-rsl.c | 140 ++ + drivers/staging/octeon/cvmx-ipd.h | 338 +++ + drivers/staging/octeon/cvmx-mdio.h | 506 +++++ + drivers/staging/octeon/cvmx-packet.h | 65 + + drivers/staging/octeon/cvmx-pcsx-defs.h | 370 ++++ + drivers/staging/octeon/cvmx-pcsxx-defs.h | 316 +++ + drivers/staging/octeon/cvmx-pip-defs.h | 1267 ++++++++++++ + drivers/staging/octeon/cvmx-pip.h | 524 +++++ + drivers/staging/octeon/cvmx-pko-defs.h | 1133 ++++++++++ + drivers/staging/octeon/cvmx-pko.c | 506 +++++ + drivers/staging/octeon/cvmx-pko.h | 610 ++++++ + drivers/staging/octeon/cvmx-pow.h | 1982 ++++++++++++++++++ + drivers/staging/octeon/cvmx-scratch.h | 139 ++ + drivers/staging/octeon/cvmx-smix-defs.h | 178 ++ + drivers/staging/octeon/cvmx-spi.c | 667 ++++++ + drivers/staging/octeon/cvmx-spi.h | 269 +++ + drivers/staging/octeon/cvmx-spxx-defs.h | 347 ++++ + drivers/staging/octeon/cvmx-srxx-defs.h | 126 ++ + drivers/staging/octeon/cvmx-stxx-defs.h | 292 +++ + drivers/staging/octeon/cvmx-wqe.h | 397 ++++ + drivers/staging/octeon/ethernet-common.c | 328 +++ + drivers/staging/octeon/ethernet-common.h | 29 + + drivers/staging/octeon/ethernet-defines.h | 134 ++ + drivers/staging/octeon/ethernet-mdio.c | 231 +++ + drivers/staging/octeon/ethernet-mdio.h | 46 + + drivers/staging/octeon/ethernet-mem.c | 198 ++ + drivers/staging/octeon/ethernet-mem.h | 29 + + drivers/staging/octeon/ethernet-proc.c | 256 +++ + drivers/staging/octeon/ethernet-proc.h | 29 + + drivers/staging/octeon/ethernet-rgmii.c | 397 ++++ + drivers/staging/octeon/ethernet-rx.c | 505 +++++ + drivers/staging/octeon/ethernet-rx.h | 33 + + drivers/staging/octeon/ethernet-sgmii.c | 129 ++ + drivers/staging/octeon/ethernet-spi.c | 323 +++ + drivers/staging/octeon/ethernet-tx.c | 634 ++++++ + drivers/staging/octeon/ethernet-tx.h | 32 + + drivers/staging/octeon/ethernet-util.h | 81 + + drivers/staging/octeon/ethernet-xaui.c | 127 ++ + drivers/staging/octeon/ethernet.c | 507 +++++ + drivers/staging/octeon/octeon-ethernet.h | 127 ++ + 74 files changed, 26146 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/octeon/Kconfig + create mode 100644 drivers/staging/octeon/Makefile + create mode 100644 drivers/staging/octeon/cvmx-address.h + create mode 100644 drivers/staging/octeon/cvmx-asxx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-cmd-queue.c + create mode 100644 drivers/staging/octeon/cvmx-cmd-queue.h + create mode 100644 drivers/staging/octeon/cvmx-config.h + create mode 100644 drivers/staging/octeon/cvmx-dbg-defs.h + create mode 100644 drivers/staging/octeon/cvmx-fau.h + create mode 100644 drivers/staging/octeon/cvmx-fpa-defs.h + create mode 100644 drivers/staging/octeon/cvmx-fpa.c + create mode 100644 drivers/staging/octeon/cvmx-fpa.h + create mode 100644 drivers/staging/octeon/cvmx-gmxx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-helper-board.c + create mode 100644 drivers/staging/octeon/cvmx-helper-board.h + create mode 100644 drivers/staging/octeon/cvmx-helper-fpa.c + create mode 100644 drivers/staging/octeon/cvmx-helper-fpa.h + create mode 100644 drivers/staging/octeon/cvmx-helper-loop.c + create mode 100644 drivers/staging/octeon/cvmx-helper-loop.h + create mode 100644 drivers/staging/octeon/cvmx-helper-npi.c + create mode 100644 drivers/staging/octeon/cvmx-helper-npi.h + create mode 100644 drivers/staging/octeon/cvmx-helper-rgmii.c + create mode 100644 drivers/staging/octeon/cvmx-helper-rgmii.h + create mode 100644 drivers/staging/octeon/cvmx-helper-sgmii.c + create mode 100644 drivers/staging/octeon/cvmx-helper-sgmii.h + create mode 100644 drivers/staging/octeon/cvmx-helper-spi.c + create mode 100644 drivers/staging/octeon/cvmx-helper-spi.h + create mode 100644 drivers/staging/octeon/cvmx-helper-util.c + create mode 100644 drivers/staging/octeon/cvmx-helper-util.h + create mode 100644 drivers/staging/octeon/cvmx-helper-xaui.c + create mode 100644 drivers/staging/octeon/cvmx-helper-xaui.h + create mode 100644 drivers/staging/octeon/cvmx-helper.c + create mode 100644 drivers/staging/octeon/cvmx-helper.h + create mode 100644 drivers/staging/octeon/cvmx-interrupt-decodes.c + create mode 100644 drivers/staging/octeon/cvmx-interrupt-rsl.c + create mode 100644 drivers/staging/octeon/cvmx-ipd.h + create mode 100644 drivers/staging/octeon/cvmx-mdio.h + create mode 100644 drivers/staging/octeon/cvmx-packet.h + create mode 100644 drivers/staging/octeon/cvmx-pcsx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-pcsxx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-pip-defs.h + create mode 100644 drivers/staging/octeon/cvmx-pip.h + create mode 100644 drivers/staging/octeon/cvmx-pko-defs.h + create mode 100644 drivers/staging/octeon/cvmx-pko.c + create mode 100644 drivers/staging/octeon/cvmx-pko.h + create mode 100644 drivers/staging/octeon/cvmx-pow.h + create mode 100644 drivers/staging/octeon/cvmx-scratch.h + create mode 100644 drivers/staging/octeon/cvmx-smix-defs.h + create mode 100644 drivers/staging/octeon/cvmx-spi.c + create mode 100644 drivers/staging/octeon/cvmx-spi.h + create mode 100644 drivers/staging/octeon/cvmx-spxx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-srxx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-stxx-defs.h + create mode 100644 drivers/staging/octeon/cvmx-wqe.h + create mode 100644 drivers/staging/octeon/ethernet-common.c + create mode 100644 drivers/staging/octeon/ethernet-common.h + create mode 100644 drivers/staging/octeon/ethernet-defines.h + create mode 100644 drivers/staging/octeon/ethernet-mdio.c + create mode 100644 drivers/staging/octeon/ethernet-mdio.h + create mode 100644 drivers/staging/octeon/ethernet-mem.c + create mode 100644 drivers/staging/octeon/ethernet-mem.h + create mode 100644 drivers/staging/octeon/ethernet-proc.c + create mode 100644 drivers/staging/octeon/ethernet-proc.h + create mode 100644 drivers/staging/octeon/ethernet-rgmii.c + create mode 100644 drivers/staging/octeon/ethernet-rx.c + create mode 100644 drivers/staging/octeon/ethernet-rx.h + create mode 100644 drivers/staging/octeon/ethernet-sgmii.c + create mode 100644 drivers/staging/octeon/ethernet-spi.c + create mode 100644 drivers/staging/octeon/ethernet-tx.c + create mode 100644 drivers/staging/octeon/ethernet-tx.h + create mode 100644 drivers/staging/octeon/ethernet-util.h + create mode 100644 drivers/staging/octeon/ethernet-xaui.c + create mode 100644 drivers/staging/octeon/ethernet.c + create mode 100644 drivers/staging/octeon/octeon-ethernet.h + +--- /dev/null ++++ b/drivers/staging/octeon/Kconfig +@@ -0,0 +1,12 @@ ++config OCTEON_ETHERNET ++ tristate "Cavium Networks Octeon Ethernet support" ++ depends on CPU_CAVIUM_OCTEON ++ select MII ++ help ++ This driver supports the builtin ethernet ports on Cavium ++ Networks' products in the Octeon family. This driver supports the ++ CN3XXX and CN5XXX Octeon processors. ++ ++ To compile this driver as a module, choose M here. The module ++ will be called octeon-ethernet. ++ +--- /dev/null ++++ b/drivers/staging/octeon/Makefile +@@ -0,0 +1,30 @@ ++# This file is subject to the terms and conditions of the GNU General Public ++# License. See the file "COPYING" in the main directory of this archive ++# for more details. ++# ++# Copyright (C) 2005-2009 Cavium Networks ++# ++ ++# ++# Makefile for Cavium OCTEON on-board ethernet driver ++# ++ ++obj-${CONFIG_OCTEON_ETHERNET} := octeon-ethernet.o ++ ++octeon-ethernet-objs := ethernet.o ++octeon-ethernet-objs += ethernet-common.o ++octeon-ethernet-objs += ethernet-mdio.o ++octeon-ethernet-objs += ethernet-mem.o ++octeon-ethernet-objs += ethernet-proc.o ++octeon-ethernet-objs += ethernet-rgmii.o ++octeon-ethernet-objs += ethernet-rx.o ++octeon-ethernet-objs += ethernet-sgmii.o ++octeon-ethernet-objs += ethernet-spi.o ++octeon-ethernet-objs += ethernet-tx.o ++octeon-ethernet-objs += ethernet-xaui.o ++octeon-ethernet-objs += cvmx-pko.o cvmx-spi.o cvmx-cmd-queue.o \ ++ cvmx-helper-board.o cvmx-helper.o cvmx-helper-xaui.o \ ++ cvmx-helper-rgmii.o cvmx-helper-sgmii.o cvmx-helper-npi.o \ ++ cvmx-helper-loop.o cvmx-helper-spi.o cvmx-helper-util.o \ ++ cvmx-interrupt-decodes.o cvmx-interrupt-rsl.o ++ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-address.h +@@ -0,0 +1,274 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2009 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * Typedefs and defines for working with Octeon physical addresses. ++ * ++ */ ++#ifndef __CVMX_ADDRESS_H__ ++#define __CVMX_ADDRESS_H__ ++ ++#if 0 ++typedef enum { ++ CVMX_MIPS_SPACE_XKSEG = 3LL, ++ CVMX_MIPS_SPACE_XKPHYS = 2LL, ++ CVMX_MIPS_SPACE_XSSEG = 1LL, ++ CVMX_MIPS_SPACE_XUSEG = 0LL ++} cvmx_mips_space_t; ++#endif ++ ++typedef enum { ++ CVMX_MIPS_XKSEG_SPACE_KSEG0 = 0LL, ++ CVMX_MIPS_XKSEG_SPACE_KSEG1 = 1LL, ++ CVMX_MIPS_XKSEG_SPACE_SSEG = 2LL, ++ CVMX_MIPS_XKSEG_SPACE_KSEG3 = 3LL ++} cvmx_mips_xkseg_space_t; ++ ++/* decodes <14:13> of a kseg3 window address */ ++typedef enum { ++ CVMX_ADD_WIN_SCR = 0L, ++ /* see cvmx_add_win_dma_dec_t for further decode */ ++ CVMX_ADD_WIN_DMA = 1L, ++ CVMX_ADD_WIN_UNUSED = 2L, ++ CVMX_ADD_WIN_UNUSED2 = 3L ++} cvmx_add_win_dec_t; ++ ++/* decode within DMA space */ ++typedef enum { ++ /* ++ * Add store data to the write buffer entry, allocating it if ++ * necessary. ++ */ ++ CVMX_ADD_WIN_DMA_ADD = 0L, ++ /* send out the write buffer entry to DRAM */ ++ CVMX_ADD_WIN_DMA_SENDMEM = 1L, ++ /* store data must be normal DRAM memory space address in this case */ ++ /* send out the write buffer entry as an IOBDMA command */ ++ CVMX_ADD_WIN_DMA_SENDDMA = 2L, ++ /* see CVMX_ADD_WIN_DMA_SEND_DEC for data contents */ ++ /* send out the write buffer entry as an IO write */ ++ CVMX_ADD_WIN_DMA_SENDIO = 3L, ++ /* store data must be normal IO space address in this case */ ++ /* send out a single-tick command on the NCB bus */ ++ CVMX_ADD_WIN_DMA_SENDSINGLE = 4L, ++ /* no write buffer data needed/used */ ++} cvmx_add_win_dma_dec_t; ++ ++/* ++ * Physical Address Decode ++ * ++ * Octeon-I HW never interprets this X (<39:36> reserved ++ * for future expansion), software should set to 0. ++ * ++ * - 0x0 XXX0 0000 0000 to DRAM Cached ++ * - 0x0 XXX0 0FFF FFFF ++ * ++ * - 0x0 XXX0 1000 0000 to Boot Bus Uncached (Converted to 0x1 00X0 1000 0000 ++ * - 0x0 XXX0 1FFF FFFF + EJTAG to 0x1 00X0 1FFF FFFF) ++ * ++ * - 0x0 XXX0 2000 0000 to DRAM Cached ++ * - 0x0 XXXF FFFF FFFF ++ * ++ * - 0x1 00X0 0000 0000 to Boot Bus Uncached ++ * - 0x1 00XF FFFF FFFF ++ * ++ * - 0x1 01X0 0000 0000 to Other NCB Uncached ++ * - 0x1 FFXF FFFF FFFF devices ++ * ++ * Decode of all Octeon addresses ++ */ ++typedef union { ++ ++ uint64_t u64; ++ /* mapped or unmapped virtual address */ ++ struct { ++ uint64_t R:2; ++ uint64_t offset:62; ++ } sva; ++ ++ /* mapped USEG virtual addresses (typically) */ ++ struct { ++ uint64_t zeroes:33; ++ uint64_t offset:31; ++ } suseg; ++ ++ /* mapped or unmapped virtual address */ ++ struct { ++ uint64_t ones:33; ++ uint64_t sp:2; ++ uint64_t offset:29; ++ } sxkseg; ++ ++ /* ++ * physical address accessed through xkphys unmapped virtual ++ * address. ++ */ ++ struct { ++ uint64_t R:2; /* CVMX_MIPS_SPACE_XKPHYS in this case */ ++ uint64_t cca:3; /* ignored by octeon */ ++ uint64_t mbz:10; ++ uint64_t pa:49; /* physical address */ ++ } sxkphys; ++ ++ /* physical address */ ++ struct { ++ uint64_t mbz:15; ++ /* if set, the address is uncached and resides on MCB bus */ ++ uint64_t is_io:1; ++ /* ++ * the hardware ignores this field when is_io==0, else ++ * device ID. ++ */ ++ uint64_t did:8; ++ /* the hardware ignores <39:36> in Octeon I */ ++ uint64_t unaddr:4; ++ uint64_t offset:36; ++ } sphys; ++ ++ /* physical mem address */ ++ struct { ++ /* techically, <47:40> are dont-cares */ ++ uint64_t zeroes:24; ++ /* the hardware ignores <39:36> in Octeon I */ ++ uint64_t unaddr:4; ++ uint64_t offset:36; ++ } smem; ++ ++ /* physical IO address */ ++ struct { ++ uint64_t mem_region:2; ++ uint64_t mbz:13; ++ /* 1 in this case */ ++ uint64_t is_io:1; ++ /* ++ * The hardware ignores this field when is_io==0, else ++ * device ID. ++ */ ++ uint64_t did:8; ++ /* the hardware ignores <39:36> in Octeon I */ ++ uint64_t unaddr:4; ++ uint64_t offset:36; ++ } sio; ++ ++ /* ++ * Scratchpad virtual address - accessed through a window at ++ * the end of kseg3 ++ */ ++ struct { ++ uint64_t ones:49; ++ /* CVMX_ADD_WIN_SCR (0) in this case */ ++ cvmx_add_win_dec_t csrdec:2; ++ uint64_t addr:13; ++ } sscr; ++ ++ /* there should only be stores to IOBDMA space, no loads */ ++ /* ++ * IOBDMA virtual address - accessed through a window at the ++ * end of kseg3 ++ */ ++ struct { ++ uint64_t ones:49; ++ uint64_t csrdec:2; /* CVMX_ADD_WIN_DMA (1) in this case */ ++ uint64_t unused2:3; ++ uint64_t type:3; ++ uint64_t addr:7; ++ } sdma; ++ ++ struct { ++ uint64_t didspace:24; ++ uint64_t unused:40; ++ } sfilldidspace; ++ ++} cvmx_addr_t; ++ ++/* These macros for used by 32 bit applications */ ++ ++#define CVMX_MIPS32_SPACE_KSEG0 1l ++#define CVMX_ADD_SEG32(segment, add) \ ++ (((int32_t)segment << 31) | (int32_t)(add)) ++ ++/* ++ * Currently all IOs are performed using XKPHYS addressing. Linux uses ++ * the CvmMemCtl register to enable XKPHYS addressing to IO space from ++ * user mode. Future OSes may need to change the upper bits of IO ++ * addresses. The following define controls the upper two bits for all ++ * IO addresses generated by the simple executive library. ++ */ ++#define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS ++ ++/* These macros simplify the process of creating common IO addresses */ ++#define CVMX_ADD_SEG(segment, add) ((((uint64_t)segment) << 62) | (add)) ++#ifndef CVMX_ADD_IO_SEG ++#define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add)) ++#endif ++#define CVMX_ADDR_DIDSPACE(did) (((CVMX_IO_SEG) << 22) | ((1ULL) << 8) | (did)) ++#define CVMX_ADDR_DID(did) (CVMX_ADDR_DIDSPACE(did) << 40) ++#define CVMX_FULL_DID(did, subdid) (((did) << 3) | (subdid)) ++ ++ /* from include/ncb_rsl_id.v */ ++#define CVMX_OCT_DID_MIS 0ULL /* misc stuff */ ++#define CVMX_OCT_DID_GMX0 1ULL ++#define CVMX_OCT_DID_GMX1 2ULL ++#define CVMX_OCT_DID_PCI 3ULL ++#define CVMX_OCT_DID_KEY 4ULL ++#define CVMX_OCT_DID_FPA 5ULL ++#define CVMX_OCT_DID_DFA 6ULL ++#define CVMX_OCT_DID_ZIP 7ULL ++#define CVMX_OCT_DID_RNG 8ULL ++#define CVMX_OCT_DID_IPD 9ULL ++#define CVMX_OCT_DID_PKT 10ULL ++#define CVMX_OCT_DID_TIM 11ULL ++#define CVMX_OCT_DID_TAG 12ULL ++ /* the rest are not on the IO bus */ ++#define CVMX_OCT_DID_L2C 16ULL ++#define CVMX_OCT_DID_LMC 17ULL ++#define CVMX_OCT_DID_SPX0 18ULL ++#define CVMX_OCT_DID_SPX1 19ULL ++#define CVMX_OCT_DID_PIP 20ULL ++#define CVMX_OCT_DID_ASX0 22ULL ++#define CVMX_OCT_DID_ASX1 23ULL ++#define CVMX_OCT_DID_IOB 30ULL ++ ++#define CVMX_OCT_DID_PKT_SEND CVMX_FULL_DID(CVMX_OCT_DID_PKT, 2ULL) ++#define CVMX_OCT_DID_TAG_SWTAG CVMX_FULL_DID(CVMX_OCT_DID_TAG, 0ULL) ++#define CVMX_OCT_DID_TAG_TAG1 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 1ULL) ++#define CVMX_OCT_DID_TAG_TAG2 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 2ULL) ++#define CVMX_OCT_DID_TAG_TAG3 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 3ULL) ++#define CVMX_OCT_DID_TAG_NULL_RD CVMX_FULL_DID(CVMX_OCT_DID_TAG, 4ULL) ++#define CVMX_OCT_DID_TAG_CSR CVMX_FULL_DID(CVMX_OCT_DID_TAG, 7ULL) ++#define CVMX_OCT_DID_FAU_FAI CVMX_FULL_DID(CVMX_OCT_DID_IOB, 0ULL) ++#define CVMX_OCT_DID_TIM_CSR CVMX_FULL_DID(CVMX_OCT_DID_TIM, 0ULL) ++#define CVMX_OCT_DID_KEY_RW CVMX_FULL_DID(CVMX_OCT_DID_KEY, 0ULL) ++#define CVMX_OCT_DID_PCI_6 CVMX_FULL_DID(CVMX_OCT_DID_PCI, 6ULL) ++#define CVMX_OCT_DID_MIS_BOO CVMX_FULL_DID(CVMX_OCT_DID_MIS, 0ULL) ++#define CVMX_OCT_DID_PCI_RML CVMX_FULL_DID(CVMX_OCT_DID_PCI, 0ULL) ++#define CVMX_OCT_DID_IPD_CSR CVMX_FULL_DID(CVMX_OCT_DID_IPD, 7ULL) ++#define CVMX_OCT_DID_DFA_CSR CVMX_FULL_DID(CVMX_OCT_DID_DFA, 7ULL) ++#define CVMX_OCT_DID_MIS_CSR CVMX_FULL_DID(CVMX_OCT_DID_MIS, 7ULL) ++#define CVMX_OCT_DID_ZIP_CSR CVMX_FULL_DID(CVMX_OCT_DID_ZIP, 0ULL) ++ ++#endif /* __CVMX_ADDRESS_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-asxx-defs.h +@@ -0,0 +1,475 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_ASXX_DEFS_H__ ++#define __CVMX_ASXX_DEFS_H__ ++ ++#define CVMX_ASXX_GMII_RX_CLK_SET(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000180ull + (((block_id) & 0) * 0x8000000ull)) ++#define CVMX_ASXX_GMII_RX_DAT_SET(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000188ull + (((block_id) & 0) * 0x8000000ull)) ++#define CVMX_ASXX_INT_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000018ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_INT_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000010ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_MII_RX_DAT_SET(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000190ull + (((block_id) & 0) * 0x8000000ull)) ++#define CVMX_ASXX_PRT_LOOP(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000040ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_BYPASS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000248ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_BYPASS_SETTING(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000250ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_COMP(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000220ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_DATA_DRV(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000218ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_FCRAM_MODE(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000210ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_NCTL_STRONG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000230ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_NCTL_WEAK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000240ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_PCTL_STRONG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000228ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_PCTL_WEAK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000238ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RLD_SETTING(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000258ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RX_CLK_SETX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000020ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RX_PRT_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000000ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RX_WOL(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000100ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RX_WOL_MSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000108ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RX_WOL_POWOK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000118ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_RX_WOL_SIG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000110ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_TX_CLK_SETX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000048ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_TX_COMP_BYP(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000068ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_TX_HI_WATERX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000080ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_ASXX_TX_PRT_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000008ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_asxx_gmii_rx_clk_set { ++ uint64_t u64; ++ struct cvmx_asxx_gmii_rx_clk_set_s { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_gmii_rx_clk_set_s cn30xx; ++ struct cvmx_asxx_gmii_rx_clk_set_s cn31xx; ++ struct cvmx_asxx_gmii_rx_clk_set_s cn50xx; ++}; ++ ++union cvmx_asxx_gmii_rx_dat_set { ++ uint64_t u64; ++ struct cvmx_asxx_gmii_rx_dat_set_s { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_gmii_rx_dat_set_s cn30xx; ++ struct cvmx_asxx_gmii_rx_dat_set_s cn31xx; ++ struct cvmx_asxx_gmii_rx_dat_set_s cn50xx; ++}; ++ ++union cvmx_asxx_int_en { ++ uint64_t u64; ++ struct cvmx_asxx_int_en_s { ++ uint64_t reserved_12_63:52; ++ uint64_t txpsh:4; ++ uint64_t txpop:4; ++ uint64_t ovrflw:4; ++ } s; ++ struct cvmx_asxx_int_en_cn30xx { ++ uint64_t reserved_11_63:53; ++ uint64_t txpsh:3; ++ uint64_t reserved_7_7:1; ++ uint64_t txpop:3; ++ uint64_t reserved_3_3:1; ++ uint64_t ovrflw:3; ++ } cn30xx; ++ struct cvmx_asxx_int_en_cn30xx cn31xx; ++ struct cvmx_asxx_int_en_s cn38xx; ++ struct cvmx_asxx_int_en_s cn38xxp2; ++ struct cvmx_asxx_int_en_cn30xx cn50xx; ++ struct cvmx_asxx_int_en_s cn58xx; ++ struct cvmx_asxx_int_en_s cn58xxp1; ++}; ++ ++union cvmx_asxx_int_reg { ++ uint64_t u64; ++ struct cvmx_asxx_int_reg_s { ++ uint64_t reserved_12_63:52; ++ uint64_t txpsh:4; ++ uint64_t txpop:4; ++ uint64_t ovrflw:4; ++ } s; ++ struct cvmx_asxx_int_reg_cn30xx { ++ uint64_t reserved_11_63:53; ++ uint64_t txpsh:3; ++ uint64_t reserved_7_7:1; ++ uint64_t txpop:3; ++ uint64_t reserved_3_3:1; ++ uint64_t ovrflw:3; ++ } cn30xx; ++ struct cvmx_asxx_int_reg_cn30xx cn31xx; ++ struct cvmx_asxx_int_reg_s cn38xx; ++ struct cvmx_asxx_int_reg_s cn38xxp2; ++ struct cvmx_asxx_int_reg_cn30xx cn50xx; ++ struct cvmx_asxx_int_reg_s cn58xx; ++ struct cvmx_asxx_int_reg_s cn58xxp1; ++}; ++ ++union cvmx_asxx_mii_rx_dat_set { ++ uint64_t u64; ++ struct cvmx_asxx_mii_rx_dat_set_s { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_mii_rx_dat_set_s cn30xx; ++ struct cvmx_asxx_mii_rx_dat_set_s cn50xx; ++}; ++ ++union cvmx_asxx_prt_loop { ++ uint64_t u64; ++ struct cvmx_asxx_prt_loop_s { ++ uint64_t reserved_8_63:56; ++ uint64_t ext_loop:4; ++ uint64_t int_loop:4; ++ } s; ++ struct cvmx_asxx_prt_loop_cn30xx { ++ uint64_t reserved_7_63:57; ++ uint64_t ext_loop:3; ++ uint64_t reserved_3_3:1; ++ uint64_t int_loop:3; ++ } cn30xx; ++ struct cvmx_asxx_prt_loop_cn30xx cn31xx; ++ struct cvmx_asxx_prt_loop_s cn38xx; ++ struct cvmx_asxx_prt_loop_s cn38xxp2; ++ struct cvmx_asxx_prt_loop_cn30xx cn50xx; ++ struct cvmx_asxx_prt_loop_s cn58xx; ++ struct cvmx_asxx_prt_loop_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_bypass { ++ uint64_t u64; ++ struct cvmx_asxx_rld_bypass_s { ++ uint64_t reserved_1_63:63; ++ uint64_t bypass:1; ++ } s; ++ struct cvmx_asxx_rld_bypass_s cn38xx; ++ struct cvmx_asxx_rld_bypass_s cn38xxp2; ++ struct cvmx_asxx_rld_bypass_s cn58xx; ++ struct cvmx_asxx_rld_bypass_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_bypass_setting { ++ uint64_t u64; ++ struct cvmx_asxx_rld_bypass_setting_s { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_rld_bypass_setting_s cn38xx; ++ struct cvmx_asxx_rld_bypass_setting_s cn38xxp2; ++ struct cvmx_asxx_rld_bypass_setting_s cn58xx; ++ struct cvmx_asxx_rld_bypass_setting_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_comp { ++ uint64_t u64; ++ struct cvmx_asxx_rld_comp_s { ++ uint64_t reserved_9_63:55; ++ uint64_t pctl:5; ++ uint64_t nctl:4; ++ } s; ++ struct cvmx_asxx_rld_comp_cn38xx { ++ uint64_t reserved_8_63:56; ++ uint64_t pctl:4; ++ uint64_t nctl:4; ++ } cn38xx; ++ struct cvmx_asxx_rld_comp_cn38xx cn38xxp2; ++ struct cvmx_asxx_rld_comp_s cn58xx; ++ struct cvmx_asxx_rld_comp_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_data_drv { ++ uint64_t u64; ++ struct cvmx_asxx_rld_data_drv_s { ++ uint64_t reserved_8_63:56; ++ uint64_t pctl:4; ++ uint64_t nctl:4; ++ } s; ++ struct cvmx_asxx_rld_data_drv_s cn38xx; ++ struct cvmx_asxx_rld_data_drv_s cn38xxp2; ++ struct cvmx_asxx_rld_data_drv_s cn58xx; ++ struct cvmx_asxx_rld_data_drv_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_fcram_mode { ++ uint64_t u64; ++ struct cvmx_asxx_rld_fcram_mode_s { ++ uint64_t reserved_1_63:63; ++ uint64_t mode:1; ++ } s; ++ struct cvmx_asxx_rld_fcram_mode_s cn38xx; ++ struct cvmx_asxx_rld_fcram_mode_s cn38xxp2; ++}; ++ ++union cvmx_asxx_rld_nctl_strong { ++ uint64_t u64; ++ struct cvmx_asxx_rld_nctl_strong_s { ++ uint64_t reserved_5_63:59; ++ uint64_t nctl:5; ++ } s; ++ struct cvmx_asxx_rld_nctl_strong_s cn38xx; ++ struct cvmx_asxx_rld_nctl_strong_s cn38xxp2; ++ struct cvmx_asxx_rld_nctl_strong_s cn58xx; ++ struct cvmx_asxx_rld_nctl_strong_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_nctl_weak { ++ uint64_t u64; ++ struct cvmx_asxx_rld_nctl_weak_s { ++ uint64_t reserved_5_63:59; ++ uint64_t nctl:5; ++ } s; ++ struct cvmx_asxx_rld_nctl_weak_s cn38xx; ++ struct cvmx_asxx_rld_nctl_weak_s cn38xxp2; ++ struct cvmx_asxx_rld_nctl_weak_s cn58xx; ++ struct cvmx_asxx_rld_nctl_weak_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_pctl_strong { ++ uint64_t u64; ++ struct cvmx_asxx_rld_pctl_strong_s { ++ uint64_t reserved_5_63:59; ++ uint64_t pctl:5; ++ } s; ++ struct cvmx_asxx_rld_pctl_strong_s cn38xx; ++ struct cvmx_asxx_rld_pctl_strong_s cn38xxp2; ++ struct cvmx_asxx_rld_pctl_strong_s cn58xx; ++ struct cvmx_asxx_rld_pctl_strong_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_pctl_weak { ++ uint64_t u64; ++ struct cvmx_asxx_rld_pctl_weak_s { ++ uint64_t reserved_5_63:59; ++ uint64_t pctl:5; ++ } s; ++ struct cvmx_asxx_rld_pctl_weak_s cn38xx; ++ struct cvmx_asxx_rld_pctl_weak_s cn38xxp2; ++ struct cvmx_asxx_rld_pctl_weak_s cn58xx; ++ struct cvmx_asxx_rld_pctl_weak_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rld_setting { ++ uint64_t u64; ++ struct cvmx_asxx_rld_setting_s { ++ uint64_t reserved_13_63:51; ++ uint64_t dfaset:5; ++ uint64_t dfalag:1; ++ uint64_t dfalead:1; ++ uint64_t dfalock:1; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_rld_setting_cn38xx { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } cn38xx; ++ struct cvmx_asxx_rld_setting_cn38xx cn38xxp2; ++ struct cvmx_asxx_rld_setting_s cn58xx; ++ struct cvmx_asxx_rld_setting_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rx_clk_setx { ++ uint64_t u64; ++ struct cvmx_asxx_rx_clk_setx_s { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_rx_clk_setx_s cn30xx; ++ struct cvmx_asxx_rx_clk_setx_s cn31xx; ++ struct cvmx_asxx_rx_clk_setx_s cn38xx; ++ struct cvmx_asxx_rx_clk_setx_s cn38xxp2; ++ struct cvmx_asxx_rx_clk_setx_s cn50xx; ++ struct cvmx_asxx_rx_clk_setx_s cn58xx; ++ struct cvmx_asxx_rx_clk_setx_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rx_prt_en { ++ uint64_t u64; ++ struct cvmx_asxx_rx_prt_en_s { ++ uint64_t reserved_4_63:60; ++ uint64_t prt_en:4; ++ } s; ++ struct cvmx_asxx_rx_prt_en_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t prt_en:3; ++ } cn30xx; ++ struct cvmx_asxx_rx_prt_en_cn30xx cn31xx; ++ struct cvmx_asxx_rx_prt_en_s cn38xx; ++ struct cvmx_asxx_rx_prt_en_s cn38xxp2; ++ struct cvmx_asxx_rx_prt_en_cn30xx cn50xx; ++ struct cvmx_asxx_rx_prt_en_s cn58xx; ++ struct cvmx_asxx_rx_prt_en_s cn58xxp1; ++}; ++ ++union cvmx_asxx_rx_wol { ++ uint64_t u64; ++ struct cvmx_asxx_rx_wol_s { ++ uint64_t reserved_2_63:62; ++ uint64_t status:1; ++ uint64_t enable:1; ++ } s; ++ struct cvmx_asxx_rx_wol_s cn38xx; ++ struct cvmx_asxx_rx_wol_s cn38xxp2; ++}; ++ ++union cvmx_asxx_rx_wol_msk { ++ uint64_t u64; ++ struct cvmx_asxx_rx_wol_msk_s { ++ uint64_t msk:64; ++ } s; ++ struct cvmx_asxx_rx_wol_msk_s cn38xx; ++ struct cvmx_asxx_rx_wol_msk_s cn38xxp2; ++}; ++ ++union cvmx_asxx_rx_wol_powok { ++ uint64_t u64; ++ struct cvmx_asxx_rx_wol_powok_s { ++ uint64_t reserved_1_63:63; ++ uint64_t powerok:1; ++ } s; ++ struct cvmx_asxx_rx_wol_powok_s cn38xx; ++ struct cvmx_asxx_rx_wol_powok_s cn38xxp2; ++}; ++ ++union cvmx_asxx_rx_wol_sig { ++ uint64_t u64; ++ struct cvmx_asxx_rx_wol_sig_s { ++ uint64_t reserved_32_63:32; ++ uint64_t sig:32; ++ } s; ++ struct cvmx_asxx_rx_wol_sig_s cn38xx; ++ struct cvmx_asxx_rx_wol_sig_s cn38xxp2; ++}; ++ ++union cvmx_asxx_tx_clk_setx { ++ uint64_t u64; ++ struct cvmx_asxx_tx_clk_setx_s { ++ uint64_t reserved_5_63:59; ++ uint64_t setting:5; ++ } s; ++ struct cvmx_asxx_tx_clk_setx_s cn30xx; ++ struct cvmx_asxx_tx_clk_setx_s cn31xx; ++ struct cvmx_asxx_tx_clk_setx_s cn38xx; ++ struct cvmx_asxx_tx_clk_setx_s cn38xxp2; ++ struct cvmx_asxx_tx_clk_setx_s cn50xx; ++ struct cvmx_asxx_tx_clk_setx_s cn58xx; ++ struct cvmx_asxx_tx_clk_setx_s cn58xxp1; ++}; ++ ++union cvmx_asxx_tx_comp_byp { ++ uint64_t u64; ++ struct cvmx_asxx_tx_comp_byp_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_asxx_tx_comp_byp_cn30xx { ++ uint64_t reserved_9_63:55; ++ uint64_t bypass:1; ++ uint64_t pctl:4; ++ uint64_t nctl:4; ++ } cn30xx; ++ struct cvmx_asxx_tx_comp_byp_cn30xx cn31xx; ++ struct cvmx_asxx_tx_comp_byp_cn38xx { ++ uint64_t reserved_8_63:56; ++ uint64_t pctl:4; ++ uint64_t nctl:4; ++ } cn38xx; ++ struct cvmx_asxx_tx_comp_byp_cn38xx cn38xxp2; ++ struct cvmx_asxx_tx_comp_byp_cn50xx { ++ uint64_t reserved_17_63:47; ++ uint64_t bypass:1; ++ uint64_t reserved_13_15:3; ++ uint64_t pctl:5; ++ uint64_t reserved_5_7:3; ++ uint64_t nctl:5; ++ } cn50xx; ++ struct cvmx_asxx_tx_comp_byp_cn58xx { ++ uint64_t reserved_13_63:51; ++ uint64_t pctl:5; ++ uint64_t reserved_5_7:3; ++ uint64_t nctl:5; ++ } cn58xx; ++ struct cvmx_asxx_tx_comp_byp_cn58xx cn58xxp1; ++}; ++ ++union cvmx_asxx_tx_hi_waterx { ++ uint64_t u64; ++ struct cvmx_asxx_tx_hi_waterx_s { ++ uint64_t reserved_4_63:60; ++ uint64_t mark:4; ++ } s; ++ struct cvmx_asxx_tx_hi_waterx_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t mark:3; ++ } cn30xx; ++ struct cvmx_asxx_tx_hi_waterx_cn30xx cn31xx; ++ struct cvmx_asxx_tx_hi_waterx_s cn38xx; ++ struct cvmx_asxx_tx_hi_waterx_s cn38xxp2; ++ struct cvmx_asxx_tx_hi_waterx_cn30xx cn50xx; ++ struct cvmx_asxx_tx_hi_waterx_s cn58xx; ++ struct cvmx_asxx_tx_hi_waterx_s cn58xxp1; ++}; ++ ++union cvmx_asxx_tx_prt_en { ++ uint64_t u64; ++ struct cvmx_asxx_tx_prt_en_s { ++ uint64_t reserved_4_63:60; ++ uint64_t prt_en:4; ++ } s; ++ struct cvmx_asxx_tx_prt_en_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t prt_en:3; ++ } cn30xx; ++ struct cvmx_asxx_tx_prt_en_cn30xx cn31xx; ++ struct cvmx_asxx_tx_prt_en_s cn38xx; ++ struct cvmx_asxx_tx_prt_en_s cn38xxp2; ++ struct cvmx_asxx_tx_prt_en_cn30xx cn50xx; ++ struct cvmx_asxx_tx_prt_en_s cn58xx; ++ struct cvmx_asxx_tx_prt_en_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-cmd-queue.c +@@ -0,0 +1,306 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Support functions for managing command queues used for ++ * various hardware blocks. ++ */ ++ ++#include ++ ++#include ++ ++#include "cvmx-config.h" ++#include "cvmx-fpa.h" ++#include "cvmx-cmd-queue.h" ++ ++#include ++#include ++#include "cvmx-pko-defs.h" ++ ++/** ++ * This application uses this pointer to access the global queue ++ * state. It points to a bootmem named block. ++ */ ++__cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr; ++ ++/** ++ * Initialize the Global queue state pointer. ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void) ++{ ++ char *alloc_name = "cvmx_cmd_queues"; ++#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32 ++ extern uint64_t octeon_reserve32_memory; ++#endif ++ ++ if (likely(__cvmx_cmd_queue_state_ptr)) ++ return CVMX_CMD_QUEUE_SUCCESS; ++ ++#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32 ++ if (octeon_reserve32_memory) ++ __cvmx_cmd_queue_state_ptr = ++ cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr), ++ octeon_reserve32_memory, ++ octeon_reserve32_memory + ++ (CONFIG_CAVIUM_RESERVE32 << ++ 20) - 1, 128, alloc_name); ++ else ++#endif ++ __cvmx_cmd_queue_state_ptr = ++ cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr), ++ 128, ++ alloc_name); ++ if (__cvmx_cmd_queue_state_ptr) ++ memset(__cvmx_cmd_queue_state_ptr, 0, ++ sizeof(*__cvmx_cmd_queue_state_ptr)); ++ else { ++ struct cvmx_bootmem_named_block_desc *block_desc = ++ cvmx_bootmem_find_named_block(alloc_name); ++ if (block_desc) ++ __cvmx_cmd_queue_state_ptr = ++ cvmx_phys_to_ptr(block_desc->base_addr); ++ else { ++ cvmx_dprintf ++ ("ERROR: cvmx_cmd_queue_initialize: Unable to get named block %s.\n", ++ alloc_name); ++ return CVMX_CMD_QUEUE_NO_MEMORY; ++ } ++ } ++ return CVMX_CMD_QUEUE_SUCCESS; ++} ++ ++/** ++ * Initialize a command queue for use. The initial FPA buffer is ++ * allocated and the hardware unit is configured to point to the ++ * new command queue. ++ * ++ * @queue_id: Hardware command queue to initialize. ++ * @max_depth: Maximum outstanding commands that can be queued. ++ * @fpa_pool: FPA pool the command queues should come from. ++ * @pool_size: Size of each buffer in the FPA pool (bytes) ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id, ++ int max_depth, int fpa_pool, ++ int pool_size) ++{ ++ __cvmx_cmd_queue_state_t *qstate; ++ cvmx_cmd_queue_result_t result = __cvmx_cmd_queue_init_state_ptr(); ++ if (result != CVMX_CMD_QUEUE_SUCCESS) ++ return result; ++ ++ qstate = __cvmx_cmd_queue_get_state(queue_id); ++ if (qstate == NULL) ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ ++ /* ++ * We artificially limit max_depth to 1<<20 words. It is an ++ * arbitrary limit. ++ */ ++ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH) { ++ if ((max_depth < 0) || (max_depth > 1 << 20)) ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } else if (max_depth != 0) ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ ++ if ((fpa_pool < 0) || (fpa_pool > 7)) ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ if ((pool_size < 128) || (pool_size > 65536)) ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ ++ /* See if someone else has already initialized the queue */ ++ if (qstate->base_ptr_div128) { ++ if (max_depth != (int)qstate->max_depth) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " ++ "Queue already initalized with different " ++ "max_depth (%d).\n", ++ (int)qstate->max_depth); ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } ++ if (fpa_pool != qstate->fpa_pool) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " ++ "Queue already initalized with different " ++ "FPA pool (%u).\n", ++ qstate->fpa_pool); ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } ++ if ((pool_size >> 3) - 1 != qstate->pool_size_m1) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " ++ "Queue already initalized with different " ++ "FPA pool size (%u).\n", ++ (qstate->pool_size_m1 + 1) << 3); ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } ++ CVMX_SYNCWS; ++ return CVMX_CMD_QUEUE_ALREADY_SETUP; ++ } else { ++ union cvmx_fpa_ctl_status status; ++ void *buffer; ++ ++ status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS); ++ if (!status.s.enb) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " ++ "FPA is not enabled.\n"); ++ return CVMX_CMD_QUEUE_NO_MEMORY; ++ } ++ buffer = cvmx_fpa_alloc(fpa_pool); ++ if (buffer == NULL) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " ++ "Unable to allocate initial buffer.\n"); ++ return CVMX_CMD_QUEUE_NO_MEMORY; ++ } ++ ++ memset(qstate, 0, sizeof(*qstate)); ++ qstate->max_depth = max_depth; ++ qstate->fpa_pool = fpa_pool; ++ qstate->pool_size_m1 = (pool_size >> 3) - 1; ++ qstate->base_ptr_div128 = cvmx_ptr_to_phys(buffer) / 128; ++ /* ++ * We zeroed the now serving field so we need to also ++ * zero the ticket. ++ */ ++ __cvmx_cmd_queue_state_ptr-> ++ ticket[__cvmx_cmd_queue_get_index(queue_id)] = 0; ++ CVMX_SYNCWS; ++ return CVMX_CMD_QUEUE_SUCCESS; ++ } ++} ++ ++/** ++ * Shutdown a queue a free it's command buffers to the FPA. The ++ * hardware connected to the queue must be stopped before this ++ * function is called. ++ * ++ * @queue_id: Queue to shutdown ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id) ++{ ++ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); ++ if (qptr == NULL) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Unable to " ++ "get queue information.\n"); ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } ++ ++ if (cvmx_cmd_queue_length(queue_id) > 0) { ++ cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Queue still " ++ "has data in it.\n"); ++ return CVMX_CMD_QUEUE_FULL; ++ } ++ ++ __cvmx_cmd_queue_lock(queue_id, qptr); ++ if (qptr->base_ptr_div128) { ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) qptr->base_ptr_div128 << 7), ++ qptr->fpa_pool, 0); ++ qptr->base_ptr_div128 = 0; ++ } ++ __cvmx_cmd_queue_unlock(qptr); ++ ++ return CVMX_CMD_QUEUE_SUCCESS; ++} ++ ++/** ++ * Return the number of command words pending in the queue. This ++ * function may be relatively slow for some hardware units. ++ * ++ * @queue_id: Hardware command queue to query ++ * ++ * Returns Number of outstanding commands ++ */ ++int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id) ++{ ++ if (CVMX_ENABLE_PARAMETER_CHECKING) { ++ if (__cvmx_cmd_queue_get_state(queue_id) == NULL) ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } ++ ++ /* ++ * The cast is here so gcc with check that all values in the ++ * cvmx_cmd_queue_id_t enumeration are here. ++ */ ++ switch ((cvmx_cmd_queue_id_t) (queue_id & 0xff0000)) { ++ case CVMX_CMD_QUEUE_PKO_BASE: ++ /* ++ * FIXME: Need atomic lock on ++ * CVMX_PKO_REG_READ_IDX. Right now we are normally ++ * called with the queue lock, so that is a SLIGHT ++ * amount of protection. ++ */ ++ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue_id & 0xffff); ++ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ union cvmx_pko_mem_debug9 debug9; ++ debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9); ++ return debug9.cn38xx.doorbell; ++ } else { ++ union cvmx_pko_mem_debug8 debug8; ++ debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); ++ return debug8.cn58xx.doorbell; ++ } ++ case CVMX_CMD_QUEUE_ZIP: ++ case CVMX_CMD_QUEUE_DFA: ++ case CVMX_CMD_QUEUE_RAID: ++ /* FIXME: Implement other lengths */ ++ return 0; ++ case CVMX_CMD_QUEUE_DMA_BASE: ++ { ++ union cvmx_npei_dmax_counts dmax_counts; ++ dmax_counts.u64 = ++ cvmx_read_csr(CVMX_PEXP_NPEI_DMAX_COUNTS ++ (queue_id & 0x7)); ++ return dmax_counts.s.dbell; ++ } ++ case CVMX_CMD_QUEUE_END: ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++ } ++ return CVMX_CMD_QUEUE_INVALID_PARAM; ++} ++ ++/** ++ * Return the command buffer to be written to. The purpose of this ++ * function is to allow CVMX routine access t othe low level buffer ++ * for initial hardware setup. User applications should not call this ++ * function directly. ++ * ++ * @queue_id: Command queue to query ++ * ++ * Returns Command buffer or NULL on failure ++ */ ++void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id) ++{ ++ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); ++ if (qptr && qptr->base_ptr_div128) ++ return cvmx_phys_to_ptr((uint64_t) qptr->base_ptr_div128 << 7); ++ else ++ return NULL; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-cmd-queue.h +@@ -0,0 +1,617 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Support functions for managing command queues used for ++ * various hardware blocks. ++ * ++ * The common command queue infrastructure abstracts out the ++ * software necessary for adding to Octeon's chained queue ++ * structures. These structures are used for commands to the ++ * PKO, ZIP, DFA, RAID, and DMA engine blocks. Although each ++ * hardware unit takes commands and CSRs of different types, ++ * they all use basic linked command buffers to store the ++ * pending request. In general, users of the CVMX API don't ++ * call cvmx-cmd-queue functions directly. Instead the hardware ++ * unit specific wrapper should be used. The wrappers perform ++ * unit specific validation and CSR writes to submit the ++ * commands. ++ * ++ * Even though most software will never directly interact with ++ * cvmx-cmd-queue, knowledge of its internal working can help ++ * in diagnosing performance problems and help with debugging. ++ * ++ * Command queue pointers are stored in a global named block ++ * called "cvmx_cmd_queues". Except for the PKO queues, each ++ * hardware queue is stored in its own cache line to reduce SMP ++ * contention on spin locks. The PKO queues are stored such that ++ * every 16th queue is next to each other in memory. This scheme ++ * allows for queues being in separate cache lines when there ++ * are low number of queues per port. With 16 queues per port, ++ * the first queue for each port is in the same cache area. The ++ * second queues for each port are in another area, etc. This ++ * allows software to implement very efficient lockless PKO with ++ * 16 queues per port using a minimum of cache lines per core. ++ * All queues for a given core will be isolated in the same ++ * cache area. ++ * ++ * In addition to the memory pointer layout, cvmx-cmd-queue ++ * provides an optimized fair ll/sc locking mechanism for the ++ * queues. The lock uses a "ticket / now serving" model to ++ * maintain fair order on contended locks. In addition, it uses ++ * predicted locking time to limit cache contention. When a core ++ * know it must wait in line for a lock, it spins on the ++ * internal cycle counter to completely eliminate any causes of ++ * bus traffic. ++ * ++ */ ++ ++#ifndef __CVMX_CMD_QUEUE_H__ ++#define __CVMX_CMD_QUEUE_H__ ++ ++#include ++ ++#include "cvmx-fpa.h" ++/** ++ * By default we disable the max depth support. Most programs ++ * don't use it and it slows down the command queue processing ++ * significantly. ++ */ ++#ifndef CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH ++#define CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH 0 ++#endif ++ ++/** ++ * Enumeration representing all hardware blocks that use command ++ * queues. Each hardware block has up to 65536 sub identifiers for ++ * multiple command queues. Not all chips support all hardware ++ * units. ++ */ ++typedef enum { ++ CVMX_CMD_QUEUE_PKO_BASE = 0x00000, ++ ++#define CVMX_CMD_QUEUE_PKO(queue) \ ++ ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_PKO_BASE + (0xffff&(queue)))) ++ ++ CVMX_CMD_QUEUE_ZIP = 0x10000, ++ CVMX_CMD_QUEUE_DFA = 0x20000, ++ CVMX_CMD_QUEUE_RAID = 0x30000, ++ CVMX_CMD_QUEUE_DMA_BASE = 0x40000, ++ ++#define CVMX_CMD_QUEUE_DMA(queue) \ ++ ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_DMA_BASE + (0xffff&(queue)))) ++ ++ CVMX_CMD_QUEUE_END = 0x50000, ++} cvmx_cmd_queue_id_t; ++ ++/** ++ * Command write operations can fail if the comamnd queue needs ++ * a new buffer and the associated FPA pool is empty. It can also ++ * fail if the number of queued command words reaches the maximum ++ * set at initialization. ++ */ ++typedef enum { ++ CVMX_CMD_QUEUE_SUCCESS = 0, ++ CVMX_CMD_QUEUE_NO_MEMORY = -1, ++ CVMX_CMD_QUEUE_FULL = -2, ++ CVMX_CMD_QUEUE_INVALID_PARAM = -3, ++ CVMX_CMD_QUEUE_ALREADY_SETUP = -4, ++} cvmx_cmd_queue_result_t; ++ ++typedef struct { ++ /* You have lock when this is your ticket */ ++ uint8_t now_serving; ++ uint64_t unused1:24; ++ /* Maximum outstanding command words */ ++ uint32_t max_depth; ++ /* FPA pool buffers come from */ ++ uint64_t fpa_pool:3; ++ /* Top of command buffer pointer shifted 7 */ ++ uint64_t base_ptr_div128:29; ++ uint64_t unused2:6; ++ /* FPA buffer size in 64bit words minus 1 */ ++ uint64_t pool_size_m1:13; ++ /* Number of comamnds already used in buffer */ ++ uint64_t index:13; ++} __cvmx_cmd_queue_state_t; ++ ++/** ++ * This structure contains the global state of all comamnd queues. ++ * It is stored in a bootmem named block and shared by all ++ * applications running on Octeon. Tickets are stored in a differnet ++ * cahce line that queue information to reduce the contention on the ++ * ll/sc used to get a ticket. If this is not the case, the update ++ * of queue state causes the ll/sc to fail quite often. ++ */ ++typedef struct { ++ uint64_t ticket[(CVMX_CMD_QUEUE_END >> 16) * 256]; ++ __cvmx_cmd_queue_state_t state[(CVMX_CMD_QUEUE_END >> 16) * 256]; ++} __cvmx_cmd_queue_all_state_t; ++ ++/** ++ * Initialize a command queue for use. The initial FPA buffer is ++ * allocated and the hardware unit is configured to point to the ++ * new command queue. ++ * ++ * @queue_id: Hardware command queue to initialize. ++ * @max_depth: Maximum outstanding commands that can be queued. ++ * @fpa_pool: FPA pool the command queues should come from. ++ * @pool_size: Size of each buffer in the FPA pool (bytes) ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id, ++ int max_depth, int fpa_pool, ++ int pool_size); ++ ++/** ++ * Shutdown a queue a free it's command buffers to the FPA. The ++ * hardware connected to the queue must be stopped before this ++ * function is called. ++ * ++ * @queue_id: Queue to shutdown ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id); ++ ++/** ++ * Return the number of command words pending in the queue. This ++ * function may be relatively slow for some hardware units. ++ * ++ * @queue_id: Hardware command queue to query ++ * ++ * Returns Number of outstanding commands ++ */ ++int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id); ++ ++/** ++ * Return the command buffer to be written to. The purpose of this ++ * function is to allow CVMX routine access t othe low level buffer ++ * for initial hardware setup. User applications should not call this ++ * function directly. ++ * ++ * @queue_id: Command queue to query ++ * ++ * Returns Command buffer or NULL on failure ++ */ ++void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id); ++ ++/** ++ * Get the index into the state arrays for the supplied queue id. ++ * ++ * @queue_id: Queue ID to get an index for ++ * ++ * Returns Index into the state arrays ++ */ ++static inline int __cvmx_cmd_queue_get_index(cvmx_cmd_queue_id_t queue_id) ++{ ++ /* ++ * Warning: This code currently only works with devices that ++ * have 256 queues or less. Devices with more than 16 queues ++ * are layed out in memory to allow cores quick access to ++ * every 16th queue. This reduces cache thrashing when you are ++ * running 16 queues per port to support lockless operation. ++ */ ++ int unit = queue_id >> 16; ++ int q = (queue_id >> 4) & 0xf; ++ int core = queue_id & 0xf; ++ return unit * 256 + core * 16 + q; ++} ++ ++/** ++ * Lock the supplied queue so nobody else is updating it at the same ++ * time as us. ++ * ++ * @queue_id: Queue ID to lock ++ * @qptr: Pointer to the queue's global state ++ */ ++static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id, ++ __cvmx_cmd_queue_state_t *qptr) ++{ ++ extern __cvmx_cmd_queue_all_state_t ++ *__cvmx_cmd_queue_state_ptr; ++ int tmp; ++ int my_ticket; ++ prefetch(qptr); ++ asm volatile ( ++ ".set push\n" ++ ".set noreorder\n" ++ "1:\n" ++ /* Atomic add one to ticket_ptr */ ++ "ll %[my_ticket], %[ticket_ptr]\n" ++ /* and store the original value */ ++ "li %[ticket], 1\n" ++ /* in my_ticket */ ++ "baddu %[ticket], %[my_ticket]\n" ++ "sc %[ticket], %[ticket_ptr]\n" ++ "beqz %[ticket], 1b\n" ++ " nop\n" ++ /* Load the current now_serving ticket */ ++ "lbu %[ticket], %[now_serving]\n" ++ "2:\n" ++ /* Jump out if now_serving == my_ticket */ ++ "beq %[ticket], %[my_ticket], 4f\n" ++ /* Find out how many tickets are in front of me */ ++ " subu %[ticket], %[my_ticket], %[ticket]\n" ++ /* Use tickets in front of me minus one to delay */ ++ "subu %[ticket], 1\n" ++ /* Delay will be ((tickets in front)-1)*32 loops */ ++ "cins %[ticket], %[ticket], 5, 7\n" ++ "3:\n" ++ /* Loop here until our ticket might be up */ ++ "bnez %[ticket], 3b\n" ++ " subu %[ticket], 1\n" ++ /* Jump back up to check out ticket again */ ++ "b 2b\n" ++ /* Load the current now_serving ticket */ ++ " lbu %[ticket], %[now_serving]\n" ++ "4:\n" ++ ".set pop\n" : ++ [ticket_ptr] "=m"(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]), ++ [now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp), ++ [my_ticket] "=r"(my_ticket) ++ ); ++} ++ ++/** ++ * Unlock the queue, flushing all writes. ++ * ++ * @qptr: Queue to unlock ++ */ ++static inline void __cvmx_cmd_queue_unlock(__cvmx_cmd_queue_state_t *qptr) ++{ ++ qptr->now_serving++; ++ CVMX_SYNCWS; ++} ++ ++/** ++ * Get the queue state structure for the given queue id ++ * ++ * @queue_id: Queue id to get ++ * ++ * Returns Queue structure or NULL on failure ++ */ ++static inline __cvmx_cmd_queue_state_t ++ *__cvmx_cmd_queue_get_state(cvmx_cmd_queue_id_t queue_id) ++{ ++ extern __cvmx_cmd_queue_all_state_t ++ *__cvmx_cmd_queue_state_ptr; ++ return &__cvmx_cmd_queue_state_ptr-> ++ state[__cvmx_cmd_queue_get_index(queue_id)]; ++} ++ ++/** ++ * Write an arbitrary number of command words to a command queue. ++ * This is a generic function; the fixed number of comamnd word ++ * functions yield higher performance. ++ * ++ * @queue_id: Hardware command queue to write to ++ * @use_locking: ++ * Use internal locking to ensure exclusive access for queue ++ * updates. If you don't use this locking you must ensure ++ * exclusivity some other way. Locking is strongly recommended. ++ * @cmd_count: Number of command words to write ++ * @cmds: Array of comamnds to write ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write(cvmx_cmd_queue_id_t ++ queue_id, ++ int use_locking, ++ int cmd_count, ++ uint64_t *cmds) ++{ ++ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); ++ ++ /* Make sure nobody else is updating the same queue */ ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_lock(queue_id, qptr); ++ ++ /* ++ * If a max queue length was specified then make sure we don't ++ * exceed it. If any part of the command would be below the ++ * limit we allow it. ++ */ ++ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { ++ if (unlikely ++ (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_FULL; ++ } ++ } ++ ++ /* ++ * Normally there is plenty of room in the current buffer for ++ * the command. ++ */ ++ if (likely(qptr->index + cmd_count < qptr->pool_size_m1)) { ++ uint64_t *ptr = ++ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> ++ base_ptr_div128 << 7); ++ ptr += qptr->index; ++ qptr->index += cmd_count; ++ while (cmd_count--) ++ *ptr++ = *cmds++; ++ } else { ++ uint64_t *ptr; ++ int count; ++ /* ++ * We need a new comamnd buffer. Fail if there isn't ++ * one available. ++ */ ++ uint64_t *new_buffer = ++ (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); ++ if (unlikely(new_buffer == NULL)) { ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_NO_MEMORY; ++ } ++ ptr = ++ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> ++ base_ptr_div128 << 7); ++ /* ++ * Figure out how many command words will fit in this ++ * buffer. One location will be needed for the next ++ * buffer pointer. ++ */ ++ count = qptr->pool_size_m1 - qptr->index; ++ ptr += qptr->index; ++ cmd_count -= count; ++ while (count--) ++ *ptr++ = *cmds++; ++ *ptr = cvmx_ptr_to_phys(new_buffer); ++ /* ++ * The current buffer is full and has a link to the ++ * next buffer. Time to write the rest of the commands ++ * into the new buffer. ++ */ ++ qptr->base_ptr_div128 = *ptr >> 7; ++ qptr->index = cmd_count; ++ ptr = new_buffer; ++ while (cmd_count--) ++ *ptr++ = *cmds++; ++ } ++ ++ /* All updates are complete. Release the lock and return */ ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_SUCCESS; ++} ++ ++/** ++ * Simple function to write two command words to a command ++ * queue. ++ * ++ * @queue_id: Hardware command queue to write to ++ * @use_locking: ++ * Use internal locking to ensure exclusive access for queue ++ * updates. If you don't use this locking you must ensure ++ * exclusivity some other way. Locking is strongly recommended. ++ * @cmd1: Command ++ * @cmd2: Command ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write2(cvmx_cmd_queue_id_t ++ queue_id, ++ int use_locking, ++ uint64_t cmd1, ++ uint64_t cmd2) ++{ ++ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); ++ ++ /* Make sure nobody else is updating the same queue */ ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_lock(queue_id, qptr); ++ ++ /* ++ * If a max queue length was specified then make sure we don't ++ * exceed it. If any part of the command would be below the ++ * limit we allow it. ++ */ ++ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { ++ if (unlikely ++ (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_FULL; ++ } ++ } ++ ++ /* ++ * Normally there is plenty of room in the current buffer for ++ * the command. ++ */ ++ if (likely(qptr->index + 2 < qptr->pool_size_m1)) { ++ uint64_t *ptr = ++ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> ++ base_ptr_div128 << 7); ++ ptr += qptr->index; ++ qptr->index += 2; ++ ptr[0] = cmd1; ++ ptr[1] = cmd2; ++ } else { ++ uint64_t *ptr; ++ /* ++ * Figure out how many command words will fit in this ++ * buffer. One location will be needed for the next ++ * buffer pointer. ++ */ ++ int count = qptr->pool_size_m1 - qptr->index; ++ /* ++ * We need a new comamnd buffer. Fail if there isn't ++ * one available. ++ */ ++ uint64_t *new_buffer = ++ (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); ++ if (unlikely(new_buffer == NULL)) { ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_NO_MEMORY; ++ } ++ count--; ++ ptr = ++ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> ++ base_ptr_div128 << 7); ++ ptr += qptr->index; ++ *ptr++ = cmd1; ++ if (likely(count)) ++ *ptr++ = cmd2; ++ *ptr = cvmx_ptr_to_phys(new_buffer); ++ /* ++ * The current buffer is full and has a link to the ++ * next buffer. Time to write the rest of the commands ++ * into the new buffer. ++ */ ++ qptr->base_ptr_div128 = *ptr >> 7; ++ qptr->index = 0; ++ if (unlikely(count == 0)) { ++ qptr->index = 1; ++ new_buffer[0] = cmd2; ++ } ++ } ++ ++ /* All updates are complete. Release the lock and return */ ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_SUCCESS; ++} ++ ++/** ++ * Simple function to write three command words to a command ++ * queue. ++ * ++ * @queue_id: Hardware command queue to write to ++ * @use_locking: ++ * Use internal locking to ensure exclusive access for queue ++ * updates. If you don't use this locking you must ensure ++ * exclusivity some other way. Locking is strongly recommended. ++ * @cmd1: Command ++ * @cmd2: Command ++ * @cmd3: Command ++ * ++ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code ++ */ ++static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write3(cvmx_cmd_queue_id_t ++ queue_id, ++ int use_locking, ++ uint64_t cmd1, ++ uint64_t cmd2, ++ uint64_t cmd3) ++{ ++ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); ++ ++ /* Make sure nobody else is updating the same queue */ ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_lock(queue_id, qptr); ++ ++ /* ++ * If a max queue length was specified then make sure we don't ++ * exceed it. If any part of the command would be below the ++ * limit we allow it. ++ */ ++ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { ++ if (unlikely ++ (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_FULL; ++ } ++ } ++ ++ /* ++ * Normally there is plenty of room in the current buffer for ++ * the command. ++ */ ++ if (likely(qptr->index + 3 < qptr->pool_size_m1)) { ++ uint64_t *ptr = ++ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> ++ base_ptr_div128 << 7); ++ ptr += qptr->index; ++ qptr->index += 3; ++ ptr[0] = cmd1; ++ ptr[1] = cmd2; ++ ptr[2] = cmd3; ++ } else { ++ uint64_t *ptr; ++ /* ++ * Figure out how many command words will fit in this ++ * buffer. One location will be needed for the next ++ * buffer pointer ++ */ ++ int count = qptr->pool_size_m1 - qptr->index; ++ /* ++ * We need a new comamnd buffer. Fail if there isn't ++ * one available ++ */ ++ uint64_t *new_buffer = ++ (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); ++ if (unlikely(new_buffer == NULL)) { ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_NO_MEMORY; ++ } ++ count--; ++ ptr = ++ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> ++ base_ptr_div128 << 7); ++ ptr += qptr->index; ++ *ptr++ = cmd1; ++ if (count) { ++ *ptr++ = cmd2; ++ if (count > 1) ++ *ptr++ = cmd3; ++ } ++ *ptr = cvmx_ptr_to_phys(new_buffer); ++ /* ++ * The current buffer is full and has a link to the ++ * next buffer. Time to write the rest of the commands ++ * into the new buffer. ++ */ ++ qptr->base_ptr_div128 = *ptr >> 7; ++ qptr->index = 0; ++ ptr = new_buffer; ++ if (count == 0) { ++ *ptr++ = cmd2; ++ qptr->index++; ++ } ++ if (count < 2) { ++ *ptr++ = cmd3; ++ qptr->index++; ++ } ++ } ++ ++ /* All updates are complete. Release the lock and return */ ++ if (likely(use_locking)) ++ __cvmx_cmd_queue_unlock(qptr); ++ return CVMX_CMD_QUEUE_SUCCESS; ++} ++ ++#endif /* __CVMX_CMD_QUEUE_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-config.h +@@ -0,0 +1,169 @@ ++#ifndef __CVMX_CONFIG_H__ ++#define __CVMX_CONFIG_H__ ++ ++/************************* Config Specific Defines ************************/ ++#define CVMX_LLM_NUM_PORTS 1 ++#define CVMX_NULL_POINTER_PROTECT 1 ++#define CVMX_ENABLE_DEBUG_PRINTS 1 ++/* PKO queues per port for interface 0 (ports 0-15) */ ++#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 1 ++/* PKO queues per port for interface 1 (ports 16-31) */ ++#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 1 ++/* Limit on the number of PKO ports enabled for interface 0 */ ++#define CVMX_PKO_MAX_PORTS_INTERFACE0 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 ++/* Limit on the number of PKO ports enabled for interface 1 */ ++#define CVMX_PKO_MAX_PORTS_INTERFACE1 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 ++/* PKO queues per port for PCI (ports 32-35) */ ++#define CVMX_PKO_QUEUES_PER_PORT_PCI 1 ++/* PKO queues per port for Loop devices (ports 36-39) */ ++#define CVMX_PKO_QUEUES_PER_PORT_LOOP 1 ++ ++/************************* FPA allocation *********************************/ ++/* Pool sizes in bytes, must be multiple of a cache line */ ++#define CVMX_FPA_POOL_0_SIZE (16 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_1_SIZE (1 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_2_SIZE (8 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_3_SIZE (0 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_4_SIZE (0 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_5_SIZE (0 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_6_SIZE (0 * CVMX_CACHE_LINE_SIZE) ++#define CVMX_FPA_POOL_7_SIZE (0 * CVMX_CACHE_LINE_SIZE) ++ ++/* Pools in use */ ++/* Packet buffers */ ++#define CVMX_FPA_PACKET_POOL (0) ++#define CVMX_FPA_PACKET_POOL_SIZE CVMX_FPA_POOL_0_SIZE ++/* Work queue entrys */ ++#define CVMX_FPA_WQE_POOL (1) ++#define CVMX_FPA_WQE_POOL_SIZE CVMX_FPA_POOL_1_SIZE ++/* PKO queue command buffers */ ++#define CVMX_FPA_OUTPUT_BUFFER_POOL (2) ++#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE CVMX_FPA_POOL_2_SIZE ++ ++/************************* FAU allocation ********************************/ ++/* The fetch and add registers are allocated here. They are arranged ++ * in order of descending size so that all alignment constraints are ++ * automatically met. The enums are linked so that the following enum ++ * continues allocating where the previous one left off, so the ++ * numbering within each enum always starts with zero. The macros ++ * take care of the address increment size, so the values entered ++ * always increase by 1. FAU registers are accessed with byte ++ * addresses. ++ */ ++ ++#define CVMX_FAU_REG_64_ADDR(x) ((x << 3) + CVMX_FAU_REG_64_START) ++typedef enum { ++ CVMX_FAU_REG_64_START = 0, ++ CVMX_FAU_REG_64_END = CVMX_FAU_REG_64_ADDR(0), ++} cvmx_fau_reg_64_t; ++ ++#define CVMX_FAU_REG_32_ADDR(x) ((x << 2) + CVMX_FAU_REG_32_START) ++typedef enum { ++ CVMX_FAU_REG_32_START = CVMX_FAU_REG_64_END, ++ CVMX_FAU_REG_32_END = CVMX_FAU_REG_32_ADDR(0), ++} cvmx_fau_reg_32_t; ++ ++#define CVMX_FAU_REG_16_ADDR(x) ((x << 1) + CVMX_FAU_REG_16_START) ++typedef enum { ++ CVMX_FAU_REG_16_START = CVMX_FAU_REG_32_END, ++ CVMX_FAU_REG_16_END = CVMX_FAU_REG_16_ADDR(0), ++} cvmx_fau_reg_16_t; ++ ++#define CVMX_FAU_REG_8_ADDR(x) ((x) + CVMX_FAU_REG_8_START) ++typedef enum { ++ CVMX_FAU_REG_8_START = CVMX_FAU_REG_16_END, ++ CVMX_FAU_REG_8_END = CVMX_FAU_REG_8_ADDR(0), ++} cvmx_fau_reg_8_t; ++ ++/* ++ * The name CVMX_FAU_REG_AVAIL_BASE is provided to indicate the first ++ * available FAU address that is not allocated in cvmx-config.h. This ++ * is 64 bit aligned. ++ */ ++#define CVMX_FAU_REG_AVAIL_BASE ((CVMX_FAU_REG_8_END + 0x7) & (~0x7ULL)) ++#define CVMX_FAU_REG_END (2048) ++ ++/********************** scratch memory allocation *************************/ ++/* Scratchpad memory allocation. Note that these are byte memory ++ * addresses. Some uses of scratchpad (IOBDMA for example) require ++ * the use of 8-byte aligned addresses, so proper alignment needs to ++ * be taken into account. ++ */ ++/* Generic scratch iobdma area */ ++#define CVMX_SCR_SCRATCH (0) ++/* First location available after cvmx-config.h allocated region. */ ++#define CVMX_SCR_REG_AVAIL_BASE (8) ++ ++/* ++ * CVMX_HELPER_FIRST_MBUFF_SKIP is the number of bytes to reserve ++ * before the beginning of the packet. If necessary, override the ++ * default here. See the IPD section of the hardware manual for MBUFF ++ * SKIP details. ++ */ ++#define CVMX_HELPER_FIRST_MBUFF_SKIP 184 ++ ++/* ++ * CVMX_HELPER_NOT_FIRST_MBUFF_SKIP is the number of bytes to reserve ++ * in each chained packet element. If necessary, override the default ++ * here. ++ */ ++#define CVMX_HELPER_NOT_FIRST_MBUFF_SKIP 0 ++ ++/* ++ * CVMX_HELPER_ENABLE_BACK_PRESSURE controls whether back pressure is ++ * enabled for all input ports. This controls if IPD sends ++ * backpressure to all ports if Octeon's FPA pools don't have enough ++ * packet or work queue entries. Even when this is off, it is still ++ * possible to get backpressure from individual hardware ports. When ++ * configuring backpressure, also check ++ * CVMX_HELPER_DISABLE_*_BACKPRESSURE below. If necessary, override ++ * the default here. ++ */ ++#define CVMX_HELPER_ENABLE_BACK_PRESSURE 1 ++ ++/* ++ * CVMX_HELPER_ENABLE_IPD controls if the IPD is enabled in the helper ++ * function. Once it is enabled the hardware starts accepting ++ * packets. You might want to skip the IPD enable if configuration ++ * changes are need from the default helper setup. If necessary, ++ * override the default here. ++ */ ++#define CVMX_HELPER_ENABLE_IPD 0 ++ ++/* ++ * CVMX_HELPER_INPUT_TAG_TYPE selects the type of tag that the IPD assigns ++ * to incoming packets. ++ */ ++#define CVMX_HELPER_INPUT_TAG_TYPE CVMX_POW_TAG_TYPE_ORDERED ++ ++#define CVMX_ENABLE_PARAMETER_CHECKING 0 ++ ++/* ++ * The following select which fields are used by the PIP to generate ++ * the tag on INPUT ++ * 0: don't include ++ * 1: include ++ */ ++#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP 0 ++#define CVMX_HELPER_INPUT_TAG_IPV6_DST_IP 0 ++#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT 0 ++#define CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT 0 ++#define CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER 0 ++#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP 0 ++#define CVMX_HELPER_INPUT_TAG_IPV4_DST_IP 0 ++#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT 0 ++#define CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT 0 ++#define CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL 0 ++#define CVMX_HELPER_INPUT_TAG_INPUT_PORT 1 ++ ++/* Select skip mode for input ports */ ++#define CVMX_HELPER_INPUT_PORT_SKIP_MODE CVMX_PIP_PORT_CFG_MODE_SKIPL2 ++ ++/* ++ * Force backpressure to be disabled. This overrides all other ++ * backpressure configuration. ++ */ ++#define CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 0 ++ ++#endif /* __CVMX_CONFIG_H__ */ ++ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-dbg-defs.h +@@ -0,0 +1,72 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_DBG_DEFS_H__ ++#define __CVMX_DBG_DEFS_H__ ++ ++#define CVMX_DBG_DATA \ ++ CVMX_ADD_IO_SEG(0x00011F00000001E8ull) ++ ++union cvmx_dbg_data { ++ uint64_t u64; ++ struct cvmx_dbg_data_s { ++ uint64_t reserved_23_63:41; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } s; ++ struct cvmx_dbg_data_cn30xx { ++ uint64_t reserved_31_63:33; ++ uint64_t pll_mul:3; ++ uint64_t reserved_23_27:5; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } cn30xx; ++ struct cvmx_dbg_data_cn30xx cn31xx; ++ struct cvmx_dbg_data_cn38xx { ++ uint64_t reserved_29_63:35; ++ uint64_t d_mul:4; ++ uint64_t dclk_mul2:1; ++ uint64_t cclk_div2:1; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } cn38xx; ++ struct cvmx_dbg_data_cn38xx cn38xxp2; ++ struct cvmx_dbg_data_cn30xx cn50xx; ++ struct cvmx_dbg_data_cn58xx { ++ uint64_t reserved_29_63:35; ++ uint64_t rem:6; ++ uint64_t c_mul:5; ++ uint64_t dsel_ext:1; ++ uint64_t data:17; ++ } cn58xx; ++ struct cvmx_dbg_data_cn58xx cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-fau.h +@@ -0,0 +1,597 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Interface to the hardware Fetch and Add Unit. ++ */ ++ ++#ifndef __CVMX_FAU_H__ ++#define __CVMX_FAU_H__ ++ ++/* ++ * Octeon Fetch and Add Unit (FAU) ++ */ ++ ++#define CVMX_FAU_LOAD_IO_ADDRESS cvmx_build_io_address(0x1e, 0) ++#define CVMX_FAU_BITS_SCRADDR 63, 56 ++#define CVMX_FAU_BITS_LEN 55, 48 ++#define CVMX_FAU_BITS_INEVAL 35, 14 ++#define CVMX_FAU_BITS_TAGWAIT 13, 13 ++#define CVMX_FAU_BITS_NOADD 13, 13 ++#define CVMX_FAU_BITS_SIZE 12, 11 ++#define CVMX_FAU_BITS_REGISTER 10, 0 ++ ++typedef enum { ++ CVMX_FAU_OP_SIZE_8 = 0, ++ CVMX_FAU_OP_SIZE_16 = 1, ++ CVMX_FAU_OP_SIZE_32 = 2, ++ CVMX_FAU_OP_SIZE_64 = 3 ++} cvmx_fau_op_size_t; ++ ++/** ++ * Tagwait return definition. If a timeout occurs, the error ++ * bit will be set. Otherwise the value of the register before ++ * the update will be returned. ++ */ ++typedef struct { ++ uint64_t error:1; ++ int64_t value:63; ++} cvmx_fau_tagwait64_t; ++ ++/** ++ * Tagwait return definition. If a timeout occurs, the error ++ * bit will be set. Otherwise the value of the register before ++ * the update will be returned. ++ */ ++typedef struct { ++ uint64_t error:1; ++ int32_t value:31; ++} cvmx_fau_tagwait32_t; ++ ++/** ++ * Tagwait return definition. If a timeout occurs, the error ++ * bit will be set. Otherwise the value of the register before ++ * the update will be returned. ++ */ ++typedef struct { ++ uint64_t error:1; ++ int16_t value:15; ++} cvmx_fau_tagwait16_t; ++ ++/** ++ * Tagwait return definition. If a timeout occurs, the error ++ * bit will be set. Otherwise the value of the register before ++ * the update will be returned. ++ */ ++typedef struct { ++ uint64_t error:1; ++ int8_t value:7; ++} cvmx_fau_tagwait8_t; ++ ++/** ++ * Asynchronous tagwait return definition. If a timeout occurs, ++ * the error bit will be set. Otherwise the value of the ++ * register before the update will be returned. ++ */ ++typedef union { ++ uint64_t u64; ++ struct { ++ uint64_t invalid:1; ++ uint64_t data:63; /* unpredictable if invalid is set */ ++ } s; ++} cvmx_fau_async_tagwait_result_t; ++ ++/** ++ * Builds a store I/O address for writing to the FAU ++ * ++ * @noadd: 0 = Store value is atomically added to the current value ++ * 1 = Store value is atomically written over the current value ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * - Step by 4 for 32 bit access. ++ * - Step by 8 for 64 bit access. ++ * Returns Address to store for atomic update ++ */ ++static inline uint64_t __cvmx_fau_store_address(uint64_t noadd, uint64_t reg) ++{ ++ return CVMX_ADD_IO_SEG(CVMX_FAU_LOAD_IO_ADDRESS) | ++ cvmx_build_bits(CVMX_FAU_BITS_NOADD, noadd) | ++ cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg); ++} ++ ++/** ++ * Builds a I/O address for accessing the FAU ++ * ++ * @tagwait: Should the atomic add wait for the current tag switch ++ * operation to complete. ++ * - 0 = Don't wait ++ * - 1 = Wait for tag switch to complete ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * - Step by 4 for 32 bit access. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to add. ++ * Note: When performing 32 and 64 bit access, only the low ++ * 22 bits are available. ++ * Returns Address to read from for atomic update ++ */ ++static inline uint64_t __cvmx_fau_atomic_address(uint64_t tagwait, uint64_t reg, ++ int64_t value) ++{ ++ return CVMX_ADD_IO_SEG(CVMX_FAU_LOAD_IO_ADDRESS) | ++ cvmx_build_bits(CVMX_FAU_BITS_INEVAL, value) | ++ cvmx_build_bits(CVMX_FAU_BITS_TAGWAIT, tagwait) | ++ cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg); ++} ++ ++/** ++ * Perform an atomic 64 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns Value of the register before the update ++ */ ++static inline int64_t cvmx_fau_fetch_and_add64(cvmx_fau_reg_64_t reg, ++ int64_t value) ++{ ++ return cvmx_read64_int64(__cvmx_fau_atomic_address(0, reg, value)); ++} ++ ++/** ++ * Perform an atomic 32 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 4 for 32 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns Value of the register before the update ++ */ ++static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg, ++ int32_t value) ++{ ++ return cvmx_read64_int32(__cvmx_fau_atomic_address(0, reg, value)); ++} ++ ++/** ++ * Perform an atomic 16 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * @value: Signed value to add. ++ * Returns Value of the register before the update ++ */ ++static inline int16_t cvmx_fau_fetch_and_add16(cvmx_fau_reg_16_t reg, ++ int16_t value) ++{ ++ return cvmx_read64_int16(__cvmx_fau_atomic_address(0, reg, value)); ++} ++ ++/** ++ * Perform an atomic 8 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * @value: Signed value to add. ++ * Returns Value of the register before the update ++ */ ++static inline int8_t cvmx_fau_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value) ++{ ++ return cvmx_read64_int8(__cvmx_fau_atomic_address(0, reg, value)); ++} ++ ++/** ++ * Perform an atomic 64 bit add after the current tag switch ++ * completes ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns If a timeout occurs, the error bit will be set. Otherwise ++ * the value of the register before the update will be ++ * returned ++ */ ++static inline cvmx_fau_tagwait64_t ++cvmx_fau_tagwait_fetch_and_add64(cvmx_fau_reg_64_t reg, int64_t value) ++{ ++ union { ++ uint64_t i64; ++ cvmx_fau_tagwait64_t t; ++ } result; ++ result.i64 = ++ cvmx_read64_int64(__cvmx_fau_atomic_address(1, reg, value)); ++ return result.t; ++} ++ ++/** ++ * Perform an atomic 32 bit add after the current tag switch ++ * completes ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 4 for 32 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns If a timeout occurs, the error bit will be set. Otherwise ++ * the value of the register before the update will be ++ * returned ++ */ ++static inline cvmx_fau_tagwait32_t ++cvmx_fau_tagwait_fetch_and_add32(cvmx_fau_reg_32_t reg, int32_t value) ++{ ++ union { ++ uint64_t i32; ++ cvmx_fau_tagwait32_t t; ++ } result; ++ result.i32 = ++ cvmx_read64_int32(__cvmx_fau_atomic_address(1, reg, value)); ++ return result.t; ++} ++ ++/** ++ * Perform an atomic 16 bit add after the current tag switch ++ * completes ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * @value: Signed value to add. ++ * Returns If a timeout occurs, the error bit will be set. Otherwise ++ * the value of the register before the update will be ++ * returned ++ */ ++static inline cvmx_fau_tagwait16_t ++cvmx_fau_tagwait_fetch_and_add16(cvmx_fau_reg_16_t reg, int16_t value) ++{ ++ union { ++ uint64_t i16; ++ cvmx_fau_tagwait16_t t; ++ } result; ++ result.i16 = ++ cvmx_read64_int16(__cvmx_fau_atomic_address(1, reg, value)); ++ return result.t; ++} ++ ++/** ++ * Perform an atomic 8 bit add after the current tag switch ++ * completes ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * @value: Signed value to add. ++ * Returns If a timeout occurs, the error bit will be set. Otherwise ++ * the value of the register before the update will be ++ * returned ++ */ ++static inline cvmx_fau_tagwait8_t ++cvmx_fau_tagwait_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value) ++{ ++ union { ++ uint64_t i8; ++ cvmx_fau_tagwait8_t t; ++ } result; ++ result.i8 = cvmx_read64_int8(__cvmx_fau_atomic_address(1, reg, value)); ++ return result.t; ++} ++ ++/** ++ * Builds I/O data for async operations ++ * ++ * @scraddr: Scratch pad byte addres to write to. Must be 8 byte aligned ++ * @value: Signed value to add. ++ * Note: When performing 32 and 64 bit access, only the low ++ * 22 bits are available. ++ * @tagwait: Should the atomic add wait for the current tag switch ++ * operation to complete. ++ * - 0 = Don't wait ++ * - 1 = Wait for tag switch to complete ++ * @size: The size of the operation: ++ * - CVMX_FAU_OP_SIZE_8 (0) = 8 bits ++ * - CVMX_FAU_OP_SIZE_16 (1) = 16 bits ++ * - CVMX_FAU_OP_SIZE_32 (2) = 32 bits ++ * - CVMX_FAU_OP_SIZE_64 (3) = 64 bits ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * - Step by 4 for 32 bit access. ++ * - Step by 8 for 64 bit access. ++ * Returns Data to write using cvmx_send_single ++ */ ++static inline uint64_t __cvmx_fau_iobdma_data(uint64_t scraddr, int64_t value, ++ uint64_t tagwait, ++ cvmx_fau_op_size_t size, ++ uint64_t reg) ++{ ++ return CVMX_FAU_LOAD_IO_ADDRESS | ++ cvmx_build_bits(CVMX_FAU_BITS_SCRADDR, scraddr >> 3) | ++ cvmx_build_bits(CVMX_FAU_BITS_LEN, 1) | ++ cvmx_build_bits(CVMX_FAU_BITS_INEVAL, value) | ++ cvmx_build_bits(CVMX_FAU_BITS_TAGWAIT, tagwait) | ++ cvmx_build_bits(CVMX_FAU_BITS_SIZE, size) | ++ cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg); ++} ++ ++/** ++ * Perform an async atomic 64 bit add. The old value is ++ * placed in the scratch memory at byte address scraddr. ++ * ++ * @scraddr: Scratch memory byte address to put response in. ++ * Must be 8 byte aligned. ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_fetch_and_add64(uint64_t scraddr, ++ cvmx_fau_reg_64_t reg, ++ int64_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 0, CVMX_FAU_OP_SIZE_64, reg)); ++} ++ ++/** ++ * Perform an async atomic 32 bit add. The old value is ++ * placed in the scratch memory at byte address scraddr. ++ * ++ * @scraddr: Scratch memory byte address to put response in. ++ * Must be 8 byte aligned. ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 4 for 32 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr, ++ cvmx_fau_reg_32_t reg, ++ int32_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 0, CVMX_FAU_OP_SIZE_32, reg)); ++} ++ ++/** ++ * Perform an async atomic 16 bit add. The old value is ++ * placed in the scratch memory at byte address scraddr. ++ * ++ * @scraddr: Scratch memory byte address to put response in. ++ * Must be 8 byte aligned. ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * @value: Signed value to add. ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_fetch_and_add16(uint64_t scraddr, ++ cvmx_fau_reg_16_t reg, ++ int16_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 0, CVMX_FAU_OP_SIZE_16, reg)); ++} ++ ++/** ++ * Perform an async atomic 8 bit add. The old value is ++ * placed in the scratch memory at byte address scraddr. ++ * ++ * @scraddr: Scratch memory byte address to put response in. ++ * Must be 8 byte aligned. ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * @value: Signed value to add. ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_fetch_and_add8(uint64_t scraddr, ++ cvmx_fau_reg_8_t reg, ++ int8_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 0, CVMX_FAU_OP_SIZE_8, reg)); ++} ++ ++/** ++ * Perform an async atomic 64 bit add after the current tag ++ * switch completes. ++ * ++ * @scraddr: Scratch memory byte address to put response in. Must be ++ * 8 byte aligned. If a timeout occurs, the error bit (63) ++ * will be set. Otherwise the value of the register before ++ * the update will be returned ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_tagwait_fetch_and_add64(uint64_t scraddr, ++ cvmx_fau_reg_64_t reg, ++ int64_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 1, CVMX_FAU_OP_SIZE_64, reg)); ++} ++ ++/** ++ * Perform an async atomic 32 bit add after the current tag ++ * switch completes. ++ * ++ * @scraddr: Scratch memory byte address to put response in. Must be ++ * 8 byte aligned. If a timeout occurs, the error bit (63) ++ * will be set. Otherwise the value of the register before ++ * the update will be returned ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 4 for 32 bit access. ++ * @value: Signed value to add. ++ * Note: Only the low 22 bits are available. ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_tagwait_fetch_and_add32(uint64_t scraddr, ++ cvmx_fau_reg_32_t reg, ++ int32_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 1, CVMX_FAU_OP_SIZE_32, reg)); ++} ++ ++/** ++ * Perform an async atomic 16 bit add after the current tag ++ * switch completes. ++ * ++ * @scraddr: Scratch memory byte address to put response in. Must be ++ * 8 byte aligned. If a timeout occurs, the error bit (63) ++ * will be set. Otherwise the value of the register before ++ * the update will be returned ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * @value: Signed value to add. ++ * ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_tagwait_fetch_and_add16(uint64_t scraddr, ++ cvmx_fau_reg_16_t reg, ++ int16_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 1, CVMX_FAU_OP_SIZE_16, reg)); ++} ++ ++/** ++ * Perform an async atomic 8 bit add after the current tag ++ * switch completes. ++ * ++ * @scraddr: Scratch memory byte address to put response in. Must be ++ * 8 byte aligned. If a timeout occurs, the error bit (63) ++ * will be set. Otherwise the value of the register before ++ * the update will be returned ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * @value: Signed value to add. ++ * ++ * Returns Placed in the scratch pad register ++ */ ++static inline void cvmx_fau_async_tagwait_fetch_and_add8(uint64_t scraddr, ++ cvmx_fau_reg_8_t reg, ++ int8_t value) ++{ ++ cvmx_send_single(__cvmx_fau_iobdma_data ++ (scraddr, value, 1, CVMX_FAU_OP_SIZE_8, reg)); ++} ++ ++/** ++ * Perform an atomic 64 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to add. ++ */ ++static inline void cvmx_fau_atomic_add64(cvmx_fau_reg_64_t reg, int64_t value) ++{ ++ cvmx_write64_int64(__cvmx_fau_store_address(0, reg), value); ++} ++ ++/** ++ * Perform an atomic 32 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 4 for 32 bit access. ++ * @value: Signed value to add. ++ */ ++static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value) ++{ ++ cvmx_write64_int32(__cvmx_fau_store_address(0, reg), value); ++} ++ ++/** ++ * Perform an atomic 16 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * @value: Signed value to add. ++ */ ++static inline void cvmx_fau_atomic_add16(cvmx_fau_reg_16_t reg, int16_t value) ++{ ++ cvmx_write64_int16(__cvmx_fau_store_address(0, reg), value); ++} ++ ++/** ++ * Perform an atomic 8 bit add ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * @value: Signed value to add. ++ */ ++static inline void cvmx_fau_atomic_add8(cvmx_fau_reg_8_t reg, int8_t value) ++{ ++ cvmx_write64_int8(__cvmx_fau_store_address(0, reg), value); ++} ++ ++/** ++ * Perform an atomic 64 bit write ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 8 for 64 bit access. ++ * @value: Signed value to write. ++ */ ++static inline void cvmx_fau_atomic_write64(cvmx_fau_reg_64_t reg, int64_t value) ++{ ++ cvmx_write64_int64(__cvmx_fau_store_address(1, reg), value); ++} ++ ++/** ++ * Perform an atomic 32 bit write ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 4 for 32 bit access. ++ * @value: Signed value to write. ++ */ ++static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value) ++{ ++ cvmx_write64_int32(__cvmx_fau_store_address(1, reg), value); ++} ++ ++/** ++ * Perform an atomic 16 bit write ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * - Step by 2 for 16 bit access. ++ * @value: Signed value to write. ++ */ ++static inline void cvmx_fau_atomic_write16(cvmx_fau_reg_16_t reg, int16_t value) ++{ ++ cvmx_write64_int16(__cvmx_fau_store_address(1, reg), value); ++} ++ ++/** ++ * Perform an atomic 8 bit write ++ * ++ * @reg: FAU atomic register to access. 0 <= reg < 2048. ++ * @value: Signed value to write. ++ */ ++static inline void cvmx_fau_atomic_write8(cvmx_fau_reg_8_t reg, int8_t value) ++{ ++ cvmx_write64_int8(__cvmx_fau_store_address(1, reg), value); ++} ++ ++#endif /* __CVMX_FAU_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-fpa-defs.h +@@ -0,0 +1,403 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_FPA_DEFS_H__ ++#define __CVMX_FPA_DEFS_H__ ++ ++#define CVMX_FPA_BIST_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011800280000E8ull) ++#define CVMX_FPA_CTL_STATUS \ ++ CVMX_ADD_IO_SEG(0x0001180028000050ull) ++#define CVMX_FPA_FPF0_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000000ull) ++#define CVMX_FPA_FPF0_SIZE \ ++ CVMX_ADD_IO_SEG(0x0001180028000058ull) ++#define CVMX_FPA_FPF1_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000008ull) ++#define CVMX_FPA_FPF2_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000010ull) ++#define CVMX_FPA_FPF3_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000018ull) ++#define CVMX_FPA_FPF4_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000020ull) ++#define CVMX_FPA_FPF5_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000028ull) ++#define CVMX_FPA_FPF6_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000030ull) ++#define CVMX_FPA_FPF7_MARKS \ ++ CVMX_ADD_IO_SEG(0x0001180028000038ull) ++#define CVMX_FPA_FPFX_MARKS(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180028000008ull + (((offset) & 7) * 8) - 8 * 1) ++#define CVMX_FPA_FPFX_SIZE(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180028000060ull + (((offset) & 7) * 8) - 8 * 1) ++#define CVMX_FPA_INT_ENB \ ++ CVMX_ADD_IO_SEG(0x0001180028000048ull) ++#define CVMX_FPA_INT_SUM \ ++ CVMX_ADD_IO_SEG(0x0001180028000040ull) ++#define CVMX_FPA_QUE0_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x00011800280000F0ull) ++#define CVMX_FPA_QUE1_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x00011800280000F8ull) ++#define CVMX_FPA_QUE2_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x0001180028000100ull) ++#define CVMX_FPA_QUE3_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x0001180028000108ull) ++#define CVMX_FPA_QUE4_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x0001180028000110ull) ++#define CVMX_FPA_QUE5_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x0001180028000118ull) ++#define CVMX_FPA_QUE6_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x0001180028000120ull) ++#define CVMX_FPA_QUE7_PAGE_INDEX \ ++ CVMX_ADD_IO_SEG(0x0001180028000128ull) ++#define CVMX_FPA_QUEX_AVAILABLE(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180028000098ull + (((offset) & 7) * 8)) ++#define CVMX_FPA_QUEX_PAGE_INDEX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800280000F0ull + (((offset) & 7) * 8)) ++#define CVMX_FPA_QUE_ACT \ ++ CVMX_ADD_IO_SEG(0x0001180028000138ull) ++#define CVMX_FPA_QUE_EXP \ ++ CVMX_ADD_IO_SEG(0x0001180028000130ull) ++#define CVMX_FPA_WART_CTL \ ++ CVMX_ADD_IO_SEG(0x00011800280000D8ull) ++#define CVMX_FPA_WART_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011800280000E0ull) ++ ++union cvmx_fpa_bist_status { ++ uint64_t u64; ++ struct cvmx_fpa_bist_status_s { ++ uint64_t reserved_5_63:59; ++ uint64_t frd:1; ++ uint64_t fpf0:1; ++ uint64_t fpf1:1; ++ uint64_t ffr:1; ++ uint64_t fdr:1; ++ } s; ++ struct cvmx_fpa_bist_status_s cn30xx; ++ struct cvmx_fpa_bist_status_s cn31xx; ++ struct cvmx_fpa_bist_status_s cn38xx; ++ struct cvmx_fpa_bist_status_s cn38xxp2; ++ struct cvmx_fpa_bist_status_s cn50xx; ++ struct cvmx_fpa_bist_status_s cn52xx; ++ struct cvmx_fpa_bist_status_s cn52xxp1; ++ struct cvmx_fpa_bist_status_s cn56xx; ++ struct cvmx_fpa_bist_status_s cn56xxp1; ++ struct cvmx_fpa_bist_status_s cn58xx; ++ struct cvmx_fpa_bist_status_s cn58xxp1; ++}; ++ ++union cvmx_fpa_ctl_status { ++ uint64_t u64; ++ struct cvmx_fpa_ctl_status_s { ++ uint64_t reserved_18_63:46; ++ uint64_t reset:1; ++ uint64_t use_ldt:1; ++ uint64_t use_stt:1; ++ uint64_t enb:1; ++ uint64_t mem1_err:7; ++ uint64_t mem0_err:7; ++ } s; ++ struct cvmx_fpa_ctl_status_s cn30xx; ++ struct cvmx_fpa_ctl_status_s cn31xx; ++ struct cvmx_fpa_ctl_status_s cn38xx; ++ struct cvmx_fpa_ctl_status_s cn38xxp2; ++ struct cvmx_fpa_ctl_status_s cn50xx; ++ struct cvmx_fpa_ctl_status_s cn52xx; ++ struct cvmx_fpa_ctl_status_s cn52xxp1; ++ struct cvmx_fpa_ctl_status_s cn56xx; ++ struct cvmx_fpa_ctl_status_s cn56xxp1; ++ struct cvmx_fpa_ctl_status_s cn58xx; ++ struct cvmx_fpa_ctl_status_s cn58xxp1; ++}; ++ ++union cvmx_fpa_fpfx_marks { ++ uint64_t u64; ++ struct cvmx_fpa_fpfx_marks_s { ++ uint64_t reserved_22_63:42; ++ uint64_t fpf_wr:11; ++ uint64_t fpf_rd:11; ++ } s; ++ struct cvmx_fpa_fpfx_marks_s cn38xx; ++ struct cvmx_fpa_fpfx_marks_s cn38xxp2; ++ struct cvmx_fpa_fpfx_marks_s cn56xx; ++ struct cvmx_fpa_fpfx_marks_s cn56xxp1; ++ struct cvmx_fpa_fpfx_marks_s cn58xx; ++ struct cvmx_fpa_fpfx_marks_s cn58xxp1; ++}; ++ ++union cvmx_fpa_fpfx_size { ++ uint64_t u64; ++ struct cvmx_fpa_fpfx_size_s { ++ uint64_t reserved_11_63:53; ++ uint64_t fpf_siz:11; ++ } s; ++ struct cvmx_fpa_fpfx_size_s cn38xx; ++ struct cvmx_fpa_fpfx_size_s cn38xxp2; ++ struct cvmx_fpa_fpfx_size_s cn56xx; ++ struct cvmx_fpa_fpfx_size_s cn56xxp1; ++ struct cvmx_fpa_fpfx_size_s cn58xx; ++ struct cvmx_fpa_fpfx_size_s cn58xxp1; ++}; ++ ++union cvmx_fpa_fpf0_marks { ++ uint64_t u64; ++ struct cvmx_fpa_fpf0_marks_s { ++ uint64_t reserved_24_63:40; ++ uint64_t fpf_wr:12; ++ uint64_t fpf_rd:12; ++ } s; ++ struct cvmx_fpa_fpf0_marks_s cn38xx; ++ struct cvmx_fpa_fpf0_marks_s cn38xxp2; ++ struct cvmx_fpa_fpf0_marks_s cn56xx; ++ struct cvmx_fpa_fpf0_marks_s cn56xxp1; ++ struct cvmx_fpa_fpf0_marks_s cn58xx; ++ struct cvmx_fpa_fpf0_marks_s cn58xxp1; ++}; ++ ++union cvmx_fpa_fpf0_size { ++ uint64_t u64; ++ struct cvmx_fpa_fpf0_size_s { ++ uint64_t reserved_12_63:52; ++ uint64_t fpf_siz:12; ++ } s; ++ struct cvmx_fpa_fpf0_size_s cn38xx; ++ struct cvmx_fpa_fpf0_size_s cn38xxp2; ++ struct cvmx_fpa_fpf0_size_s cn56xx; ++ struct cvmx_fpa_fpf0_size_s cn56xxp1; ++ struct cvmx_fpa_fpf0_size_s cn58xx; ++ struct cvmx_fpa_fpf0_size_s cn58xxp1; ++}; ++ ++union cvmx_fpa_int_enb { ++ uint64_t u64; ++ struct cvmx_fpa_int_enb_s { ++ uint64_t reserved_28_63:36; ++ uint64_t q7_perr:1; ++ uint64_t q7_coff:1; ++ uint64_t q7_und:1; ++ uint64_t q6_perr:1; ++ uint64_t q6_coff:1; ++ uint64_t q6_und:1; ++ uint64_t q5_perr:1; ++ uint64_t q5_coff:1; ++ uint64_t q5_und:1; ++ uint64_t q4_perr:1; ++ uint64_t q4_coff:1; ++ uint64_t q4_und:1; ++ uint64_t q3_perr:1; ++ uint64_t q3_coff:1; ++ uint64_t q3_und:1; ++ uint64_t q2_perr:1; ++ uint64_t q2_coff:1; ++ uint64_t q2_und:1; ++ uint64_t q1_perr:1; ++ uint64_t q1_coff:1; ++ uint64_t q1_und:1; ++ uint64_t q0_perr:1; ++ uint64_t q0_coff:1; ++ uint64_t q0_und:1; ++ uint64_t fed1_dbe:1; ++ uint64_t fed1_sbe:1; ++ uint64_t fed0_dbe:1; ++ uint64_t fed0_sbe:1; ++ } s; ++ struct cvmx_fpa_int_enb_s cn30xx; ++ struct cvmx_fpa_int_enb_s cn31xx; ++ struct cvmx_fpa_int_enb_s cn38xx; ++ struct cvmx_fpa_int_enb_s cn38xxp2; ++ struct cvmx_fpa_int_enb_s cn50xx; ++ struct cvmx_fpa_int_enb_s cn52xx; ++ struct cvmx_fpa_int_enb_s cn52xxp1; ++ struct cvmx_fpa_int_enb_s cn56xx; ++ struct cvmx_fpa_int_enb_s cn56xxp1; ++ struct cvmx_fpa_int_enb_s cn58xx; ++ struct cvmx_fpa_int_enb_s cn58xxp1; ++}; ++ ++union cvmx_fpa_int_sum { ++ uint64_t u64; ++ struct cvmx_fpa_int_sum_s { ++ uint64_t reserved_28_63:36; ++ uint64_t q7_perr:1; ++ uint64_t q7_coff:1; ++ uint64_t q7_und:1; ++ uint64_t q6_perr:1; ++ uint64_t q6_coff:1; ++ uint64_t q6_und:1; ++ uint64_t q5_perr:1; ++ uint64_t q5_coff:1; ++ uint64_t q5_und:1; ++ uint64_t q4_perr:1; ++ uint64_t q4_coff:1; ++ uint64_t q4_und:1; ++ uint64_t q3_perr:1; ++ uint64_t q3_coff:1; ++ uint64_t q3_und:1; ++ uint64_t q2_perr:1; ++ uint64_t q2_coff:1; ++ uint64_t q2_und:1; ++ uint64_t q1_perr:1; ++ uint64_t q1_coff:1; ++ uint64_t q1_und:1; ++ uint64_t q0_perr:1; ++ uint64_t q0_coff:1; ++ uint64_t q0_und:1; ++ uint64_t fed1_dbe:1; ++ uint64_t fed1_sbe:1; ++ uint64_t fed0_dbe:1; ++ uint64_t fed0_sbe:1; ++ } s; ++ struct cvmx_fpa_int_sum_s cn30xx; ++ struct cvmx_fpa_int_sum_s cn31xx; ++ struct cvmx_fpa_int_sum_s cn38xx; ++ struct cvmx_fpa_int_sum_s cn38xxp2; ++ struct cvmx_fpa_int_sum_s cn50xx; ++ struct cvmx_fpa_int_sum_s cn52xx; ++ struct cvmx_fpa_int_sum_s cn52xxp1; ++ struct cvmx_fpa_int_sum_s cn56xx; ++ struct cvmx_fpa_int_sum_s cn56xxp1; ++ struct cvmx_fpa_int_sum_s cn58xx; ++ struct cvmx_fpa_int_sum_s cn58xxp1; ++}; ++ ++union cvmx_fpa_quex_available { ++ uint64_t u64; ++ struct cvmx_fpa_quex_available_s { ++ uint64_t reserved_29_63:35; ++ uint64_t que_siz:29; ++ } s; ++ struct cvmx_fpa_quex_available_s cn30xx; ++ struct cvmx_fpa_quex_available_s cn31xx; ++ struct cvmx_fpa_quex_available_s cn38xx; ++ struct cvmx_fpa_quex_available_s cn38xxp2; ++ struct cvmx_fpa_quex_available_s cn50xx; ++ struct cvmx_fpa_quex_available_s cn52xx; ++ struct cvmx_fpa_quex_available_s cn52xxp1; ++ struct cvmx_fpa_quex_available_s cn56xx; ++ struct cvmx_fpa_quex_available_s cn56xxp1; ++ struct cvmx_fpa_quex_available_s cn58xx; ++ struct cvmx_fpa_quex_available_s cn58xxp1; ++}; ++ ++union cvmx_fpa_quex_page_index { ++ uint64_t u64; ++ struct cvmx_fpa_quex_page_index_s { ++ uint64_t reserved_25_63:39; ++ uint64_t pg_num:25; ++ } s; ++ struct cvmx_fpa_quex_page_index_s cn30xx; ++ struct cvmx_fpa_quex_page_index_s cn31xx; ++ struct cvmx_fpa_quex_page_index_s cn38xx; ++ struct cvmx_fpa_quex_page_index_s cn38xxp2; ++ struct cvmx_fpa_quex_page_index_s cn50xx; ++ struct cvmx_fpa_quex_page_index_s cn52xx; ++ struct cvmx_fpa_quex_page_index_s cn52xxp1; ++ struct cvmx_fpa_quex_page_index_s cn56xx; ++ struct cvmx_fpa_quex_page_index_s cn56xxp1; ++ struct cvmx_fpa_quex_page_index_s cn58xx; ++ struct cvmx_fpa_quex_page_index_s cn58xxp1; ++}; ++ ++union cvmx_fpa_que_act { ++ uint64_t u64; ++ struct cvmx_fpa_que_act_s { ++ uint64_t reserved_29_63:35; ++ uint64_t act_que:3; ++ uint64_t act_indx:26; ++ } s; ++ struct cvmx_fpa_que_act_s cn30xx; ++ struct cvmx_fpa_que_act_s cn31xx; ++ struct cvmx_fpa_que_act_s cn38xx; ++ struct cvmx_fpa_que_act_s cn38xxp2; ++ struct cvmx_fpa_que_act_s cn50xx; ++ struct cvmx_fpa_que_act_s cn52xx; ++ struct cvmx_fpa_que_act_s cn52xxp1; ++ struct cvmx_fpa_que_act_s cn56xx; ++ struct cvmx_fpa_que_act_s cn56xxp1; ++ struct cvmx_fpa_que_act_s cn58xx; ++ struct cvmx_fpa_que_act_s cn58xxp1; ++}; ++ ++union cvmx_fpa_que_exp { ++ uint64_t u64; ++ struct cvmx_fpa_que_exp_s { ++ uint64_t reserved_29_63:35; ++ uint64_t exp_que:3; ++ uint64_t exp_indx:26; ++ } s; ++ struct cvmx_fpa_que_exp_s cn30xx; ++ struct cvmx_fpa_que_exp_s cn31xx; ++ struct cvmx_fpa_que_exp_s cn38xx; ++ struct cvmx_fpa_que_exp_s cn38xxp2; ++ struct cvmx_fpa_que_exp_s cn50xx; ++ struct cvmx_fpa_que_exp_s cn52xx; ++ struct cvmx_fpa_que_exp_s cn52xxp1; ++ struct cvmx_fpa_que_exp_s cn56xx; ++ struct cvmx_fpa_que_exp_s cn56xxp1; ++ struct cvmx_fpa_que_exp_s cn58xx; ++ struct cvmx_fpa_que_exp_s cn58xxp1; ++}; ++ ++union cvmx_fpa_wart_ctl { ++ uint64_t u64; ++ struct cvmx_fpa_wart_ctl_s { ++ uint64_t reserved_16_63:48; ++ uint64_t ctl:16; ++ } s; ++ struct cvmx_fpa_wart_ctl_s cn30xx; ++ struct cvmx_fpa_wart_ctl_s cn31xx; ++ struct cvmx_fpa_wart_ctl_s cn38xx; ++ struct cvmx_fpa_wart_ctl_s cn38xxp2; ++ struct cvmx_fpa_wart_ctl_s cn50xx; ++ struct cvmx_fpa_wart_ctl_s cn52xx; ++ struct cvmx_fpa_wart_ctl_s cn52xxp1; ++ struct cvmx_fpa_wart_ctl_s cn56xx; ++ struct cvmx_fpa_wart_ctl_s cn56xxp1; ++ struct cvmx_fpa_wart_ctl_s cn58xx; ++ struct cvmx_fpa_wart_ctl_s cn58xxp1; ++}; ++ ++union cvmx_fpa_wart_status { ++ uint64_t u64; ++ struct cvmx_fpa_wart_status_s { ++ uint64_t reserved_32_63:32; ++ uint64_t status:32; ++ } s; ++ struct cvmx_fpa_wart_status_s cn30xx; ++ struct cvmx_fpa_wart_status_s cn31xx; ++ struct cvmx_fpa_wart_status_s cn38xx; ++ struct cvmx_fpa_wart_status_s cn38xxp2; ++ struct cvmx_fpa_wart_status_s cn50xx; ++ struct cvmx_fpa_wart_status_s cn52xx; ++ struct cvmx_fpa_wart_status_s cn52xxp1; ++ struct cvmx_fpa_wart_status_s cn56xx; ++ struct cvmx_fpa_wart_status_s cn56xxp1; ++ struct cvmx_fpa_wart_status_s cn58xx; ++ struct cvmx_fpa_wart_status_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-fpa.c +@@ -0,0 +1,183 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Support library for the hardware Free Pool Allocator. ++ * ++ * ++ */ ++ ++#include "cvmx-config.h" ++#include "cvmx.h" ++#include "cvmx-fpa.h" ++#include "cvmx-ipd.h" ++ ++/** ++ * Current state of all the pools. Use access functions ++ * instead of using it directly. ++ */ ++CVMX_SHARED cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS]; ++ ++/** ++ * Setup a FPA pool to control a new block of memory. The ++ * buffer pointer must be a physical address. ++ * ++ * @pool: Pool to initialize ++ * 0 <= pool < 8 ++ * @name: Constant character string to name this pool. ++ * String is not copied. ++ * @buffer: Pointer to the block of memory to use. This must be ++ * accessable by all processors and external hardware. ++ * @block_size: Size for each block controlled by the FPA ++ * @num_blocks: Number of blocks ++ * ++ * Returns 0 on Success, ++ * -1 on failure ++ */ ++int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer, ++ uint64_t block_size, uint64_t num_blocks) ++{ ++ char *ptr; ++ if (!buffer) { ++ cvmx_dprintf ++ ("ERROR: cvmx_fpa_setup_pool: NULL buffer pointer!\n"); ++ return -1; ++ } ++ if (pool >= CVMX_FPA_NUM_POOLS) { ++ cvmx_dprintf("ERROR: cvmx_fpa_setup_pool: Illegal pool!\n"); ++ return -1; ++ } ++ ++ if (block_size < CVMX_FPA_MIN_BLOCK_SIZE) { ++ cvmx_dprintf ++ ("ERROR: cvmx_fpa_setup_pool: Block size too small.\n"); ++ return -1; ++ } ++ ++ if (((unsigned long)buffer & (CVMX_FPA_ALIGNMENT - 1)) != 0) { ++ cvmx_dprintf ++ ("ERROR: cvmx_fpa_setup_pool: Buffer not aligned properly.\n"); ++ return -1; ++ } ++ ++ cvmx_fpa_pool_info[pool].name = name; ++ cvmx_fpa_pool_info[pool].size = block_size; ++ cvmx_fpa_pool_info[pool].starting_element_count = num_blocks; ++ cvmx_fpa_pool_info[pool].base = buffer; ++ ++ ptr = (char *)buffer; ++ while (num_blocks--) { ++ cvmx_fpa_free(ptr, pool, 0); ++ ptr += block_size; ++ } ++ return 0; ++} ++ ++/** ++ * Shutdown a Memory pool and validate that it had all of ++ * the buffers originally placed in it. ++ * ++ * @pool: Pool to shutdown ++ * Returns Zero on success ++ * - Positive is count of missing buffers ++ * - Negative is too many buffers or corrupted pointers ++ */ ++uint64_t cvmx_fpa_shutdown_pool(uint64_t pool) ++{ ++ uint64_t errors = 0; ++ uint64_t count = 0; ++ uint64_t base = cvmx_ptr_to_phys(cvmx_fpa_pool_info[pool].base); ++ uint64_t finish = ++ base + ++ cvmx_fpa_pool_info[pool].size * ++ cvmx_fpa_pool_info[pool].starting_element_count; ++ void *ptr; ++ uint64_t address; ++ ++ count = 0; ++ do { ++ ptr = cvmx_fpa_alloc(pool); ++ if (ptr) ++ address = cvmx_ptr_to_phys(ptr); ++ else ++ address = 0; ++ if (address) { ++ if ((address >= base) && (address < finish) && ++ (((address - ++ base) % cvmx_fpa_pool_info[pool].size) == 0)) { ++ count++; ++ } else { ++ cvmx_dprintf ++ ("ERROR: cvmx_fpa_shutdown_pool: Illegal address 0x%llx in pool %s(%d)\n", ++ (unsigned long long)address, ++ cvmx_fpa_pool_info[pool].name, (int)pool); ++ errors++; ++ } ++ } ++ } while (address); ++ ++#ifdef CVMX_ENABLE_PKO_FUNCTIONS ++ if (pool == 0) ++ cvmx_ipd_free_ptr(); ++#endif ++ ++ if (errors) { ++ cvmx_dprintf ++ ("ERROR: cvmx_fpa_shutdown_pool: Pool %s(%d) started at 0x%llx, ended at 0x%llx, with a step of 0x%llx\n", ++ cvmx_fpa_pool_info[pool].name, (int)pool, ++ (unsigned long long)base, (unsigned long long)finish, ++ (unsigned long long)cvmx_fpa_pool_info[pool].size); ++ return -errors; ++ } else ++ return 0; ++} ++ ++uint64_t cvmx_fpa_get_block_size(uint64_t pool) ++{ ++ switch (pool) { ++ case 0: ++ return CVMX_FPA_POOL_0_SIZE; ++ case 1: ++ return CVMX_FPA_POOL_1_SIZE; ++ case 2: ++ return CVMX_FPA_POOL_2_SIZE; ++ case 3: ++ return CVMX_FPA_POOL_3_SIZE; ++ case 4: ++ return CVMX_FPA_POOL_4_SIZE; ++ case 5: ++ return CVMX_FPA_POOL_5_SIZE; ++ case 6: ++ return CVMX_FPA_POOL_6_SIZE; ++ case 7: ++ return CVMX_FPA_POOL_7_SIZE; ++ default: ++ return 0; ++ } ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-fpa.h +@@ -0,0 +1,299 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Interface to the hardware Free Pool Allocator. ++ * ++ * ++ */ ++ ++#ifndef __CVMX_FPA_H__ ++#define __CVMX_FPA_H__ ++ ++#include "cvmx-address.h" ++#include "cvmx-fpa-defs.h" ++ ++#define CVMX_FPA_NUM_POOLS 8 ++#define CVMX_FPA_MIN_BLOCK_SIZE 128 ++#define CVMX_FPA_ALIGNMENT 128 ++ ++/** ++ * Structure describing the data format used for stores to the FPA. ++ */ ++typedef union { ++ uint64_t u64; ++ struct { ++ /* ++ * the (64-bit word) location in scratchpad to write ++ * to (if len != 0) ++ */ ++ uint64_t scraddr:8; ++ /* the number of words in the response (0 => no response) */ ++ uint64_t len:8; ++ /* the ID of the device on the non-coherent bus */ ++ uint64_t did:8; ++ /* ++ * the address that will appear in the first tick on ++ * the NCB bus. ++ */ ++ uint64_t addr:40; ++ } s; ++} cvmx_fpa_iobdma_data_t; ++ ++/** ++ * Structure describing the current state of a FPA pool. ++ */ ++typedef struct { ++ /* Name it was created under */ ++ const char *name; ++ /* Size of each block */ ++ uint64_t size; ++ /* The base memory address of whole block */ ++ void *base; ++ /* The number of elements in the pool at creation */ ++ uint64_t starting_element_count; ++} cvmx_fpa_pool_info_t; ++ ++/** ++ * Current state of all the pools. Use access functions ++ * instead of using it directly. ++ */ ++extern cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS]; ++ ++/* CSR typedefs have been moved to cvmx-csr-*.h */ ++ ++/** ++ * Return the name of the pool ++ * ++ * @pool: Pool to get the name of ++ * Returns The name ++ */ ++static inline const char *cvmx_fpa_get_name(uint64_t pool) ++{ ++ return cvmx_fpa_pool_info[pool].name; ++} ++ ++/** ++ * Return the base of the pool ++ * ++ * @pool: Pool to get the base of ++ * Returns The base ++ */ ++static inline void *cvmx_fpa_get_base(uint64_t pool) ++{ ++ return cvmx_fpa_pool_info[pool].base; ++} ++ ++/** ++ * Check if a pointer belongs to an FPA pool. Return non-zero ++ * if the supplied pointer is inside the memory controlled by ++ * an FPA pool. ++ * ++ * @pool: Pool to check ++ * @ptr: Pointer to check ++ * Returns Non-zero if pointer is in the pool. Zero if not ++ */ ++static inline int cvmx_fpa_is_member(uint64_t pool, void *ptr) ++{ ++ return ((ptr >= cvmx_fpa_pool_info[pool].base) && ++ ((char *)ptr < ++ ((char *)(cvmx_fpa_pool_info[pool].base)) + ++ cvmx_fpa_pool_info[pool].size * ++ cvmx_fpa_pool_info[pool].starting_element_count)); ++} ++ ++/** ++ * Enable the FPA for use. Must be performed after any CSR ++ * configuration but before any other FPA functions. ++ */ ++static inline void cvmx_fpa_enable(void) ++{ ++ union cvmx_fpa_ctl_status status; ++ ++ status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS); ++ if (status.s.enb) { ++ cvmx_dprintf ++ ("Warning: Enabling FPA when FPA already enabled.\n"); ++ } ++ ++ /* ++ * Do runtime check as we allow pass1 compiled code to run on ++ * pass2 chips. ++ */ ++ if (cvmx_octeon_is_pass1()) { ++ union cvmx_fpa_fpfx_marks marks; ++ int i; ++ for (i = 1; i < 8; i++) { ++ marks.u64 = ++ cvmx_read_csr(CVMX_FPA_FPF1_MARKS + (i - 1) * 8ull); ++ marks.s.fpf_wr = 0xe0; ++ cvmx_write_csr(CVMX_FPA_FPF1_MARKS + (i - 1) * 8ull, ++ marks.u64); ++ } ++ ++ /* Enforce a 10 cycle delay between config and enable */ ++ cvmx_wait(10); ++ } ++ ++ /* FIXME: CVMX_FPA_CTL_STATUS read is unmodelled */ ++ status.u64 = 0; ++ status.s.enb = 1; ++ cvmx_write_csr(CVMX_FPA_CTL_STATUS, status.u64); ++} ++ ++/** ++ * Get a new block from the FPA ++ * ++ * @pool: Pool to get the block from ++ * Returns Pointer to the block or NULL on failure ++ */ ++static inline void *cvmx_fpa_alloc(uint64_t pool) ++{ ++ uint64_t address = ++ cvmx_read_csr(CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool))); ++ if (address) ++ return cvmx_phys_to_ptr(address); ++ else ++ return NULL; ++} ++ ++/** ++ * Asynchronously get a new block from the FPA ++ * ++ * @scr_addr: Local scratch address to put response in. This is a byte address, ++ * but must be 8 byte aligned. ++ * @pool: Pool to get the block from ++ */ ++static inline void cvmx_fpa_async_alloc(uint64_t scr_addr, uint64_t pool) ++{ ++ cvmx_fpa_iobdma_data_t data; ++ ++ /* ++ * Hardware only uses 64 bit alligned locations, so convert ++ * from byte address to 64-bit index ++ */ ++ data.s.scraddr = scr_addr >> 3; ++ data.s.len = 1; ++ data.s.did = CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool); ++ data.s.addr = 0; ++ cvmx_send_single(data.u64); ++} ++ ++/** ++ * Free a block allocated with a FPA pool. Does NOT provide memory ++ * ordering in cases where the memory block was modified by the core. ++ * ++ * @ptr: Block to free ++ * @pool: Pool to put it in ++ * @num_cache_lines: ++ * Cache lines to invalidate ++ */ ++static inline void cvmx_fpa_free_nosync(void *ptr, uint64_t pool, ++ uint64_t num_cache_lines) ++{ ++ cvmx_addr_t newptr; ++ newptr.u64 = cvmx_ptr_to_phys(ptr); ++ newptr.sfilldidspace.didspace = ++ CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)); ++ /* Prevent GCC from reordering around free */ ++ barrier(); ++ /* value written is number of cache lines not written back */ ++ cvmx_write_io(newptr.u64, num_cache_lines); ++} ++ ++/** ++ * Free a block allocated with a FPA pool. Provides required memory ++ * ordering in cases where memory block was modified by core. ++ * ++ * @ptr: Block to free ++ * @pool: Pool to put it in ++ * @num_cache_lines: ++ * Cache lines to invalidate ++ */ ++static inline void cvmx_fpa_free(void *ptr, uint64_t pool, ++ uint64_t num_cache_lines) ++{ ++ cvmx_addr_t newptr; ++ newptr.u64 = cvmx_ptr_to_phys(ptr); ++ newptr.sfilldidspace.didspace = ++ CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)); ++ /* ++ * Make sure that any previous writes to memory go out before ++ * we free this buffer. This also serves as a barrier to ++ * prevent GCC from reordering operations to after the ++ * free. ++ */ ++ CVMX_SYNCWS; ++ /* value written is number of cache lines not written back */ ++ cvmx_write_io(newptr.u64, num_cache_lines); ++} ++ ++/** ++ * Setup a FPA pool to control a new block of memory. ++ * This can only be called once per pool. Make sure proper ++ * locking enforces this. ++ * ++ * @pool: Pool to initialize ++ * 0 <= pool < 8 ++ * @name: Constant character string to name this pool. ++ * String is not copied. ++ * @buffer: Pointer to the block of memory to use. This must be ++ * accessable by all processors and external hardware. ++ * @block_size: Size for each block controlled by the FPA ++ * @num_blocks: Number of blocks ++ * ++ * Returns 0 on Success, ++ * -1 on failure ++ */ ++extern int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer, ++ uint64_t block_size, uint64_t num_blocks); ++ ++/** ++ * Shutdown a Memory pool and validate that it had all of ++ * the buffers originally placed in it. This should only be ++ * called by one processor after all hardware has finished ++ * using the pool. ++ * ++ * @pool: Pool to shutdown ++ * Returns Zero on success ++ * - Positive is count of missing buffers ++ * - Negative is too many buffers or corrupted pointers ++ */ ++extern uint64_t cvmx_fpa_shutdown_pool(uint64_t pool); ++ ++/** ++ * Get the size of blocks controlled by the pool ++ * This is resolved to a constant at compile time. ++ * ++ * @pool: Pool to access ++ * Returns Size of the block in bytes ++ */ ++uint64_t cvmx_fpa_get_block_size(uint64_t pool); ++ ++#endif /* __CVM_FPA_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-gmxx-defs.h +@@ -0,0 +1,2529 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_GMXX_DEFS_H__ ++#define __CVMX_GMXX_DEFS_H__ ++ ++#define CVMX_GMXX_BAD_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000518ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_BIST(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000400ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_CLK_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080007F0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_HG2_CONTROL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000550ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_INF_MODE(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080007F8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_NXA_ADR(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000510ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_PRTX_CBFC_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000580ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_PRTX_CFG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000010ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM0(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000180ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM1(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000188ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM2(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000190ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM3(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000198ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM4(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080001A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM5(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080001A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CAM_EN(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000108ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_ADR_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000100ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_DECISION(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000040ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_FRM_CHK(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000020ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_FRM_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000018ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_FRM_MAX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000030ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_FRM_MIN(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000028ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_IFG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000058ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_INT_EN(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000008ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_INT_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000000ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_JABBER(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000038ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_PAUSE_DROP_TIME(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000068ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_RX_INBND(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000060ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000050ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_OCTS(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000088ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_OCTS_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000098ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_OCTS_DMAC(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080000A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_OCTS_DRP(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080000B8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_PKTS(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000080ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_PKTS_BAD(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080000C0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_PKTS_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000090ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_PKTS_DMAC(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080000A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_STATS_PKTS_DRP(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080000B0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RXX_UDD_SKP(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000048ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_BP_DROPX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000420ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_BP_OFFX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000460ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_BP_ONX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000440ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_HG2_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000548ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_PASS_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080005F8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_PASS_MAPX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000600ull + (((offset) & 15) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_PRTS(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000410ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_PRT_INFO(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004E8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_TX_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080007E8ull + (((block_id) & 0) * 0x8000000ull)) ++#define CVMX_GMXX_RX_XAUI_BAD_COL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000538ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_RX_XAUI_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000530ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_SMACX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000230ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_STAT_BP(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000520ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_APPEND(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000218ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_BURST(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000228ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_CBFC_XOFF(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080005A0ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_CBFC_XON(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080005C0ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_CLK(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000208ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000270ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_MIN_PKT(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000240ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000248ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_PAUSE_PKT_TIME(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000238ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_PAUSE_TOGO(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000258ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_PAUSE_ZERO(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000260ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_SGMII_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000300ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_SLOT(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000220ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_SOFT_PAUSE(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000250ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT0(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000280ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT1(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000288ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT2(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000290ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT3(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000298ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT4(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080002A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT5(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080002A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT6(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080002B0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT7(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080002B8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT8(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080002C0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STAT9(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080002C8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_STATS_CTL(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000268ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TXX_THRESH(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000210ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_BP(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004D0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_CLK_MSKX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000780ull + (((offset) & 1) * 8) + (((block_id) & 0) * 0x0ull)) ++#define CVMX_GMXX_TX_COL_ATTEMPT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000498ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_CORRUPT(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004D8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_HG2_REG1(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000558ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_HG2_REG2(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000560ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_IFG(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000488ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_INT_EN(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000508ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_INT_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000500ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_JAM(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000490ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_LFSR(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004F8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_OVR_BP(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004C8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_PAUSE_PKT_DMAC(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004A0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_PAUSE_PKT_TYPE(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004A8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_PRTS(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000480ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_SPI_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004C0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_SPI_DRAIN(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004E0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_SPI_MAX(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004B0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_SPI_ROUNDX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000680ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_SPI_THRESH(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800080004B8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_TX_XAUI_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000528ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_GMXX_XAUI_EXT_LOOPBACK(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180008000540ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_gmxx_bad_reg { ++ uint64_t u64; ++ struct cvmx_gmxx_bad_reg_s { ++ uint64_t reserved_31_63:33; ++ uint64_t inb_nxa:4; ++ uint64_t statovr:1; ++ uint64_t loststat:4; ++ uint64_t reserved_18_21:4; ++ uint64_t out_ovr:16; ++ uint64_t ncb_ovr:1; ++ uint64_t out_col:1; ++ } s; ++ struct cvmx_gmxx_bad_reg_cn30xx { ++ uint64_t reserved_31_63:33; ++ uint64_t inb_nxa:4; ++ uint64_t statovr:1; ++ uint64_t reserved_25_25:1; ++ uint64_t loststat:3; ++ uint64_t reserved_5_21:17; ++ uint64_t out_ovr:3; ++ uint64_t reserved_0_1:2; ++ } cn30xx; ++ struct cvmx_gmxx_bad_reg_cn30xx cn31xx; ++ struct cvmx_gmxx_bad_reg_s cn38xx; ++ struct cvmx_gmxx_bad_reg_s cn38xxp2; ++ struct cvmx_gmxx_bad_reg_cn30xx cn50xx; ++ struct cvmx_gmxx_bad_reg_cn52xx { ++ uint64_t reserved_31_63:33; ++ uint64_t inb_nxa:4; ++ uint64_t statovr:1; ++ uint64_t loststat:4; ++ uint64_t reserved_6_21:16; ++ uint64_t out_ovr:4; ++ uint64_t reserved_0_1:2; ++ } cn52xx; ++ struct cvmx_gmxx_bad_reg_cn52xx cn52xxp1; ++ struct cvmx_gmxx_bad_reg_cn52xx cn56xx; ++ struct cvmx_gmxx_bad_reg_cn52xx cn56xxp1; ++ struct cvmx_gmxx_bad_reg_s cn58xx; ++ struct cvmx_gmxx_bad_reg_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_bist { ++ uint64_t u64; ++ struct cvmx_gmxx_bist_s { ++ uint64_t reserved_17_63:47; ++ uint64_t status:17; ++ } s; ++ struct cvmx_gmxx_bist_cn30xx { ++ uint64_t reserved_10_63:54; ++ uint64_t status:10; ++ } cn30xx; ++ struct cvmx_gmxx_bist_cn30xx cn31xx; ++ struct cvmx_gmxx_bist_cn30xx cn38xx; ++ struct cvmx_gmxx_bist_cn30xx cn38xxp2; ++ struct cvmx_gmxx_bist_cn50xx { ++ uint64_t reserved_12_63:52; ++ uint64_t status:12; ++ } cn50xx; ++ struct cvmx_gmxx_bist_cn52xx { ++ uint64_t reserved_16_63:48; ++ uint64_t status:16; ++ } cn52xx; ++ struct cvmx_gmxx_bist_cn52xx cn52xxp1; ++ struct cvmx_gmxx_bist_cn52xx cn56xx; ++ struct cvmx_gmxx_bist_cn52xx cn56xxp1; ++ struct cvmx_gmxx_bist_s cn58xx; ++ struct cvmx_gmxx_bist_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_clk_en { ++ uint64_t u64; ++ struct cvmx_gmxx_clk_en_s { ++ uint64_t reserved_1_63:63; ++ uint64_t clk_en:1; ++ } s; ++ struct cvmx_gmxx_clk_en_s cn52xx; ++ struct cvmx_gmxx_clk_en_s cn52xxp1; ++ struct cvmx_gmxx_clk_en_s cn56xx; ++ struct cvmx_gmxx_clk_en_s cn56xxp1; ++}; ++ ++union cvmx_gmxx_hg2_control { ++ uint64_t u64; ++ struct cvmx_gmxx_hg2_control_s { ++ uint64_t reserved_19_63:45; ++ uint64_t hg2tx_en:1; ++ uint64_t hg2rx_en:1; ++ uint64_t phys_en:1; ++ uint64_t logl_en:16; ++ } s; ++ struct cvmx_gmxx_hg2_control_s cn52xx; ++ struct cvmx_gmxx_hg2_control_s cn52xxp1; ++ struct cvmx_gmxx_hg2_control_s cn56xx; ++}; ++ ++union cvmx_gmxx_inf_mode { ++ uint64_t u64; ++ struct cvmx_gmxx_inf_mode_s { ++ uint64_t reserved_10_63:54; ++ uint64_t speed:2; ++ uint64_t reserved_6_7:2; ++ uint64_t mode:2; ++ uint64_t reserved_3_3:1; ++ uint64_t p0mii:1; ++ uint64_t en:1; ++ uint64_t type:1; ++ } s; ++ struct cvmx_gmxx_inf_mode_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t p0mii:1; ++ uint64_t en:1; ++ uint64_t type:1; ++ } cn30xx; ++ struct cvmx_gmxx_inf_mode_cn31xx { ++ uint64_t reserved_2_63:62; ++ uint64_t en:1; ++ uint64_t type:1; ++ } cn31xx; ++ struct cvmx_gmxx_inf_mode_cn31xx cn38xx; ++ struct cvmx_gmxx_inf_mode_cn31xx cn38xxp2; ++ struct cvmx_gmxx_inf_mode_cn30xx cn50xx; ++ struct cvmx_gmxx_inf_mode_cn52xx { ++ uint64_t reserved_10_63:54; ++ uint64_t speed:2; ++ uint64_t reserved_6_7:2; ++ uint64_t mode:2; ++ uint64_t reserved_2_3:2; ++ uint64_t en:1; ++ uint64_t type:1; ++ } cn52xx; ++ struct cvmx_gmxx_inf_mode_cn52xx cn52xxp1; ++ struct cvmx_gmxx_inf_mode_cn52xx cn56xx; ++ struct cvmx_gmxx_inf_mode_cn52xx cn56xxp1; ++ struct cvmx_gmxx_inf_mode_cn31xx cn58xx; ++ struct cvmx_gmxx_inf_mode_cn31xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_nxa_adr { ++ uint64_t u64; ++ struct cvmx_gmxx_nxa_adr_s { ++ uint64_t reserved_6_63:58; ++ uint64_t prt:6; ++ } s; ++ struct cvmx_gmxx_nxa_adr_s cn30xx; ++ struct cvmx_gmxx_nxa_adr_s cn31xx; ++ struct cvmx_gmxx_nxa_adr_s cn38xx; ++ struct cvmx_gmxx_nxa_adr_s cn38xxp2; ++ struct cvmx_gmxx_nxa_adr_s cn50xx; ++ struct cvmx_gmxx_nxa_adr_s cn52xx; ++ struct cvmx_gmxx_nxa_adr_s cn52xxp1; ++ struct cvmx_gmxx_nxa_adr_s cn56xx; ++ struct cvmx_gmxx_nxa_adr_s cn56xxp1; ++ struct cvmx_gmxx_nxa_adr_s cn58xx; ++ struct cvmx_gmxx_nxa_adr_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_prtx_cbfc_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_prtx_cbfc_ctl_s { ++ uint64_t phys_en:16; ++ uint64_t logl_en:16; ++ uint64_t phys_bp:16; ++ uint64_t reserved_4_15:12; ++ uint64_t bck_en:1; ++ uint64_t drp_en:1; ++ uint64_t tx_en:1; ++ uint64_t rx_en:1; ++ } s; ++ struct cvmx_gmxx_prtx_cbfc_ctl_s cn52xx; ++ struct cvmx_gmxx_prtx_cbfc_ctl_s cn56xx; ++}; ++ ++union cvmx_gmxx_prtx_cfg { ++ uint64_t u64; ++ struct cvmx_gmxx_prtx_cfg_s { ++ uint64_t reserved_14_63:50; ++ uint64_t tx_idle:1; ++ uint64_t rx_idle:1; ++ uint64_t reserved_9_11:3; ++ uint64_t speed_msb:1; ++ uint64_t reserved_4_7:4; ++ uint64_t slottime:1; ++ uint64_t duplex:1; ++ uint64_t speed:1; ++ uint64_t en:1; ++ } s; ++ struct cvmx_gmxx_prtx_cfg_cn30xx { ++ uint64_t reserved_4_63:60; ++ uint64_t slottime:1; ++ uint64_t duplex:1; ++ uint64_t speed:1; ++ uint64_t en:1; ++ } cn30xx; ++ struct cvmx_gmxx_prtx_cfg_cn30xx cn31xx; ++ struct cvmx_gmxx_prtx_cfg_cn30xx cn38xx; ++ struct cvmx_gmxx_prtx_cfg_cn30xx cn38xxp2; ++ struct cvmx_gmxx_prtx_cfg_cn30xx cn50xx; ++ struct cvmx_gmxx_prtx_cfg_s cn52xx; ++ struct cvmx_gmxx_prtx_cfg_s cn52xxp1; ++ struct cvmx_gmxx_prtx_cfg_s cn56xx; ++ struct cvmx_gmxx_prtx_cfg_s cn56xxp1; ++ struct cvmx_gmxx_prtx_cfg_cn30xx cn58xx; ++ struct cvmx_gmxx_prtx_cfg_cn30xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam0 { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam0_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam0_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam1 { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam1_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam1_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam2 { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam2_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam2_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam3 { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam3_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam3_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam4 { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam4_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam4_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam5 { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam5_s { ++ uint64_t adr:64; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam5_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_cam_en { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_cam_en_s { ++ uint64_t reserved_8_63:56; ++ uint64_t en:8; ++ } s; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_cam_en_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_adr_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_adr_ctl_s { ++ uint64_t reserved_4_63:60; ++ uint64_t cam_mode:1; ++ uint64_t mcst:2; ++ uint64_t bcst:1; ++ } s; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn30xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn31xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn38xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn38xxp2; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn50xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn52xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn52xxp1; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn56xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn56xxp1; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn58xx; ++ struct cvmx_gmxx_rxx_adr_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_decision { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_decision_s { ++ uint64_t reserved_5_63:59; ++ uint64_t cnt:5; ++ } s; ++ struct cvmx_gmxx_rxx_decision_s cn30xx; ++ struct cvmx_gmxx_rxx_decision_s cn31xx; ++ struct cvmx_gmxx_rxx_decision_s cn38xx; ++ struct cvmx_gmxx_rxx_decision_s cn38xxp2; ++ struct cvmx_gmxx_rxx_decision_s cn50xx; ++ struct cvmx_gmxx_rxx_decision_s cn52xx; ++ struct cvmx_gmxx_rxx_decision_s cn52xxp1; ++ struct cvmx_gmxx_rxx_decision_s cn56xx; ++ struct cvmx_gmxx_rxx_decision_s cn56xxp1; ++ struct cvmx_gmxx_rxx_decision_s cn58xx; ++ struct cvmx_gmxx_rxx_decision_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_frm_chk { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_frm_chk_s { ++ uint64_t reserved_10_63:54; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } s; ++ struct cvmx_gmxx_rxx_frm_chk_s cn30xx; ++ struct cvmx_gmxx_rxx_frm_chk_s cn31xx; ++ struct cvmx_gmxx_rxx_frm_chk_s cn38xx; ++ struct cvmx_gmxx_rxx_frm_chk_s cn38xxp2; ++ struct cvmx_gmxx_rxx_frm_chk_cn50xx { ++ uint64_t reserved_10_63:54; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_6_6:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn50xx; ++ struct cvmx_gmxx_rxx_frm_chk_cn52xx { ++ uint64_t reserved_9_63:55; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_5_6:2; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn52xx; ++ struct cvmx_gmxx_rxx_frm_chk_cn52xx cn52xxp1; ++ struct cvmx_gmxx_rxx_frm_chk_cn52xx cn56xx; ++ struct cvmx_gmxx_rxx_frm_chk_cn52xx cn56xxp1; ++ struct cvmx_gmxx_rxx_frm_chk_s cn58xx; ++ struct cvmx_gmxx_rxx_frm_chk_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_frm_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_frm_ctl_s { ++ uint64_t reserved_11_63:53; ++ uint64_t null_dis:1; ++ uint64_t pre_align:1; ++ uint64_t pad_len:1; ++ uint64_t vlan_len:1; ++ uint64_t pre_free:1; ++ uint64_t ctl_smac:1; ++ uint64_t ctl_mcst:1; ++ uint64_t ctl_bck:1; ++ uint64_t ctl_drp:1; ++ uint64_t pre_strp:1; ++ uint64_t pre_chk:1; ++ } s; ++ struct cvmx_gmxx_rxx_frm_ctl_cn30xx { ++ uint64_t reserved_9_63:55; ++ uint64_t pad_len:1; ++ uint64_t vlan_len:1; ++ uint64_t pre_free:1; ++ uint64_t ctl_smac:1; ++ uint64_t ctl_mcst:1; ++ uint64_t ctl_bck:1; ++ uint64_t ctl_drp:1; ++ uint64_t pre_strp:1; ++ uint64_t pre_chk:1; ++ } cn30xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn31xx { ++ uint64_t reserved_8_63:56; ++ uint64_t vlan_len:1; ++ uint64_t pre_free:1; ++ uint64_t ctl_smac:1; ++ uint64_t ctl_mcst:1; ++ uint64_t ctl_bck:1; ++ uint64_t ctl_drp:1; ++ uint64_t pre_strp:1; ++ uint64_t pre_chk:1; ++ } cn31xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn30xx cn38xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn31xx cn38xxp2; ++ struct cvmx_gmxx_rxx_frm_ctl_cn50xx { ++ uint64_t reserved_11_63:53; ++ uint64_t null_dis:1; ++ uint64_t pre_align:1; ++ uint64_t reserved_7_8:2; ++ uint64_t pre_free:1; ++ uint64_t ctl_smac:1; ++ uint64_t ctl_mcst:1; ++ uint64_t ctl_bck:1; ++ uint64_t ctl_drp:1; ++ uint64_t pre_strp:1; ++ uint64_t pre_chk:1; ++ } cn50xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn52xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn52xxp1; ++ struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn56xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn56xxp1 { ++ uint64_t reserved_10_63:54; ++ uint64_t pre_align:1; ++ uint64_t reserved_7_8:2; ++ uint64_t pre_free:1; ++ uint64_t ctl_smac:1; ++ uint64_t ctl_mcst:1; ++ uint64_t ctl_bck:1; ++ uint64_t ctl_drp:1; ++ uint64_t pre_strp:1; ++ uint64_t pre_chk:1; ++ } cn56xxp1; ++ struct cvmx_gmxx_rxx_frm_ctl_s cn58xx; ++ struct cvmx_gmxx_rxx_frm_ctl_cn30xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_frm_max { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_frm_max_s { ++ uint64_t reserved_16_63:48; ++ uint64_t len:16; ++ } s; ++ struct cvmx_gmxx_rxx_frm_max_s cn30xx; ++ struct cvmx_gmxx_rxx_frm_max_s cn31xx; ++ struct cvmx_gmxx_rxx_frm_max_s cn38xx; ++ struct cvmx_gmxx_rxx_frm_max_s cn38xxp2; ++ struct cvmx_gmxx_rxx_frm_max_s cn58xx; ++ struct cvmx_gmxx_rxx_frm_max_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_frm_min { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_frm_min_s { ++ uint64_t reserved_16_63:48; ++ uint64_t len:16; ++ } s; ++ struct cvmx_gmxx_rxx_frm_min_s cn30xx; ++ struct cvmx_gmxx_rxx_frm_min_s cn31xx; ++ struct cvmx_gmxx_rxx_frm_min_s cn38xx; ++ struct cvmx_gmxx_rxx_frm_min_s cn38xxp2; ++ struct cvmx_gmxx_rxx_frm_min_s cn58xx; ++ struct cvmx_gmxx_rxx_frm_min_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_ifg { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_ifg_s { ++ uint64_t reserved_4_63:60; ++ uint64_t ifg:4; ++ } s; ++ struct cvmx_gmxx_rxx_ifg_s cn30xx; ++ struct cvmx_gmxx_rxx_ifg_s cn31xx; ++ struct cvmx_gmxx_rxx_ifg_s cn38xx; ++ struct cvmx_gmxx_rxx_ifg_s cn38xxp2; ++ struct cvmx_gmxx_rxx_ifg_s cn50xx; ++ struct cvmx_gmxx_rxx_ifg_s cn52xx; ++ struct cvmx_gmxx_rxx_ifg_s cn52xxp1; ++ struct cvmx_gmxx_rxx_ifg_s cn56xx; ++ struct cvmx_gmxx_rxx_ifg_s cn56xxp1; ++ struct cvmx_gmxx_rxx_ifg_s cn58xx; ++ struct cvmx_gmxx_rxx_ifg_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_int_en { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_int_en_s { ++ uint64_t reserved_29_63:35; ++ uint64_t hg2cc:1; ++ uint64_t hg2fld:1; ++ uint64_t undat:1; ++ uint64_t uneop:1; ++ uint64_t unsop:1; ++ uint64_t bad_term:1; ++ uint64_t bad_seq:1; ++ uint64_t rem_fault:1; ++ uint64_t loc_fault:1; ++ uint64_t pause_drp:1; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } s; ++ struct cvmx_gmxx_rxx_int_en_cn30xx { ++ uint64_t reserved_19_63:45; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } cn30xx; ++ struct cvmx_gmxx_rxx_int_en_cn30xx cn31xx; ++ struct cvmx_gmxx_rxx_int_en_cn30xx cn38xx; ++ struct cvmx_gmxx_rxx_int_en_cn30xx cn38xxp2; ++ struct cvmx_gmxx_rxx_int_en_cn50xx { ++ uint64_t reserved_20_63:44; ++ uint64_t pause_drp:1; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_6_6:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn50xx; ++ struct cvmx_gmxx_rxx_int_en_cn52xx { ++ uint64_t reserved_29_63:35; ++ uint64_t hg2cc:1; ++ uint64_t hg2fld:1; ++ uint64_t undat:1; ++ uint64_t uneop:1; ++ uint64_t unsop:1; ++ uint64_t bad_term:1; ++ uint64_t bad_seq:1; ++ uint64_t rem_fault:1; ++ uint64_t loc_fault:1; ++ uint64_t pause_drp:1; ++ uint64_t reserved_16_18:3; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t reserved_9_9:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_5_6:2; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn52xx; ++ struct cvmx_gmxx_rxx_int_en_cn52xx cn52xxp1; ++ struct cvmx_gmxx_rxx_int_en_cn52xx cn56xx; ++ struct cvmx_gmxx_rxx_int_en_cn56xxp1 { ++ uint64_t reserved_27_63:37; ++ uint64_t undat:1; ++ uint64_t uneop:1; ++ uint64_t unsop:1; ++ uint64_t bad_term:1; ++ uint64_t bad_seq:1; ++ uint64_t rem_fault:1; ++ uint64_t loc_fault:1; ++ uint64_t pause_drp:1; ++ uint64_t reserved_16_18:3; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t reserved_9_9:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_5_6:2; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn56xxp1; ++ struct cvmx_gmxx_rxx_int_en_cn58xx { ++ uint64_t reserved_20_63:44; ++ uint64_t pause_drp:1; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } cn58xx; ++ struct cvmx_gmxx_rxx_int_en_cn58xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_int_reg { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_int_reg_s { ++ uint64_t reserved_29_63:35; ++ uint64_t hg2cc:1; ++ uint64_t hg2fld:1; ++ uint64_t undat:1; ++ uint64_t uneop:1; ++ uint64_t unsop:1; ++ uint64_t bad_term:1; ++ uint64_t bad_seq:1; ++ uint64_t rem_fault:1; ++ uint64_t loc_fault:1; ++ uint64_t pause_drp:1; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } s; ++ struct cvmx_gmxx_rxx_int_reg_cn30xx { ++ uint64_t reserved_19_63:45; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } cn30xx; ++ struct cvmx_gmxx_rxx_int_reg_cn30xx cn31xx; ++ struct cvmx_gmxx_rxx_int_reg_cn30xx cn38xx; ++ struct cvmx_gmxx_rxx_int_reg_cn30xx cn38xxp2; ++ struct cvmx_gmxx_rxx_int_reg_cn50xx { ++ uint64_t reserved_20_63:44; ++ uint64_t pause_drp:1; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_6_6:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn50xx; ++ struct cvmx_gmxx_rxx_int_reg_cn52xx { ++ uint64_t reserved_29_63:35; ++ uint64_t hg2cc:1; ++ uint64_t hg2fld:1; ++ uint64_t undat:1; ++ uint64_t uneop:1; ++ uint64_t unsop:1; ++ uint64_t bad_term:1; ++ uint64_t bad_seq:1; ++ uint64_t rem_fault:1; ++ uint64_t loc_fault:1; ++ uint64_t pause_drp:1; ++ uint64_t reserved_16_18:3; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t reserved_9_9:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_5_6:2; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn52xx; ++ struct cvmx_gmxx_rxx_int_reg_cn52xx cn52xxp1; ++ struct cvmx_gmxx_rxx_int_reg_cn52xx cn56xx; ++ struct cvmx_gmxx_rxx_int_reg_cn56xxp1 { ++ uint64_t reserved_27_63:37; ++ uint64_t undat:1; ++ uint64_t uneop:1; ++ uint64_t unsop:1; ++ uint64_t bad_term:1; ++ uint64_t bad_seq:1; ++ uint64_t rem_fault:1; ++ uint64_t loc_fault:1; ++ uint64_t pause_drp:1; ++ uint64_t reserved_16_18:3; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t reserved_9_9:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t reserved_5_6:2; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t reserved_2_2:1; ++ uint64_t carext:1; ++ uint64_t reserved_0_0:1; ++ } cn56xxp1; ++ struct cvmx_gmxx_rxx_int_reg_cn58xx { ++ uint64_t reserved_20_63:44; ++ uint64_t pause_drp:1; ++ uint64_t phy_dupx:1; ++ uint64_t phy_spd:1; ++ uint64_t phy_link:1; ++ uint64_t ifgerr:1; ++ uint64_t coldet:1; ++ uint64_t falerr:1; ++ uint64_t rsverr:1; ++ uint64_t pcterr:1; ++ uint64_t ovrerr:1; ++ uint64_t niberr:1; ++ uint64_t skperr:1; ++ uint64_t rcverr:1; ++ uint64_t lenerr:1; ++ uint64_t alnerr:1; ++ uint64_t fcserr:1; ++ uint64_t jabber:1; ++ uint64_t maxerr:1; ++ uint64_t carext:1; ++ uint64_t minerr:1; ++ } cn58xx; ++ struct cvmx_gmxx_rxx_int_reg_cn58xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_jabber { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_jabber_s { ++ uint64_t reserved_16_63:48; ++ uint64_t cnt:16; ++ } s; ++ struct cvmx_gmxx_rxx_jabber_s cn30xx; ++ struct cvmx_gmxx_rxx_jabber_s cn31xx; ++ struct cvmx_gmxx_rxx_jabber_s cn38xx; ++ struct cvmx_gmxx_rxx_jabber_s cn38xxp2; ++ struct cvmx_gmxx_rxx_jabber_s cn50xx; ++ struct cvmx_gmxx_rxx_jabber_s cn52xx; ++ struct cvmx_gmxx_rxx_jabber_s cn52xxp1; ++ struct cvmx_gmxx_rxx_jabber_s cn56xx; ++ struct cvmx_gmxx_rxx_jabber_s cn56xxp1; ++ struct cvmx_gmxx_rxx_jabber_s cn58xx; ++ struct cvmx_gmxx_rxx_jabber_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_pause_drop_time { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_pause_drop_time_s { ++ uint64_t reserved_16_63:48; ++ uint64_t status:16; ++ } s; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn50xx; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn52xx; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn52xxp1; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn56xx; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn56xxp1; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn58xx; ++ struct cvmx_gmxx_rxx_pause_drop_time_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_rx_inbnd { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_rx_inbnd_s { ++ uint64_t reserved_4_63:60; ++ uint64_t duplex:1; ++ uint64_t speed:2; ++ uint64_t status:1; ++ } s; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn30xx; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn31xx; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn38xx; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn38xxp2; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn50xx; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn58xx; ++ struct cvmx_gmxx_rxx_rx_inbnd_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_ctl_s { ++ uint64_t reserved_1_63:63; ++ uint64_t rd_clr:1; ++ } s; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_octs { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_octs_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_gmxx_rxx_stats_octs_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_octs_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_octs_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_octs_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_octs_dmac { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_octs_drp { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s { ++ uint64_t reserved_48_63:16; ++ uint64_t cnt:48; ++ } s; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_octs_drp_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_pkts { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_pkts_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_pkts_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_pkts_bad { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_pkts_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_pkts_dmac { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_stats_pkts_drp { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn30xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn31xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn38xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn38xxp2; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn50xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn52xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn52xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn56xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn56xxp1; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn58xx; ++ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rxx_udd_skp { ++ uint64_t u64; ++ struct cvmx_gmxx_rxx_udd_skp_s { ++ uint64_t reserved_9_63:55; ++ uint64_t fcssel:1; ++ uint64_t reserved_7_7:1; ++ uint64_t len:7; ++ } s; ++ struct cvmx_gmxx_rxx_udd_skp_s cn30xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn31xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn38xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn38xxp2; ++ struct cvmx_gmxx_rxx_udd_skp_s cn50xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn52xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn52xxp1; ++ struct cvmx_gmxx_rxx_udd_skp_s cn56xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn56xxp1; ++ struct cvmx_gmxx_rxx_udd_skp_s cn58xx; ++ struct cvmx_gmxx_rxx_udd_skp_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_bp_dropx { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_bp_dropx_s { ++ uint64_t reserved_6_63:58; ++ uint64_t mark:6; ++ } s; ++ struct cvmx_gmxx_rx_bp_dropx_s cn30xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn31xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn38xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn38xxp2; ++ struct cvmx_gmxx_rx_bp_dropx_s cn50xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn52xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn52xxp1; ++ struct cvmx_gmxx_rx_bp_dropx_s cn56xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn56xxp1; ++ struct cvmx_gmxx_rx_bp_dropx_s cn58xx; ++ struct cvmx_gmxx_rx_bp_dropx_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_bp_offx { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_bp_offx_s { ++ uint64_t reserved_6_63:58; ++ uint64_t mark:6; ++ } s; ++ struct cvmx_gmxx_rx_bp_offx_s cn30xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn31xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn38xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn38xxp2; ++ struct cvmx_gmxx_rx_bp_offx_s cn50xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn52xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn52xxp1; ++ struct cvmx_gmxx_rx_bp_offx_s cn56xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn56xxp1; ++ struct cvmx_gmxx_rx_bp_offx_s cn58xx; ++ struct cvmx_gmxx_rx_bp_offx_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_bp_onx { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_bp_onx_s { ++ uint64_t reserved_9_63:55; ++ uint64_t mark:9; ++ } s; ++ struct cvmx_gmxx_rx_bp_onx_s cn30xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn31xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn38xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn38xxp2; ++ struct cvmx_gmxx_rx_bp_onx_s cn50xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn52xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn52xxp1; ++ struct cvmx_gmxx_rx_bp_onx_s cn56xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn56xxp1; ++ struct cvmx_gmxx_rx_bp_onx_s cn58xx; ++ struct cvmx_gmxx_rx_bp_onx_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_hg2_status { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_hg2_status_s { ++ uint64_t reserved_48_63:16; ++ uint64_t phtim2go:16; ++ uint64_t xof:16; ++ uint64_t lgtim2go:16; ++ } s; ++ struct cvmx_gmxx_rx_hg2_status_s cn52xx; ++ struct cvmx_gmxx_rx_hg2_status_s cn52xxp1; ++ struct cvmx_gmxx_rx_hg2_status_s cn56xx; ++}; ++ ++union cvmx_gmxx_rx_pass_en { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_pass_en_s { ++ uint64_t reserved_16_63:48; ++ uint64_t en:16; ++ } s; ++ struct cvmx_gmxx_rx_pass_en_s cn38xx; ++ struct cvmx_gmxx_rx_pass_en_s cn38xxp2; ++ struct cvmx_gmxx_rx_pass_en_s cn58xx; ++ struct cvmx_gmxx_rx_pass_en_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_pass_mapx { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_pass_mapx_s { ++ uint64_t reserved_4_63:60; ++ uint64_t dprt:4; ++ } s; ++ struct cvmx_gmxx_rx_pass_mapx_s cn38xx; ++ struct cvmx_gmxx_rx_pass_mapx_s cn38xxp2; ++ struct cvmx_gmxx_rx_pass_mapx_s cn58xx; ++ struct cvmx_gmxx_rx_pass_mapx_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_prt_info { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_prt_info_s { ++ uint64_t reserved_32_63:32; ++ uint64_t drop:16; ++ uint64_t commit:16; ++ } s; ++ struct cvmx_gmxx_rx_prt_info_cn30xx { ++ uint64_t reserved_19_63:45; ++ uint64_t drop:3; ++ uint64_t reserved_3_15:13; ++ uint64_t commit:3; ++ } cn30xx; ++ struct cvmx_gmxx_rx_prt_info_cn30xx cn31xx; ++ struct cvmx_gmxx_rx_prt_info_s cn38xx; ++ struct cvmx_gmxx_rx_prt_info_cn30xx cn50xx; ++ struct cvmx_gmxx_rx_prt_info_cn52xx { ++ uint64_t reserved_20_63:44; ++ uint64_t drop:4; ++ uint64_t reserved_4_15:12; ++ uint64_t commit:4; ++ } cn52xx; ++ struct cvmx_gmxx_rx_prt_info_cn52xx cn52xxp1; ++ struct cvmx_gmxx_rx_prt_info_cn52xx cn56xx; ++ struct cvmx_gmxx_rx_prt_info_cn52xx cn56xxp1; ++ struct cvmx_gmxx_rx_prt_info_s cn58xx; ++ struct cvmx_gmxx_rx_prt_info_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_prts { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_prts_s { ++ uint64_t reserved_3_63:61; ++ uint64_t prts:3; ++ } s; ++ struct cvmx_gmxx_rx_prts_s cn30xx; ++ struct cvmx_gmxx_rx_prts_s cn31xx; ++ struct cvmx_gmxx_rx_prts_s cn38xx; ++ struct cvmx_gmxx_rx_prts_s cn38xxp2; ++ struct cvmx_gmxx_rx_prts_s cn50xx; ++ struct cvmx_gmxx_rx_prts_s cn52xx; ++ struct cvmx_gmxx_rx_prts_s cn52xxp1; ++ struct cvmx_gmxx_rx_prts_s cn56xx; ++ struct cvmx_gmxx_rx_prts_s cn56xxp1; ++ struct cvmx_gmxx_rx_prts_s cn58xx; ++ struct cvmx_gmxx_rx_prts_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_rx_tx_status { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_tx_status_s { ++ uint64_t reserved_7_63:57; ++ uint64_t tx:3; ++ uint64_t reserved_3_3:1; ++ uint64_t rx:3; ++ } s; ++ struct cvmx_gmxx_rx_tx_status_s cn30xx; ++ struct cvmx_gmxx_rx_tx_status_s cn31xx; ++ struct cvmx_gmxx_rx_tx_status_s cn50xx; ++}; ++ ++union cvmx_gmxx_rx_xaui_bad_col { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_xaui_bad_col_s { ++ uint64_t reserved_40_63:24; ++ uint64_t val:1; ++ uint64_t state:3; ++ uint64_t lane_rxc:4; ++ uint64_t lane_rxd:32; ++ } s; ++ struct cvmx_gmxx_rx_xaui_bad_col_s cn52xx; ++ struct cvmx_gmxx_rx_xaui_bad_col_s cn52xxp1; ++ struct cvmx_gmxx_rx_xaui_bad_col_s cn56xx; ++ struct cvmx_gmxx_rx_xaui_bad_col_s cn56xxp1; ++}; ++ ++union cvmx_gmxx_rx_xaui_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_rx_xaui_ctl_s { ++ uint64_t reserved_2_63:62; ++ uint64_t status:2; ++ } s; ++ struct cvmx_gmxx_rx_xaui_ctl_s cn52xx; ++ struct cvmx_gmxx_rx_xaui_ctl_s cn52xxp1; ++ struct cvmx_gmxx_rx_xaui_ctl_s cn56xx; ++ struct cvmx_gmxx_rx_xaui_ctl_s cn56xxp1; ++}; ++ ++union cvmx_gmxx_smacx { ++ uint64_t u64; ++ struct cvmx_gmxx_smacx_s { ++ uint64_t reserved_48_63:16; ++ uint64_t smac:48; ++ } s; ++ struct cvmx_gmxx_smacx_s cn30xx; ++ struct cvmx_gmxx_smacx_s cn31xx; ++ struct cvmx_gmxx_smacx_s cn38xx; ++ struct cvmx_gmxx_smacx_s cn38xxp2; ++ struct cvmx_gmxx_smacx_s cn50xx; ++ struct cvmx_gmxx_smacx_s cn52xx; ++ struct cvmx_gmxx_smacx_s cn52xxp1; ++ struct cvmx_gmxx_smacx_s cn56xx; ++ struct cvmx_gmxx_smacx_s cn56xxp1; ++ struct cvmx_gmxx_smacx_s cn58xx; ++ struct cvmx_gmxx_smacx_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_stat_bp { ++ uint64_t u64; ++ struct cvmx_gmxx_stat_bp_s { ++ uint64_t reserved_17_63:47; ++ uint64_t bp:1; ++ uint64_t cnt:16; ++ } s; ++ struct cvmx_gmxx_stat_bp_s cn30xx; ++ struct cvmx_gmxx_stat_bp_s cn31xx; ++ struct cvmx_gmxx_stat_bp_s cn38xx; ++ struct cvmx_gmxx_stat_bp_s cn38xxp2; ++ struct cvmx_gmxx_stat_bp_s cn50xx; ++ struct cvmx_gmxx_stat_bp_s cn52xx; ++ struct cvmx_gmxx_stat_bp_s cn52xxp1; ++ struct cvmx_gmxx_stat_bp_s cn56xx; ++ struct cvmx_gmxx_stat_bp_s cn56xxp1; ++ struct cvmx_gmxx_stat_bp_s cn58xx; ++ struct cvmx_gmxx_stat_bp_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_append { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_append_s { ++ uint64_t reserved_4_63:60; ++ uint64_t force_fcs:1; ++ uint64_t fcs:1; ++ uint64_t pad:1; ++ uint64_t preamble:1; ++ } s; ++ struct cvmx_gmxx_txx_append_s cn30xx; ++ struct cvmx_gmxx_txx_append_s cn31xx; ++ struct cvmx_gmxx_txx_append_s cn38xx; ++ struct cvmx_gmxx_txx_append_s cn38xxp2; ++ struct cvmx_gmxx_txx_append_s cn50xx; ++ struct cvmx_gmxx_txx_append_s cn52xx; ++ struct cvmx_gmxx_txx_append_s cn52xxp1; ++ struct cvmx_gmxx_txx_append_s cn56xx; ++ struct cvmx_gmxx_txx_append_s cn56xxp1; ++ struct cvmx_gmxx_txx_append_s cn58xx; ++ struct cvmx_gmxx_txx_append_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_burst { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_burst_s { ++ uint64_t reserved_16_63:48; ++ uint64_t burst:16; ++ } s; ++ struct cvmx_gmxx_txx_burst_s cn30xx; ++ struct cvmx_gmxx_txx_burst_s cn31xx; ++ struct cvmx_gmxx_txx_burst_s cn38xx; ++ struct cvmx_gmxx_txx_burst_s cn38xxp2; ++ struct cvmx_gmxx_txx_burst_s cn50xx; ++ struct cvmx_gmxx_txx_burst_s cn52xx; ++ struct cvmx_gmxx_txx_burst_s cn52xxp1; ++ struct cvmx_gmxx_txx_burst_s cn56xx; ++ struct cvmx_gmxx_txx_burst_s cn56xxp1; ++ struct cvmx_gmxx_txx_burst_s cn58xx; ++ struct cvmx_gmxx_txx_burst_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_cbfc_xoff { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_cbfc_xoff_s { ++ uint64_t reserved_16_63:48; ++ uint64_t xoff:16; ++ } s; ++ struct cvmx_gmxx_txx_cbfc_xoff_s cn52xx; ++ struct cvmx_gmxx_txx_cbfc_xoff_s cn56xx; ++}; ++ ++union cvmx_gmxx_txx_cbfc_xon { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_cbfc_xon_s { ++ uint64_t reserved_16_63:48; ++ uint64_t xon:16; ++ } s; ++ struct cvmx_gmxx_txx_cbfc_xon_s cn52xx; ++ struct cvmx_gmxx_txx_cbfc_xon_s cn56xx; ++}; ++ ++union cvmx_gmxx_txx_clk { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_clk_s { ++ uint64_t reserved_6_63:58; ++ uint64_t clk_cnt:6; ++ } s; ++ struct cvmx_gmxx_txx_clk_s cn30xx; ++ struct cvmx_gmxx_txx_clk_s cn31xx; ++ struct cvmx_gmxx_txx_clk_s cn38xx; ++ struct cvmx_gmxx_txx_clk_s cn38xxp2; ++ struct cvmx_gmxx_txx_clk_s cn50xx; ++ struct cvmx_gmxx_txx_clk_s cn58xx; ++ struct cvmx_gmxx_txx_clk_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_ctl_s { ++ uint64_t reserved_2_63:62; ++ uint64_t xsdef_en:1; ++ uint64_t xscol_en:1; ++ } s; ++ struct cvmx_gmxx_txx_ctl_s cn30xx; ++ struct cvmx_gmxx_txx_ctl_s cn31xx; ++ struct cvmx_gmxx_txx_ctl_s cn38xx; ++ struct cvmx_gmxx_txx_ctl_s cn38xxp2; ++ struct cvmx_gmxx_txx_ctl_s cn50xx; ++ struct cvmx_gmxx_txx_ctl_s cn52xx; ++ struct cvmx_gmxx_txx_ctl_s cn52xxp1; ++ struct cvmx_gmxx_txx_ctl_s cn56xx; ++ struct cvmx_gmxx_txx_ctl_s cn56xxp1; ++ struct cvmx_gmxx_txx_ctl_s cn58xx; ++ struct cvmx_gmxx_txx_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_min_pkt { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_min_pkt_s { ++ uint64_t reserved_8_63:56; ++ uint64_t min_size:8; ++ } s; ++ struct cvmx_gmxx_txx_min_pkt_s cn30xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn31xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn38xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn38xxp2; ++ struct cvmx_gmxx_txx_min_pkt_s cn50xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn52xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn52xxp1; ++ struct cvmx_gmxx_txx_min_pkt_s cn56xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn56xxp1; ++ struct cvmx_gmxx_txx_min_pkt_s cn58xx; ++ struct cvmx_gmxx_txx_min_pkt_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_pause_pkt_interval { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s { ++ uint64_t reserved_16_63:48; ++ uint64_t interval:16; ++ } s; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn30xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn31xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn38xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn38xxp2; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn50xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn52xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn52xxp1; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn56xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn56xxp1; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn58xx; ++ struct cvmx_gmxx_txx_pause_pkt_interval_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_pause_pkt_time { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_pause_pkt_time_s { ++ uint64_t reserved_16_63:48; ++ uint64_t time:16; ++ } s; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn30xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn31xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn38xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn38xxp2; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn50xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn52xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn52xxp1; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn56xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn56xxp1; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn58xx; ++ struct cvmx_gmxx_txx_pause_pkt_time_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_pause_togo { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_pause_togo_s { ++ uint64_t reserved_32_63:32; ++ uint64_t msg_time:16; ++ uint64_t time:16; ++ } s; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx { ++ uint64_t reserved_16_63:48; ++ uint64_t time:16; ++ } cn30xx; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn31xx; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn38xx; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn38xxp2; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn50xx; ++ struct cvmx_gmxx_txx_pause_togo_s cn52xx; ++ struct cvmx_gmxx_txx_pause_togo_s cn52xxp1; ++ struct cvmx_gmxx_txx_pause_togo_s cn56xx; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn56xxp1; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn58xx; ++ struct cvmx_gmxx_txx_pause_togo_cn30xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_pause_zero { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_pause_zero_s { ++ uint64_t reserved_1_63:63; ++ uint64_t send:1; ++ } s; ++ struct cvmx_gmxx_txx_pause_zero_s cn30xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn31xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn38xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn38xxp2; ++ struct cvmx_gmxx_txx_pause_zero_s cn50xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn52xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn52xxp1; ++ struct cvmx_gmxx_txx_pause_zero_s cn56xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn56xxp1; ++ struct cvmx_gmxx_txx_pause_zero_s cn58xx; ++ struct cvmx_gmxx_txx_pause_zero_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_sgmii_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_sgmii_ctl_s { ++ uint64_t reserved_1_63:63; ++ uint64_t align:1; ++ } s; ++ struct cvmx_gmxx_txx_sgmii_ctl_s cn52xx; ++ struct cvmx_gmxx_txx_sgmii_ctl_s cn52xxp1; ++ struct cvmx_gmxx_txx_sgmii_ctl_s cn56xx; ++ struct cvmx_gmxx_txx_sgmii_ctl_s cn56xxp1; ++}; ++ ++union cvmx_gmxx_txx_slot { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_slot_s { ++ uint64_t reserved_10_63:54; ++ uint64_t slot:10; ++ } s; ++ struct cvmx_gmxx_txx_slot_s cn30xx; ++ struct cvmx_gmxx_txx_slot_s cn31xx; ++ struct cvmx_gmxx_txx_slot_s cn38xx; ++ struct cvmx_gmxx_txx_slot_s cn38xxp2; ++ struct cvmx_gmxx_txx_slot_s cn50xx; ++ struct cvmx_gmxx_txx_slot_s cn52xx; ++ struct cvmx_gmxx_txx_slot_s cn52xxp1; ++ struct cvmx_gmxx_txx_slot_s cn56xx; ++ struct cvmx_gmxx_txx_slot_s cn56xxp1; ++ struct cvmx_gmxx_txx_slot_s cn58xx; ++ struct cvmx_gmxx_txx_slot_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_soft_pause { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_soft_pause_s { ++ uint64_t reserved_16_63:48; ++ uint64_t time:16; ++ } s; ++ struct cvmx_gmxx_txx_soft_pause_s cn30xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn31xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn38xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn38xxp2; ++ struct cvmx_gmxx_txx_soft_pause_s cn50xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn52xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn52xxp1; ++ struct cvmx_gmxx_txx_soft_pause_s cn56xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn56xxp1; ++ struct cvmx_gmxx_txx_soft_pause_s cn58xx; ++ struct cvmx_gmxx_txx_soft_pause_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat0 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat0_s { ++ uint64_t xsdef:32; ++ uint64_t xscol:32; ++ } s; ++ struct cvmx_gmxx_txx_stat0_s cn30xx; ++ struct cvmx_gmxx_txx_stat0_s cn31xx; ++ struct cvmx_gmxx_txx_stat0_s cn38xx; ++ struct cvmx_gmxx_txx_stat0_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat0_s cn50xx; ++ struct cvmx_gmxx_txx_stat0_s cn52xx; ++ struct cvmx_gmxx_txx_stat0_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat0_s cn56xx; ++ struct cvmx_gmxx_txx_stat0_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat0_s cn58xx; ++ struct cvmx_gmxx_txx_stat0_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat1 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat1_s { ++ uint64_t scol:32; ++ uint64_t mcol:32; ++ } s; ++ struct cvmx_gmxx_txx_stat1_s cn30xx; ++ struct cvmx_gmxx_txx_stat1_s cn31xx; ++ struct cvmx_gmxx_txx_stat1_s cn38xx; ++ struct cvmx_gmxx_txx_stat1_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat1_s cn50xx; ++ struct cvmx_gmxx_txx_stat1_s cn52xx; ++ struct cvmx_gmxx_txx_stat1_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat1_s cn56xx; ++ struct cvmx_gmxx_txx_stat1_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat1_s cn58xx; ++ struct cvmx_gmxx_txx_stat1_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat2 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat2_s { ++ uint64_t reserved_48_63:16; ++ uint64_t octs:48; ++ } s; ++ struct cvmx_gmxx_txx_stat2_s cn30xx; ++ struct cvmx_gmxx_txx_stat2_s cn31xx; ++ struct cvmx_gmxx_txx_stat2_s cn38xx; ++ struct cvmx_gmxx_txx_stat2_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat2_s cn50xx; ++ struct cvmx_gmxx_txx_stat2_s cn52xx; ++ struct cvmx_gmxx_txx_stat2_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat2_s cn56xx; ++ struct cvmx_gmxx_txx_stat2_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat2_s cn58xx; ++ struct cvmx_gmxx_txx_stat2_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat3 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat3_s { ++ uint64_t reserved_32_63:32; ++ uint64_t pkts:32; ++ } s; ++ struct cvmx_gmxx_txx_stat3_s cn30xx; ++ struct cvmx_gmxx_txx_stat3_s cn31xx; ++ struct cvmx_gmxx_txx_stat3_s cn38xx; ++ struct cvmx_gmxx_txx_stat3_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat3_s cn50xx; ++ struct cvmx_gmxx_txx_stat3_s cn52xx; ++ struct cvmx_gmxx_txx_stat3_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat3_s cn56xx; ++ struct cvmx_gmxx_txx_stat3_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat3_s cn58xx; ++ struct cvmx_gmxx_txx_stat3_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat4 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat4_s { ++ uint64_t hist1:32; ++ uint64_t hist0:32; ++ } s; ++ struct cvmx_gmxx_txx_stat4_s cn30xx; ++ struct cvmx_gmxx_txx_stat4_s cn31xx; ++ struct cvmx_gmxx_txx_stat4_s cn38xx; ++ struct cvmx_gmxx_txx_stat4_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat4_s cn50xx; ++ struct cvmx_gmxx_txx_stat4_s cn52xx; ++ struct cvmx_gmxx_txx_stat4_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat4_s cn56xx; ++ struct cvmx_gmxx_txx_stat4_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat4_s cn58xx; ++ struct cvmx_gmxx_txx_stat4_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat5 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat5_s { ++ uint64_t hist3:32; ++ uint64_t hist2:32; ++ } s; ++ struct cvmx_gmxx_txx_stat5_s cn30xx; ++ struct cvmx_gmxx_txx_stat5_s cn31xx; ++ struct cvmx_gmxx_txx_stat5_s cn38xx; ++ struct cvmx_gmxx_txx_stat5_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat5_s cn50xx; ++ struct cvmx_gmxx_txx_stat5_s cn52xx; ++ struct cvmx_gmxx_txx_stat5_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat5_s cn56xx; ++ struct cvmx_gmxx_txx_stat5_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat5_s cn58xx; ++ struct cvmx_gmxx_txx_stat5_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat6 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat6_s { ++ uint64_t hist5:32; ++ uint64_t hist4:32; ++ } s; ++ struct cvmx_gmxx_txx_stat6_s cn30xx; ++ struct cvmx_gmxx_txx_stat6_s cn31xx; ++ struct cvmx_gmxx_txx_stat6_s cn38xx; ++ struct cvmx_gmxx_txx_stat6_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat6_s cn50xx; ++ struct cvmx_gmxx_txx_stat6_s cn52xx; ++ struct cvmx_gmxx_txx_stat6_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat6_s cn56xx; ++ struct cvmx_gmxx_txx_stat6_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat6_s cn58xx; ++ struct cvmx_gmxx_txx_stat6_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat7 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat7_s { ++ uint64_t hist7:32; ++ uint64_t hist6:32; ++ } s; ++ struct cvmx_gmxx_txx_stat7_s cn30xx; ++ struct cvmx_gmxx_txx_stat7_s cn31xx; ++ struct cvmx_gmxx_txx_stat7_s cn38xx; ++ struct cvmx_gmxx_txx_stat7_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat7_s cn50xx; ++ struct cvmx_gmxx_txx_stat7_s cn52xx; ++ struct cvmx_gmxx_txx_stat7_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat7_s cn56xx; ++ struct cvmx_gmxx_txx_stat7_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat7_s cn58xx; ++ struct cvmx_gmxx_txx_stat7_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat8 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat8_s { ++ uint64_t mcst:32; ++ uint64_t bcst:32; ++ } s; ++ struct cvmx_gmxx_txx_stat8_s cn30xx; ++ struct cvmx_gmxx_txx_stat8_s cn31xx; ++ struct cvmx_gmxx_txx_stat8_s cn38xx; ++ struct cvmx_gmxx_txx_stat8_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat8_s cn50xx; ++ struct cvmx_gmxx_txx_stat8_s cn52xx; ++ struct cvmx_gmxx_txx_stat8_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat8_s cn56xx; ++ struct cvmx_gmxx_txx_stat8_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat8_s cn58xx; ++ struct cvmx_gmxx_txx_stat8_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stat9 { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stat9_s { ++ uint64_t undflw:32; ++ uint64_t ctl:32; ++ } s; ++ struct cvmx_gmxx_txx_stat9_s cn30xx; ++ struct cvmx_gmxx_txx_stat9_s cn31xx; ++ struct cvmx_gmxx_txx_stat9_s cn38xx; ++ struct cvmx_gmxx_txx_stat9_s cn38xxp2; ++ struct cvmx_gmxx_txx_stat9_s cn50xx; ++ struct cvmx_gmxx_txx_stat9_s cn52xx; ++ struct cvmx_gmxx_txx_stat9_s cn52xxp1; ++ struct cvmx_gmxx_txx_stat9_s cn56xx; ++ struct cvmx_gmxx_txx_stat9_s cn56xxp1; ++ struct cvmx_gmxx_txx_stat9_s cn58xx; ++ struct cvmx_gmxx_txx_stat9_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_stats_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_stats_ctl_s { ++ uint64_t reserved_1_63:63; ++ uint64_t rd_clr:1; ++ } s; ++ struct cvmx_gmxx_txx_stats_ctl_s cn30xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn31xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn38xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn38xxp2; ++ struct cvmx_gmxx_txx_stats_ctl_s cn50xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn52xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn52xxp1; ++ struct cvmx_gmxx_txx_stats_ctl_s cn56xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn56xxp1; ++ struct cvmx_gmxx_txx_stats_ctl_s cn58xx; ++ struct cvmx_gmxx_txx_stats_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_txx_thresh { ++ uint64_t u64; ++ struct cvmx_gmxx_txx_thresh_s { ++ uint64_t reserved_9_63:55; ++ uint64_t cnt:9; ++ } s; ++ struct cvmx_gmxx_txx_thresh_cn30xx { ++ uint64_t reserved_7_63:57; ++ uint64_t cnt:7; ++ } cn30xx; ++ struct cvmx_gmxx_txx_thresh_cn30xx cn31xx; ++ struct cvmx_gmxx_txx_thresh_s cn38xx; ++ struct cvmx_gmxx_txx_thresh_s cn38xxp2; ++ struct cvmx_gmxx_txx_thresh_cn30xx cn50xx; ++ struct cvmx_gmxx_txx_thresh_s cn52xx; ++ struct cvmx_gmxx_txx_thresh_s cn52xxp1; ++ struct cvmx_gmxx_txx_thresh_s cn56xx; ++ struct cvmx_gmxx_txx_thresh_s cn56xxp1; ++ struct cvmx_gmxx_txx_thresh_s cn58xx; ++ struct cvmx_gmxx_txx_thresh_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_bp { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_bp_s { ++ uint64_t reserved_4_63:60; ++ uint64_t bp:4; ++ } s; ++ struct cvmx_gmxx_tx_bp_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t bp:3; ++ } cn30xx; ++ struct cvmx_gmxx_tx_bp_cn30xx cn31xx; ++ struct cvmx_gmxx_tx_bp_s cn38xx; ++ struct cvmx_gmxx_tx_bp_s cn38xxp2; ++ struct cvmx_gmxx_tx_bp_cn30xx cn50xx; ++ struct cvmx_gmxx_tx_bp_s cn52xx; ++ struct cvmx_gmxx_tx_bp_s cn52xxp1; ++ struct cvmx_gmxx_tx_bp_s cn56xx; ++ struct cvmx_gmxx_tx_bp_s cn56xxp1; ++ struct cvmx_gmxx_tx_bp_s cn58xx; ++ struct cvmx_gmxx_tx_bp_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_clk_mskx { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_clk_mskx_s { ++ uint64_t reserved_1_63:63; ++ uint64_t msk:1; ++ } s; ++ struct cvmx_gmxx_tx_clk_mskx_s cn30xx; ++ struct cvmx_gmxx_tx_clk_mskx_s cn50xx; ++}; ++ ++union cvmx_gmxx_tx_col_attempt { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_col_attempt_s { ++ uint64_t reserved_5_63:59; ++ uint64_t limit:5; ++ } s; ++ struct cvmx_gmxx_tx_col_attempt_s cn30xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn31xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn38xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn38xxp2; ++ struct cvmx_gmxx_tx_col_attempt_s cn50xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn52xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn52xxp1; ++ struct cvmx_gmxx_tx_col_attempt_s cn56xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn56xxp1; ++ struct cvmx_gmxx_tx_col_attempt_s cn58xx; ++ struct cvmx_gmxx_tx_col_attempt_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_corrupt { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_corrupt_s { ++ uint64_t reserved_4_63:60; ++ uint64_t corrupt:4; ++ } s; ++ struct cvmx_gmxx_tx_corrupt_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t corrupt:3; ++ } cn30xx; ++ struct cvmx_gmxx_tx_corrupt_cn30xx cn31xx; ++ struct cvmx_gmxx_tx_corrupt_s cn38xx; ++ struct cvmx_gmxx_tx_corrupt_s cn38xxp2; ++ struct cvmx_gmxx_tx_corrupt_cn30xx cn50xx; ++ struct cvmx_gmxx_tx_corrupt_s cn52xx; ++ struct cvmx_gmxx_tx_corrupt_s cn52xxp1; ++ struct cvmx_gmxx_tx_corrupt_s cn56xx; ++ struct cvmx_gmxx_tx_corrupt_s cn56xxp1; ++ struct cvmx_gmxx_tx_corrupt_s cn58xx; ++ struct cvmx_gmxx_tx_corrupt_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_hg2_reg1 { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_hg2_reg1_s { ++ uint64_t reserved_16_63:48; ++ uint64_t tx_xof:16; ++ } s; ++ struct cvmx_gmxx_tx_hg2_reg1_s cn52xx; ++ struct cvmx_gmxx_tx_hg2_reg1_s cn52xxp1; ++ struct cvmx_gmxx_tx_hg2_reg1_s cn56xx; ++}; ++ ++union cvmx_gmxx_tx_hg2_reg2 { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_hg2_reg2_s { ++ uint64_t reserved_16_63:48; ++ uint64_t tx_xon:16; ++ } s; ++ struct cvmx_gmxx_tx_hg2_reg2_s cn52xx; ++ struct cvmx_gmxx_tx_hg2_reg2_s cn52xxp1; ++ struct cvmx_gmxx_tx_hg2_reg2_s cn56xx; ++}; ++ ++union cvmx_gmxx_tx_ifg { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_ifg_s { ++ uint64_t reserved_8_63:56; ++ uint64_t ifg2:4; ++ uint64_t ifg1:4; ++ } s; ++ struct cvmx_gmxx_tx_ifg_s cn30xx; ++ struct cvmx_gmxx_tx_ifg_s cn31xx; ++ struct cvmx_gmxx_tx_ifg_s cn38xx; ++ struct cvmx_gmxx_tx_ifg_s cn38xxp2; ++ struct cvmx_gmxx_tx_ifg_s cn50xx; ++ struct cvmx_gmxx_tx_ifg_s cn52xx; ++ struct cvmx_gmxx_tx_ifg_s cn52xxp1; ++ struct cvmx_gmxx_tx_ifg_s cn56xx; ++ struct cvmx_gmxx_tx_ifg_s cn56xxp1; ++ struct cvmx_gmxx_tx_ifg_s cn58xx; ++ struct cvmx_gmxx_tx_ifg_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_int_en { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_int_en_s { ++ uint64_t reserved_20_63:44; ++ uint64_t late_col:4; ++ uint64_t xsdef:4; ++ uint64_t xscol:4; ++ uint64_t reserved_6_7:2; ++ uint64_t undflw:4; ++ uint64_t ncb_nxa:1; ++ uint64_t pko_nxa:1; ++ } s; ++ struct cvmx_gmxx_tx_int_en_cn30xx { ++ uint64_t reserved_19_63:45; ++ uint64_t late_col:3; ++ uint64_t reserved_15_15:1; ++ uint64_t xsdef:3; ++ uint64_t reserved_11_11:1; ++ uint64_t xscol:3; ++ uint64_t reserved_5_7:3; ++ uint64_t undflw:3; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn30xx; ++ struct cvmx_gmxx_tx_int_en_cn31xx { ++ uint64_t reserved_15_63:49; ++ uint64_t xsdef:3; ++ uint64_t reserved_11_11:1; ++ uint64_t xscol:3; ++ uint64_t reserved_5_7:3; ++ uint64_t undflw:3; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn31xx; ++ struct cvmx_gmxx_tx_int_en_s cn38xx; ++ struct cvmx_gmxx_tx_int_en_cn38xxp2 { ++ uint64_t reserved_16_63:48; ++ uint64_t xsdef:4; ++ uint64_t xscol:4; ++ uint64_t reserved_6_7:2; ++ uint64_t undflw:4; ++ uint64_t ncb_nxa:1; ++ uint64_t pko_nxa:1; ++ } cn38xxp2; ++ struct cvmx_gmxx_tx_int_en_cn30xx cn50xx; ++ struct cvmx_gmxx_tx_int_en_cn52xx { ++ uint64_t reserved_20_63:44; ++ uint64_t late_col:4; ++ uint64_t xsdef:4; ++ uint64_t xscol:4; ++ uint64_t reserved_6_7:2; ++ uint64_t undflw:4; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn52xx; ++ struct cvmx_gmxx_tx_int_en_cn52xx cn52xxp1; ++ struct cvmx_gmxx_tx_int_en_cn52xx cn56xx; ++ struct cvmx_gmxx_tx_int_en_cn52xx cn56xxp1; ++ struct cvmx_gmxx_tx_int_en_s cn58xx; ++ struct cvmx_gmxx_tx_int_en_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_int_reg { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_int_reg_s { ++ uint64_t reserved_20_63:44; ++ uint64_t late_col:4; ++ uint64_t xsdef:4; ++ uint64_t xscol:4; ++ uint64_t reserved_6_7:2; ++ uint64_t undflw:4; ++ uint64_t ncb_nxa:1; ++ uint64_t pko_nxa:1; ++ } s; ++ struct cvmx_gmxx_tx_int_reg_cn30xx { ++ uint64_t reserved_19_63:45; ++ uint64_t late_col:3; ++ uint64_t reserved_15_15:1; ++ uint64_t xsdef:3; ++ uint64_t reserved_11_11:1; ++ uint64_t xscol:3; ++ uint64_t reserved_5_7:3; ++ uint64_t undflw:3; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn30xx; ++ struct cvmx_gmxx_tx_int_reg_cn31xx { ++ uint64_t reserved_15_63:49; ++ uint64_t xsdef:3; ++ uint64_t reserved_11_11:1; ++ uint64_t xscol:3; ++ uint64_t reserved_5_7:3; ++ uint64_t undflw:3; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn31xx; ++ struct cvmx_gmxx_tx_int_reg_s cn38xx; ++ struct cvmx_gmxx_tx_int_reg_cn38xxp2 { ++ uint64_t reserved_16_63:48; ++ uint64_t xsdef:4; ++ uint64_t xscol:4; ++ uint64_t reserved_6_7:2; ++ uint64_t undflw:4; ++ uint64_t ncb_nxa:1; ++ uint64_t pko_nxa:1; ++ } cn38xxp2; ++ struct cvmx_gmxx_tx_int_reg_cn30xx cn50xx; ++ struct cvmx_gmxx_tx_int_reg_cn52xx { ++ uint64_t reserved_20_63:44; ++ uint64_t late_col:4; ++ uint64_t xsdef:4; ++ uint64_t xscol:4; ++ uint64_t reserved_6_7:2; ++ uint64_t undflw:4; ++ uint64_t reserved_1_1:1; ++ uint64_t pko_nxa:1; ++ } cn52xx; ++ struct cvmx_gmxx_tx_int_reg_cn52xx cn52xxp1; ++ struct cvmx_gmxx_tx_int_reg_cn52xx cn56xx; ++ struct cvmx_gmxx_tx_int_reg_cn52xx cn56xxp1; ++ struct cvmx_gmxx_tx_int_reg_s cn58xx; ++ struct cvmx_gmxx_tx_int_reg_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_jam { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_jam_s { ++ uint64_t reserved_8_63:56; ++ uint64_t jam:8; ++ } s; ++ struct cvmx_gmxx_tx_jam_s cn30xx; ++ struct cvmx_gmxx_tx_jam_s cn31xx; ++ struct cvmx_gmxx_tx_jam_s cn38xx; ++ struct cvmx_gmxx_tx_jam_s cn38xxp2; ++ struct cvmx_gmxx_tx_jam_s cn50xx; ++ struct cvmx_gmxx_tx_jam_s cn52xx; ++ struct cvmx_gmxx_tx_jam_s cn52xxp1; ++ struct cvmx_gmxx_tx_jam_s cn56xx; ++ struct cvmx_gmxx_tx_jam_s cn56xxp1; ++ struct cvmx_gmxx_tx_jam_s cn58xx; ++ struct cvmx_gmxx_tx_jam_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_lfsr { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_lfsr_s { ++ uint64_t reserved_16_63:48; ++ uint64_t lfsr:16; ++ } s; ++ struct cvmx_gmxx_tx_lfsr_s cn30xx; ++ struct cvmx_gmxx_tx_lfsr_s cn31xx; ++ struct cvmx_gmxx_tx_lfsr_s cn38xx; ++ struct cvmx_gmxx_tx_lfsr_s cn38xxp2; ++ struct cvmx_gmxx_tx_lfsr_s cn50xx; ++ struct cvmx_gmxx_tx_lfsr_s cn52xx; ++ struct cvmx_gmxx_tx_lfsr_s cn52xxp1; ++ struct cvmx_gmxx_tx_lfsr_s cn56xx; ++ struct cvmx_gmxx_tx_lfsr_s cn56xxp1; ++ struct cvmx_gmxx_tx_lfsr_s cn58xx; ++ struct cvmx_gmxx_tx_lfsr_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_ovr_bp { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_ovr_bp_s { ++ uint64_t reserved_48_63:16; ++ uint64_t tx_prt_bp:16; ++ uint64_t reserved_12_31:20; ++ uint64_t en:4; ++ uint64_t bp:4; ++ uint64_t ign_full:4; ++ } s; ++ struct cvmx_gmxx_tx_ovr_bp_cn30xx { ++ uint64_t reserved_11_63:53; ++ uint64_t en:3; ++ uint64_t reserved_7_7:1; ++ uint64_t bp:3; ++ uint64_t reserved_3_3:1; ++ uint64_t ign_full:3; ++ } cn30xx; ++ struct cvmx_gmxx_tx_ovr_bp_cn30xx cn31xx; ++ struct cvmx_gmxx_tx_ovr_bp_cn38xx { ++ uint64_t reserved_12_63:52; ++ uint64_t en:4; ++ uint64_t bp:4; ++ uint64_t ign_full:4; ++ } cn38xx; ++ struct cvmx_gmxx_tx_ovr_bp_cn38xx cn38xxp2; ++ struct cvmx_gmxx_tx_ovr_bp_cn30xx cn50xx; ++ struct cvmx_gmxx_tx_ovr_bp_s cn52xx; ++ struct cvmx_gmxx_tx_ovr_bp_s cn52xxp1; ++ struct cvmx_gmxx_tx_ovr_bp_s cn56xx; ++ struct cvmx_gmxx_tx_ovr_bp_s cn56xxp1; ++ struct cvmx_gmxx_tx_ovr_bp_cn38xx cn58xx; ++ struct cvmx_gmxx_tx_ovr_bp_cn38xx cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_pause_pkt_dmac { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s { ++ uint64_t reserved_48_63:16; ++ uint64_t dmac:48; ++ } s; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn30xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn31xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn38xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn38xxp2; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn50xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn52xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn52xxp1; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn56xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn56xxp1; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn58xx; ++ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_pause_pkt_type { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_pause_pkt_type_s { ++ uint64_t reserved_16_63:48; ++ uint64_t type:16; ++ } s; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn30xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn31xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn38xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn38xxp2; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn50xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn52xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn52xxp1; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn56xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn56xxp1; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn58xx; ++ struct cvmx_gmxx_tx_pause_pkt_type_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_prts { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_prts_s { ++ uint64_t reserved_5_63:59; ++ uint64_t prts:5; ++ } s; ++ struct cvmx_gmxx_tx_prts_s cn30xx; ++ struct cvmx_gmxx_tx_prts_s cn31xx; ++ struct cvmx_gmxx_tx_prts_s cn38xx; ++ struct cvmx_gmxx_tx_prts_s cn38xxp2; ++ struct cvmx_gmxx_tx_prts_s cn50xx; ++ struct cvmx_gmxx_tx_prts_s cn52xx; ++ struct cvmx_gmxx_tx_prts_s cn52xxp1; ++ struct cvmx_gmxx_tx_prts_s cn56xx; ++ struct cvmx_gmxx_tx_prts_s cn56xxp1; ++ struct cvmx_gmxx_tx_prts_s cn58xx; ++ struct cvmx_gmxx_tx_prts_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_spi_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_spi_ctl_s { ++ uint64_t reserved_2_63:62; ++ uint64_t tpa_clr:1; ++ uint64_t cont_pkt:1; ++ } s; ++ struct cvmx_gmxx_tx_spi_ctl_s cn38xx; ++ struct cvmx_gmxx_tx_spi_ctl_s cn38xxp2; ++ struct cvmx_gmxx_tx_spi_ctl_s cn58xx; ++ struct cvmx_gmxx_tx_spi_ctl_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_spi_drain { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_spi_drain_s { ++ uint64_t reserved_16_63:48; ++ uint64_t drain:16; ++ } s; ++ struct cvmx_gmxx_tx_spi_drain_s cn38xx; ++ struct cvmx_gmxx_tx_spi_drain_s cn58xx; ++ struct cvmx_gmxx_tx_spi_drain_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_spi_max { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_spi_max_s { ++ uint64_t reserved_23_63:41; ++ uint64_t slice:7; ++ uint64_t max2:8; ++ uint64_t max1:8; ++ } s; ++ struct cvmx_gmxx_tx_spi_max_cn38xx { ++ uint64_t reserved_16_63:48; ++ uint64_t max2:8; ++ uint64_t max1:8; ++ } cn38xx; ++ struct cvmx_gmxx_tx_spi_max_cn38xx cn38xxp2; ++ struct cvmx_gmxx_tx_spi_max_s cn58xx; ++ struct cvmx_gmxx_tx_spi_max_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_spi_roundx { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_spi_roundx_s { ++ uint64_t reserved_16_63:48; ++ uint64_t round:16; ++ } s; ++ struct cvmx_gmxx_tx_spi_roundx_s cn58xx; ++ struct cvmx_gmxx_tx_spi_roundx_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_spi_thresh { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_spi_thresh_s { ++ uint64_t reserved_6_63:58; ++ uint64_t thresh:6; ++ } s; ++ struct cvmx_gmxx_tx_spi_thresh_s cn38xx; ++ struct cvmx_gmxx_tx_spi_thresh_s cn38xxp2; ++ struct cvmx_gmxx_tx_spi_thresh_s cn58xx; ++ struct cvmx_gmxx_tx_spi_thresh_s cn58xxp1; ++}; ++ ++union cvmx_gmxx_tx_xaui_ctl { ++ uint64_t u64; ++ struct cvmx_gmxx_tx_xaui_ctl_s { ++ uint64_t reserved_11_63:53; ++ uint64_t hg_pause_hgi:2; ++ uint64_t hg_en:1; ++ uint64_t reserved_7_7:1; ++ uint64_t ls_byp:1; ++ uint64_t ls:2; ++ uint64_t reserved_2_3:2; ++ uint64_t uni_en:1; ++ uint64_t dic_en:1; ++ } s; ++ struct cvmx_gmxx_tx_xaui_ctl_s cn52xx; ++ struct cvmx_gmxx_tx_xaui_ctl_s cn52xxp1; ++ struct cvmx_gmxx_tx_xaui_ctl_s cn56xx; ++ struct cvmx_gmxx_tx_xaui_ctl_s cn56xxp1; ++}; ++ ++union cvmx_gmxx_xaui_ext_loopback { ++ uint64_t u64; ++ struct cvmx_gmxx_xaui_ext_loopback_s { ++ uint64_t reserved_5_63:59; ++ uint64_t en:1; ++ uint64_t thresh:4; ++ } s; ++ struct cvmx_gmxx_xaui_ext_loopback_s cn52xx; ++ struct cvmx_gmxx_xaui_ext_loopback_s cn52xxp1; ++ struct cvmx_gmxx_xaui_ext_loopback_s cn56xx; ++ struct cvmx_gmxx_xaui_ext_loopback_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-board.c +@@ -0,0 +1,706 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Helper functions to abstract board specific data about ++ * network ports from the rest of the cvmx-helper files. ++ */ ++ ++#include ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-mdio.h" ++ ++#include "cvmx-helper.h" ++#include "cvmx-helper-util.h" ++#include "cvmx-helper-board.h" ++ ++#include "cvmx-gmxx-defs.h" ++#include "cvmx-asxx-defs.h" ++ ++/** ++ * cvmx_override_board_link_get(int ipd_port) is a function ++ * pointer. It is meant to allow customization of the process of ++ * talking to a PHY to determine link speed. It is called every ++ * time a PHY must be polled for link status. Users should set ++ * this pointer to a function before calling any cvmx-helper ++ * operations. ++ */ ++cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port) = ++ NULL; ++ ++/** ++ * Return the MII PHY address associated with the given IPD ++ * port. A result of -1 means there isn't a MII capable PHY ++ * connected to this port. On chips supporting multiple MII ++ * busses the bus number is encoded in bits <15:8>. ++ * ++ * This function must be modified for every new Octeon board. ++ * Internally it uses switch statements based on the cvmx_sysinfo ++ * data to determine board types and revisions. It replies on the ++ * fact that every Octeon board receives a unique board type ++ * enumeration from the bootloader. ++ * ++ * @ipd_port: Octeon IPD port to get the MII address for. ++ * ++ * Returns MII PHY address and bus number or -1. ++ */ ++int cvmx_helper_board_get_mii_address(int ipd_port) ++{ ++ switch (cvmx_sysinfo_get()->board_type) { ++ case CVMX_BOARD_TYPE_SIM: ++ /* Simulator doesn't have MII */ ++ return -1; ++ case CVMX_BOARD_TYPE_EBT3000: ++ case CVMX_BOARD_TYPE_EBT5800: ++ case CVMX_BOARD_TYPE_THUNDER: ++ case CVMX_BOARD_TYPE_NICPRO2: ++ /* Interface 0 is SPI4, interface 1 is RGMII */ ++ if ((ipd_port >= 16) && (ipd_port < 20)) ++ return ipd_port - 16; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_KODAMA: ++ case CVMX_BOARD_TYPE_EBH3100: ++ case CVMX_BOARD_TYPE_HIKARI: ++ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: ++ case CVMX_BOARD_TYPE_CN3020_EVB_HS5: ++ /* ++ * Port 0 is WAN connected to a PHY, Port 1 is GMII ++ * connected to a switch ++ */ ++ if (ipd_port == 0) ++ return 4; ++ else if (ipd_port == 1) ++ return 9; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_NAC38: ++ /* Board has 8 RGMII ports PHYs are 0-7 */ ++ if ((ipd_port >= 0) && (ipd_port < 4)) ++ return ipd_port; ++ else if ((ipd_port >= 16) && (ipd_port < 20)) ++ return ipd_port - 16 + 4; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_EBH3000: ++ /* Board has dual SPI4 and no PHYs */ ++ return -1; ++ case CVMX_BOARD_TYPE_EBH5200: ++ case CVMX_BOARD_TYPE_EBH5201: ++ case CVMX_BOARD_TYPE_EBT5200: ++ /* ++ * Board has 4 SGMII ports. The PHYs start right after the MII ++ * ports MII0 = 0, MII1 = 1, SGMII = 2-5. ++ */ ++ if ((ipd_port >= 0) && (ipd_port < 4)) ++ return ipd_port + 2; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_EBH5600: ++ case CVMX_BOARD_TYPE_EBH5601: ++ case CVMX_BOARD_TYPE_EBH5610: ++ /* ++ * Board has 8 SGMII ports. 4 connect out, two connect ++ * to a switch, and 2 loop to each other ++ */ ++ if ((ipd_port >= 0) && (ipd_port < 4)) ++ return ipd_port + 1; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_CUST_NB5: ++ if (ipd_port == 2) ++ return 4; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_NIC_XLE_4G: ++ /* Board has 4 SGMII ports. connected QLM3(interface 1) */ ++ if ((ipd_port >= 16) && (ipd_port < 20)) ++ return ipd_port - 16 + 1; ++ else ++ return -1; ++ case CVMX_BOARD_TYPE_BBGW_REF: ++ /* ++ * No PHYs are connected to Octeon, everything is ++ * through switch. ++ */ ++ return -1; ++ } ++ ++ /* Some unknown board. Somebody forgot to update this function... */ ++ cvmx_dprintf ++ ("cvmx_helper_board_get_mii_address: Unknown board type %d\n", ++ cvmx_sysinfo_get()->board_type); ++ return -1; ++} ++ ++/** ++ * This function is the board specific method of determining an ++ * ethernet ports link speed. Most Octeon boards have Marvell PHYs ++ * and are handled by the fall through case. This function must be ++ * updated for boards that don't have the normal Marvell PHYs. ++ * ++ * This function must be modified for every new Octeon board. ++ * Internally it uses switch statements based on the cvmx_sysinfo ++ * data to determine board types and revisions. It relies on the ++ * fact that every Octeon board receives a unique board type ++ * enumeration from the bootloader. ++ * ++ * @ipd_port: IPD input port associated with the port we want to get link ++ * status for. ++ * ++ * Returns The ports link status. If the link isn't fully resolved, this must ++ * return zero. ++ */ ++cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) ++{ ++ cvmx_helper_link_info_t result; ++ int phy_addr; ++ int is_broadcom_phy = 0; ++ ++ /* Give the user a chance to override the processing of this function */ ++ if (cvmx_override_board_link_get) ++ return cvmx_override_board_link_get(ipd_port); ++ ++ /* Unless we fix it later, all links are defaulted to down */ ++ result.u64 = 0; ++ ++ /* ++ * This switch statement should handle all ports that either don't use ++ * Marvell PHYS, or don't support in-band status. ++ */ ++ switch (cvmx_sysinfo_get()->board_type) { ++ case CVMX_BOARD_TYPE_SIM: ++ /* The simulator gives you a simulated 1Gbps full duplex link */ ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ return result; ++ case CVMX_BOARD_TYPE_EBH3100: ++ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: ++ case CVMX_BOARD_TYPE_CN3020_EVB_HS5: ++ /* Port 1 on these boards is always Gigabit */ ++ if (ipd_port == 1) { ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ return result; ++ } ++ /* Fall through to the generic code below */ ++ break; ++ case CVMX_BOARD_TYPE_CUST_NB5: ++ /* Port 1 on these boards is always Gigabit */ ++ if (ipd_port == 1) { ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ return result; ++ } else /* The other port uses a broadcom PHY */ ++ is_broadcom_phy = 1; ++ break; ++ case CVMX_BOARD_TYPE_BBGW_REF: ++ /* Port 1 on these boards is always Gigabit */ ++ if (ipd_port == 2) { ++ /* Port 2 is not hooked up */ ++ result.u64 = 0; ++ return result; ++ } else { ++ /* Ports 0 and 1 connect to the switch */ ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ return result; ++ } ++ break; ++ } ++ ++ phy_addr = cvmx_helper_board_get_mii_address(ipd_port); ++ if (phy_addr != -1) { ++ if (is_broadcom_phy) { ++ /* ++ * Below we are going to read SMI/MDIO ++ * register 0x19 which works on Broadcom ++ * parts ++ */ ++ int phy_status = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ 0x19); ++ switch ((phy_status >> 8) & 0x7) { ++ case 0: ++ result.u64 = 0; ++ break; ++ case 1: ++ result.s.link_up = 1; ++ result.s.full_duplex = 0; ++ result.s.speed = 10; ++ break; ++ case 2: ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 10; ++ break; ++ case 3: ++ result.s.link_up = 1; ++ result.s.full_duplex = 0; ++ result.s.speed = 100; ++ break; ++ case 4: ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 100; ++ break; ++ case 5: ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 100; ++ break; ++ case 6: ++ result.s.link_up = 1; ++ result.s.full_duplex = 0; ++ result.s.speed = 1000; ++ break; ++ case 7: ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ break; ++ } ++ } else { ++ /* ++ * This code assumes we are using a Marvell ++ * Gigabit PHY. All the speed information can ++ * be read from register 17 in one ++ * go. Somebody using a different PHY will ++ * need to handle it above in the board ++ * specific area. ++ */ ++ int phy_status = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); ++ ++ /* ++ * If the resolve bit 11 isn't set, see if ++ * autoneg is turned off (bit 12, reg 0). The ++ * resolve bit doesn't get set properly when ++ * autoneg is off, so force it. ++ */ ++ if ((phy_status & (1 << 11)) == 0) { ++ int auto_status = ++ cvmx_mdio_read(phy_addr >> 8, ++ phy_addr & 0xff, 0); ++ if ((auto_status & (1 << 12)) == 0) ++ phy_status |= 1 << 11; ++ } ++ ++ /* ++ * Only return a link if the PHY has finished ++ * auto negotiation and set the resolved bit ++ * (bit 11) ++ */ ++ if (phy_status & (1 << 11)) { ++ result.s.link_up = 1; ++ result.s.full_duplex = ((phy_status >> 13) & 1); ++ switch ((phy_status >> 14) & 3) { ++ case 0: /* 10 Mbps */ ++ result.s.speed = 10; ++ break; ++ case 1: /* 100 Mbps */ ++ result.s.speed = 100; ++ break; ++ case 2: /* 1 Gbps */ ++ result.s.speed = 1000; ++ break; ++ case 3: /* Illegal */ ++ result.u64 = 0; ++ break; ++ } ++ } ++ } ++ } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ /* ++ * We don't have a PHY address, so attempt to use ++ * in-band status. It is really important that boards ++ * not supporting in-band status never get ++ * here. Reading broken in-band status tends to do bad ++ * things ++ */ ++ union cvmx_gmxx_rxx_rx_inbnd inband_status; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ inband_status.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); ++ ++ result.s.link_up = inband_status.s.status; ++ result.s.full_duplex = inband_status.s.duplex; ++ switch (inband_status.s.speed) { ++ case 0: /* 10 Mbps */ ++ result.s.speed = 10; ++ break; ++ case 1: /* 100 Mbps */ ++ result.s.speed = 100; ++ break; ++ case 2: /* 1 Gbps */ ++ result.s.speed = 1000; ++ break; ++ case 3: /* Illegal */ ++ result.u64 = 0; ++ break; ++ } ++ } else { ++ /* ++ * We don't have a PHY address and we don't have ++ * in-band status. There is no way to determine the ++ * link speed. Return down assuming this port isn't ++ * wired ++ */ ++ result.u64 = 0; ++ } ++ ++ /* If link is down, return all fields as zero. */ ++ if (!result.s.link_up) ++ result.u64 = 0; ++ ++ return result; ++} ++ ++/** ++ * This function as a board specific method of changing the PHY ++ * speed, duplex, and auto-negotiation. This programs the PHY and ++ * not Octeon. This can be used to force Octeon's links to ++ * specific settings. ++ * ++ * @phy_addr: The address of the PHY to program ++ * @enable_autoneg: ++ * Non zero if you want to enable auto-negotiation. ++ * @link_info: Link speed to program. If the speed is zero and auto-negotiation ++ * is enabled, all possible negotiation speeds are advertised. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_helper_board_link_set_phy(int phy_addr, ++ cvmx_helper_board_set_phy_link_flags_types_t ++ link_flags, ++ cvmx_helper_link_info_t link_info) ++{ ++ ++ /* Set the flow control settings based on link_flags */ ++ if ((link_flags & set_phy_link_flags_flow_control_mask) != ++ set_phy_link_flags_flow_control_dont_touch) { ++ cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; ++ reg_autoneg_adver.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_AUTONEG_ADVER); ++ reg_autoneg_adver.s.asymmetric_pause = ++ (link_flags & set_phy_link_flags_flow_control_mask) == ++ set_phy_link_flags_flow_control_enable; ++ reg_autoneg_adver.s.pause = ++ (link_flags & set_phy_link_flags_flow_control_mask) == ++ set_phy_link_flags_flow_control_enable; ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_AUTONEG_ADVER, ++ reg_autoneg_adver.u16); ++ } ++ ++ /* If speed isn't set and autoneg is on advertise all supported modes */ ++ if ((link_flags & set_phy_link_flags_autoneg) ++ && (link_info.s.speed == 0)) { ++ cvmx_mdio_phy_reg_control_t reg_control; ++ cvmx_mdio_phy_reg_status_t reg_status; ++ cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; ++ cvmx_mdio_phy_reg_extended_status_t reg_extended_status; ++ cvmx_mdio_phy_reg_control_1000_t reg_control_1000; ++ ++ reg_status.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_STATUS); ++ reg_autoneg_adver.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_AUTONEG_ADVER); ++ reg_autoneg_adver.s.advert_100base_t4 = ++ reg_status.s.capable_100base_t4; ++ reg_autoneg_adver.s.advert_10base_tx_full = ++ reg_status.s.capable_10_full; ++ reg_autoneg_adver.s.advert_10base_tx_half = ++ reg_status.s.capable_10_half; ++ reg_autoneg_adver.s.advert_100base_tx_full = ++ reg_status.s.capable_100base_x_full; ++ reg_autoneg_adver.s.advert_100base_tx_half = ++ reg_status.s.capable_100base_x_half; ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_AUTONEG_ADVER, ++ reg_autoneg_adver.u16); ++ if (reg_status.s.capable_extended_status) { ++ reg_extended_status.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_EXTENDED_STATUS); ++ reg_control_1000.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL_1000); ++ reg_control_1000.s.advert_1000base_t_full = ++ reg_extended_status.s.capable_1000base_t_full; ++ reg_control_1000.s.advert_1000base_t_half = ++ reg_extended_status.s.capable_1000base_t_half; ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL_1000, ++ reg_control_1000.u16); ++ } ++ reg_control.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL); ++ reg_control.s.autoneg_enable = 1; ++ reg_control.s.restart_autoneg = 1; ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); ++ } else if ((link_flags & set_phy_link_flags_autoneg)) { ++ cvmx_mdio_phy_reg_control_t reg_control; ++ cvmx_mdio_phy_reg_status_t reg_status; ++ cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; ++ cvmx_mdio_phy_reg_extended_status_t reg_extended_status; ++ cvmx_mdio_phy_reg_control_1000_t reg_control_1000; ++ ++ reg_status.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_STATUS); ++ reg_autoneg_adver.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_AUTONEG_ADVER); ++ reg_autoneg_adver.s.advert_100base_t4 = 0; ++ reg_autoneg_adver.s.advert_10base_tx_full = 0; ++ reg_autoneg_adver.s.advert_10base_tx_half = 0; ++ reg_autoneg_adver.s.advert_100base_tx_full = 0; ++ reg_autoneg_adver.s.advert_100base_tx_half = 0; ++ if (reg_status.s.capable_extended_status) { ++ reg_extended_status.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_EXTENDED_STATUS); ++ reg_control_1000.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL_1000); ++ reg_control_1000.s.advert_1000base_t_full = 0; ++ reg_control_1000.s.advert_1000base_t_half = 0; ++ } ++ switch (link_info.s.speed) { ++ case 10: ++ reg_autoneg_adver.s.advert_10base_tx_full = ++ link_info.s.full_duplex; ++ reg_autoneg_adver.s.advert_10base_tx_half = ++ !link_info.s.full_duplex; ++ break; ++ case 100: ++ reg_autoneg_adver.s.advert_100base_tx_full = ++ link_info.s.full_duplex; ++ reg_autoneg_adver.s.advert_100base_tx_half = ++ !link_info.s.full_duplex; ++ break; ++ case 1000: ++ reg_control_1000.s.advert_1000base_t_full = ++ link_info.s.full_duplex; ++ reg_control_1000.s.advert_1000base_t_half = ++ !link_info.s.full_duplex; ++ break; ++ } ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_AUTONEG_ADVER, ++ reg_autoneg_adver.u16); ++ if (reg_status.s.capable_extended_status) ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL_1000, ++ reg_control_1000.u16); ++ reg_control.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL); ++ reg_control.s.autoneg_enable = 1; ++ reg_control.s.restart_autoneg = 1; ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); ++ } else { ++ cvmx_mdio_phy_reg_control_t reg_control; ++ reg_control.u16 = ++ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL); ++ reg_control.s.autoneg_enable = 0; ++ reg_control.s.restart_autoneg = 1; ++ reg_control.s.duplex = link_info.s.full_duplex; ++ if (link_info.s.speed == 1000) { ++ reg_control.s.speed_msb = 1; ++ reg_control.s.speed_lsb = 0; ++ } else if (link_info.s.speed == 100) { ++ reg_control.s.speed_msb = 0; ++ reg_control.s.speed_lsb = 1; ++ } else if (link_info.s.speed == 10) { ++ reg_control.s.speed_msb = 0; ++ reg_control.s.speed_lsb = 0; ++ } ++ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, ++ CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); ++ } ++ return 0; ++} ++ ++/** ++ * This function is called by cvmx_helper_interface_probe() after it ++ * determines the number of ports Octeon can support on a specific ++ * interface. This function is the per board location to override ++ * this value. It is called with the number of ports Octeon might ++ * support and should return the number of actual ports on the ++ * board. ++ * ++ * This function must be modifed for every new Octeon board. ++ * Internally it uses switch statements based on the cvmx_sysinfo ++ * data to determine board types and revisions. It relys on the ++ * fact that every Octeon board receives a unique board type ++ * enumeration from the bootloader. ++ * ++ * @interface: Interface to probe ++ * @supported_ports: ++ * Number of ports Octeon supports. ++ * ++ * Returns Number of ports the actual board supports. Many times this will ++ * simple be "support_ports". ++ */ ++int __cvmx_helper_board_interface_probe(int interface, int supported_ports) ++{ ++ switch (cvmx_sysinfo_get()->board_type) { ++ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: ++ if (interface == 0) ++ return 2; ++ break; ++ case CVMX_BOARD_TYPE_BBGW_REF: ++ if (interface == 0) ++ return 2; ++ break; ++ case CVMX_BOARD_TYPE_NIC_XLE_4G: ++ if (interface == 0) ++ return 0; ++ break; ++ /* The 2nd interface on the EBH5600 is connected to the Marvel switch, ++ which we don't support. Disable ports connected to it */ ++ case CVMX_BOARD_TYPE_EBH5600: ++ if (interface == 1) ++ return 0; ++ break; ++ } ++ return supported_ports; ++} ++ ++/** ++ * Enable packet input/output from the hardware. This function is ++ * called after by cvmx_helper_packet_hardware_enable() to ++ * perform board specific initialization. For most boards ++ * nothing is needed. ++ * ++ * @interface: Interface to enable ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_board_hardware_enable(int interface) ++{ ++ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) { ++ if (interface == 0) { ++ /* Different config for switch port */ ++ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); ++ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); ++ /* ++ * Boards with gigabit WAN ports need a ++ * different setting that is compatible with ++ * 100 Mbit settings ++ */ ++ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), ++ 0xc); ++ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), ++ 0xc); ++ } ++ } else if (cvmx_sysinfo_get()->board_type == ++ CVMX_BOARD_TYPE_CN3010_EVB_HS5) { ++ /* ++ * Broadcom PHYs require differnet ASX ++ * clocks. Unfortunately many boards don't define a ++ * new board Id and simply mangle the ++ * CN3010_EVB_HS5 ++ */ ++ if (interface == 0) { ++ /* ++ * Some boards use a hacked up bootloader that ++ * identifies them as CN3010_EVB_HS5 ++ * evaluation boards. This leads to all kinds ++ * of configuration problems. Detect one ++ * case, and print warning, while trying to do ++ * the right thing. ++ */ ++ int phy_addr = cvmx_helper_board_get_mii_address(0); ++ if (phy_addr != -1) { ++ int phy_identifier = ++ cvmx_mdio_read(phy_addr >> 8, ++ phy_addr & 0xff, 0x2); ++ /* Is it a Broadcom PHY? */ ++ if (phy_identifier == 0x0143) { ++ cvmx_dprintf("\n"); ++ cvmx_dprintf("ERROR:\n"); ++ cvmx_dprintf ++ ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); ++ cvmx_dprintf ++ ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); ++ cvmx_dprintf ++ ("ERROR: All boards require a unique board type to identify them.\n"); ++ cvmx_dprintf("ERROR:\n"); ++ cvmx_dprintf("\n"); ++ cvmx_wait(1000000000); ++ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX ++ (0, interface), 5); ++ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX ++ (0, interface), 5); ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) ++{ ++ switch (cvmx_sysinfo_get()->board_type) { ++ case CVMX_BOARD_TYPE_BBGW_REF: ++ return USB_CLOCK_TYPE_CRYSTAL_12; ++ } ++ return USB_CLOCK_TYPE_REF_48; ++} ++ ++int __cvmx_helper_board_usb_get_num_ports(int supported_ports) ++{ ++ switch (cvmx_sysinfo_get()->board_type) { ++ case CVMX_BOARD_TYPE_NIC_XLE_4G: ++ return 0; ++ } ++ ++ return supported_ports; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-board.h +@@ -0,0 +1,180 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Helper functions to abstract board specific data about ++ * network ports from the rest of the cvmx-helper files. ++ * ++ */ ++#ifndef __CVMX_HELPER_BOARD_H__ ++#define __CVMX_HELPER_BOARD_H__ ++ ++#include "cvmx-helper.h" ++ ++typedef enum { ++ USB_CLOCK_TYPE_REF_12, ++ USB_CLOCK_TYPE_REF_24, ++ USB_CLOCK_TYPE_REF_48, ++ USB_CLOCK_TYPE_CRYSTAL_12, ++} cvmx_helper_board_usb_clock_types_t; ++ ++typedef enum { ++ set_phy_link_flags_autoneg = 0x1, ++ set_phy_link_flags_flow_control_dont_touch = 0x0 << 1, ++ set_phy_link_flags_flow_control_enable = 0x1 << 1, ++ set_phy_link_flags_flow_control_disable = 0x2 << 1, ++ set_phy_link_flags_flow_control_mask = 0x3 << 1, /* Mask for 2 bit wide flow control field */ ++} cvmx_helper_board_set_phy_link_flags_types_t; ++ ++/** ++ * cvmx_override_board_link_get(int ipd_port) is a function ++ * pointer. It is meant to allow customization of the process of ++ * talking to a PHY to determine link speed. It is called every ++ * time a PHY must be polled for link status. Users should set ++ * this pointer to a function before calling any cvmx-helper ++ * operations. ++ */ ++extern cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port); ++ ++/** ++ * Return the MII PHY address associated with the given IPD ++ * port. A result of -1 means there isn't a MII capable PHY ++ * connected to this port. On chips supporting multiple MII ++ * busses the bus number is encoded in bits <15:8>. ++ * ++ * This function must be modifed for every new Octeon board. ++ * Internally it uses switch statements based on the cvmx_sysinfo ++ * data to determine board types and revisions. It relys on the ++ * fact that every Octeon board receives a unique board type ++ * enumeration from the bootloader. ++ * ++ * @ipd_port: Octeon IPD port to get the MII address for. ++ * ++ * Returns MII PHY address and bus number or -1. ++ */ ++extern int cvmx_helper_board_get_mii_address(int ipd_port); ++ ++/** ++ * This function as a board specific method of changing the PHY ++ * speed, duplex, and autonegotiation. This programs the PHY and ++ * not Octeon. This can be used to force Octeon's links to ++ * specific settings. ++ * ++ * @phy_addr: The address of the PHY to program ++ * @link_flags: ++ * Flags to control autonegotiation. Bit 0 is autonegotiation ++ * enable/disable to maintain backware compatability. ++ * @link_info: Link speed to program. If the speed is zero and autonegotiation ++ * is enabled, all possible negotiation speeds are advertised. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_helper_board_link_set_phy(int phy_addr, ++ cvmx_helper_board_set_phy_link_flags_types_t ++ link_flags, ++ cvmx_helper_link_info_t link_info); ++ ++/** ++ * This function is the board specific method of determining an ++ * ethernet ports link speed. Most Octeon boards have Marvell PHYs ++ * and are handled by the fall through case. This function must be ++ * updated for boards that don't have the normal Marvell PHYs. ++ * ++ * This function must be modifed for every new Octeon board. ++ * Internally it uses switch statements based on the cvmx_sysinfo ++ * data to determine board types and revisions. It relys on the ++ * fact that every Octeon board receives a unique board type ++ * enumeration from the bootloader. ++ * ++ * @ipd_port: IPD input port associated with the port we want to get link ++ * status for. ++ * ++ * Returns The ports link status. If the link isn't fully resolved, this must ++ * return zero. ++ */ ++extern cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port); ++ ++/** ++ * This function is called by cvmx_helper_interface_probe() after it ++ * determines the number of ports Octeon can support on a specific ++ * interface. This function is the per board location to override ++ * this value. It is called with the number of ports Octeon might ++ * support and should return the number of actual ports on the ++ * board. ++ * ++ * This function must be modifed for every new Octeon board. ++ * Internally it uses switch statements based on the cvmx_sysinfo ++ * data to determine board types and revisions. It relys on the ++ * fact that every Octeon board receives a unique board type ++ * enumeration from the bootloader. ++ * ++ * @interface: Interface to probe ++ * @supported_ports: ++ * Number of ports Octeon supports. ++ * ++ * Returns Number of ports the actual board supports. Many times this will ++ * simple be "support_ports". ++ */ ++extern int __cvmx_helper_board_interface_probe(int interface, ++ int supported_ports); ++ ++/** ++ * Enable packet input/output from the hardware. This function is ++ * called after by cvmx_helper_packet_hardware_enable() to ++ * perform board specific initialization. For most boards ++ * nothing is needed. ++ * ++ * @interface: Interface to enable ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_board_hardware_enable(int interface); ++ ++/** ++ * Gets the clock type used for the USB block based on board type. ++ * Used by the USB code for auto configuration of clock type. ++ * ++ * Returns USB clock type enumeration ++ */ ++cvmx_helper_board_usb_clock_types_t ++__cvmx_helper_board_usb_get_clock_type(void); ++ ++/** ++ * Adjusts the number of available USB ports on Octeon based on board ++ * specifics. ++ * ++ * @supported_ports: expected number of ports based on chip type; ++ * ++ * ++ * Returns number of available usb ports, based on board specifics. ++ * Return value is supported_ports if function does not ++ * override. ++ */ ++int __cvmx_helper_board_usb_get_num_ports(int supported_ports); ++ ++#endif /* __CVMX_HELPER_BOARD_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-fpa.c +@@ -0,0 +1,243 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Helper functions for FPA setup. ++ * ++ */ ++#include "executive-config.h" ++#include "cvmx-config.h" ++#include "cvmx.h" ++#include "cvmx-bootmem.h" ++#include "cvmx-fpa.h" ++#include "cvmx-helper-fpa.h" ++ ++/** ++ * Allocate memory for and initialize a single FPA pool. ++ * ++ * @pool: Pool to initialize ++ * @buffer_size: Size of buffers to allocate in bytes ++ * @buffers: Number of buffers to put in the pool. Zero is allowed ++ * @name: String name of the pool for debugging purposes ++ * Returns Zero on success, non-zero on failure ++ */ ++static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size, ++ uint64_t buffers, const char *name) ++{ ++ uint64_t current_num; ++ void *memory; ++ uint64_t align = CVMX_CACHE_LINE_SIZE; ++ ++ /* ++ * Align the allocation so that power of 2 size buffers are ++ * naturally aligned. ++ */ ++ while (align < buffer_size) ++ align = align << 1; ++ ++ if (buffers == 0) ++ return 0; ++ ++ current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool)); ++ if (current_num) { ++ cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. " ++ "Skipping setup.\n", ++ pool, name, (unsigned long long)current_num); ++ return 0; ++ } ++ ++ memory = cvmx_bootmem_alloc(buffer_size * buffers, align); ++ if (memory == NULL) { ++ cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n", ++ pool, name); ++ return -1; ++ } ++ cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers); ++ return 0; ++} ++ ++/** ++ * Allocate memory and initialize the FPA pools using memory ++ * from cvmx-bootmem. Specifying zero for the number of ++ * buffers will cause that FPA pool to not be setup. This is ++ * useful if you aren't using some of the hardware and want ++ * to save memory. Use cvmx_helper_initialize_fpa instead of ++ * this function directly. ++ * ++ * @pip_pool: Should always be CVMX_FPA_PACKET_POOL ++ * @pip_size: Should always be CVMX_FPA_PACKET_POOL_SIZE ++ * @pip_buffers: ++ * Number of packet buffers. ++ * @wqe_pool: Should always be CVMX_FPA_WQE_POOL ++ * @wqe_size: Should always be CVMX_FPA_WQE_POOL_SIZE ++ * @wqe_entries: ++ * Number of work queue entries ++ * @pko_pool: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL ++ * @pko_size: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE ++ * @pko_buffers: ++ * PKO Command buffers. You should at minimum have two per ++ * each PKO queue. ++ * @tim_pool: Should always be CVMX_FPA_TIMER_POOL ++ * @tim_size: Should always be CVMX_FPA_TIMER_POOL_SIZE ++ * @tim_buffers: ++ * TIM ring buffer command queues. At least two per timer bucket ++ * is recommened. ++ * @dfa_pool: Should always be CVMX_FPA_DFA_POOL ++ * @dfa_size: Should always be CVMX_FPA_DFA_POOL_SIZE ++ * @dfa_buffers: ++ * DFA command buffer. A relatively small (32 for example) ++ * number should work. ++ * Returns Zero on success, non-zero if out of memory ++ */ ++static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size, ++ int pip_buffers, int wqe_pool, ++ int wqe_size, int wqe_entries, ++ int pko_pool, int pko_size, ++ int pko_buffers, int tim_pool, ++ int tim_size, int tim_buffers, ++ int dfa_pool, int dfa_size, ++ int dfa_buffers) ++{ ++ int status; ++ ++ cvmx_fpa_enable(); ++ ++ if ((pip_buffers > 0) && (pip_buffers <= 64)) ++ cvmx_dprintf ++ ("Warning: %d packet buffers may not be enough for hardware" ++ " prefetch. 65 or more is recommended.\n", pip_buffers); ++ ++ if (pip_pool >= 0) { ++ status = ++ __cvmx_helper_initialize_fpa_pool(pip_pool, pip_size, ++ pip_buffers, ++ "Packet Buffers"); ++ if (status) ++ return status; ++ } ++ ++ if (wqe_pool >= 0) { ++ status = ++ __cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size, ++ wqe_entries, ++ "Work Queue Entries"); ++ if (status) ++ return status; ++ } ++ ++ if (pko_pool >= 0) { ++ status = ++ __cvmx_helper_initialize_fpa_pool(pko_pool, pko_size, ++ pko_buffers, ++ "PKO Command Buffers"); ++ if (status) ++ return status; ++ } ++ ++ if (tim_pool >= 0) { ++ status = ++ __cvmx_helper_initialize_fpa_pool(tim_pool, tim_size, ++ tim_buffers, ++ "TIM Command Buffers"); ++ if (status) ++ return status; ++ } ++ ++ if (dfa_pool >= 0) { ++ status = ++ __cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size, ++ dfa_buffers, ++ "DFA Command Buffers"); ++ if (status) ++ return status; ++ } ++ ++ return 0; ++} ++ ++/** ++ * Allocate memory and initialize the FPA pools using memory ++ * from cvmx-bootmem. Sizes of each element in the pools is ++ * controlled by the cvmx-config.h header file. Specifying ++ * zero for any parameter will cause that FPA pool to not be ++ * setup. This is useful if you aren't using some of the ++ * hardware and want to save memory. ++ * ++ * @packet_buffers: ++ * Number of packet buffers to allocate ++ * @work_queue_entries: ++ * Number of work queue entries ++ * @pko_buffers: ++ * PKO Command buffers. You should at minimum have two per ++ * each PKO queue. ++ * @tim_buffers: ++ * TIM ring buffer command queues. At least two per timer bucket ++ * is recommened. ++ * @dfa_buffers: ++ * DFA command buffer. A relatively small (32 for example) ++ * number should work. ++ * Returns Zero on success, non-zero if out of memory ++ */ ++int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries, ++ int pko_buffers, int tim_buffers, ++ int dfa_buffers) ++{ ++#ifndef CVMX_FPA_PACKET_POOL ++#define CVMX_FPA_PACKET_POOL -1 ++#define CVMX_FPA_PACKET_POOL_SIZE 0 ++#endif ++#ifndef CVMX_FPA_WQE_POOL ++#define CVMX_FPA_WQE_POOL -1 ++#define CVMX_FPA_WQE_POOL_SIZE 0 ++#endif ++#ifndef CVMX_FPA_OUTPUT_BUFFER_POOL ++#define CVMX_FPA_OUTPUT_BUFFER_POOL -1 ++#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0 ++#endif ++#ifndef CVMX_FPA_TIMER_POOL ++#define CVMX_FPA_TIMER_POOL -1 ++#define CVMX_FPA_TIMER_POOL_SIZE 0 ++#endif ++#ifndef CVMX_FPA_DFA_POOL ++#define CVMX_FPA_DFA_POOL -1 ++#define CVMX_FPA_DFA_POOL_SIZE 0 ++#endif ++ return __cvmx_helper_initialize_fpa(CVMX_FPA_PACKET_POOL, ++ CVMX_FPA_PACKET_POOL_SIZE, ++ packet_buffers, CVMX_FPA_WQE_POOL, ++ CVMX_FPA_WQE_POOL_SIZE, ++ work_queue_entries, ++ CVMX_FPA_OUTPUT_BUFFER_POOL, ++ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, ++ pko_buffers, CVMX_FPA_TIMER_POOL, ++ CVMX_FPA_TIMER_POOL_SIZE, ++ tim_buffers, CVMX_FPA_DFA_POOL, ++ CVMX_FPA_DFA_POOL_SIZE, ++ dfa_buffers); ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-fpa.h +@@ -0,0 +1,64 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Helper functions for FPA setup. ++ * ++ */ ++#ifndef __CVMX_HELPER_H_FPA__ ++#define __CVMX_HELPER_H_FPA__ ++ ++/** ++ * Allocate memory and initialize the FPA pools using memory ++ * from cvmx-bootmem. Sizes of each element in the pools is ++ * controlled by the cvmx-config.h header file. Specifying ++ * zero for any parameter will cause that FPA pool to not be ++ * setup. This is useful if you aren't using some of the ++ * hardware and want to save memory. ++ * ++ * @packet_buffers: ++ * Number of packet buffers to allocate ++ * @work_queue_entries: ++ * Number of work queue entries ++ * @pko_buffers: ++ * PKO Command buffers. You should at minimum have two per ++ * each PKO queue. ++ * @tim_buffers: ++ * TIM ring buffer command queues. At least two per timer bucket ++ * is recommened. ++ * @dfa_buffers: ++ * DFA command buffer. A relatively small (32 for example) ++ * number should work. ++ * Returns Zero on success, non-zero if out of memory ++ */ ++extern int cvmx_helper_initialize_fpa(int packet_buffers, ++ int work_queue_entries, int pko_buffers, ++ int tim_buffers, int dfa_buffers); ++ ++#endif /* __CVMX_HELPER_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-loop.c +@@ -0,0 +1,85 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Functions for LOOP initialization, configuration, ++ * and monitoring. ++ */ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-helper.h" ++#include "cvmx-pip-defs.h" ++ ++/** ++ * Probe a LOOP interface and determine the number of ports ++ * connected to it. The LOOP interface should still be down ++ * after this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++int __cvmx_helper_loop_probe(int interface) ++{ ++ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; ++ int num_ports = 4; ++ int port; ++ ++ /* We need to disable length checking so packet < 64 bytes and jumbo ++ frames don't get errors */ ++ for (port = 0; port < num_ports; port++) { ++ union cvmx_pip_prt_cfgx port_cfg; ++ int ipd_port = cvmx_helper_get_ipd_port(interface, port); ++ port_cfg.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); ++ port_cfg.s.maxerr_en = 0; ++ port_cfg.s.minerr_en = 0; ++ cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_cfg.u64); ++ } ++ ++ /* Disable FCS stripping for loopback ports */ ++ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); ++ ipd_sub_port_fcs.s.port_bit2 = 0; ++ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); ++ return num_ports; ++} ++ ++/** ++ * Bringup and enable a LOOP interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_loop_enable(int interface) ++{ ++ /* Do nothing. */ ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-loop.h +@@ -0,0 +1,59 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as published by ++ * the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. ++ * See the GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Functions for LOOP initialization, configuration, ++ * and monitoring. ++ * ++ */ ++#ifndef __CVMX_HELPER_LOOP_H__ ++#define __CVMX_HELPER_LOOP_H__ ++ ++/** ++ * Probe a LOOP interface and determine the number of ports ++ * connected to it. The LOOP interface should still be down after ++ * this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++extern int __cvmx_helper_loop_probe(int interface); ++ ++/** ++ * Bringup and enable a LOOP interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_loop_enable(int interface); ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-npi.c +@@ -0,0 +1,113 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Functions for NPI initialization, configuration, ++ * and monitoring. ++ */ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-helper.h" ++ ++#include "cvmx-pip-defs.h" ++ ++/** ++ * Probe a NPI interface and determine the number of ports ++ * connected to it. The NPI interface should still be down ++ * after this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++int __cvmx_helper_npi_probe(int interface) ++{ ++#if CVMX_PKO_QUEUES_PER_PORT_PCI > 0 ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) ++ return 4; ++ else if (OCTEON_IS_MODEL(OCTEON_CN56XX) ++ && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ++ /* The packet engines didn't exist before pass 2 */ ++ return 4; ++ else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ++ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) ++ /* The packet engines didn't exist before pass 2 */ ++ return 4; ++#if 0 ++ /* ++ * Technically CN30XX, CN31XX, and CN50XX contain packet ++ * engines, but nobody ever uses them. Since this is the case, ++ * we disable them here. ++ */ ++ else if (OCTEON_IS_MODEL(OCTEON_CN31XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)) ++ return 2; ++ else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) ++ return 1; ++#endif ++#endif ++ return 0; ++} ++ ++/** ++ * Bringup and enable a NPI interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_npi_enable(int interface) ++{ ++ /* ++ * On CN50XX, CN52XX, and CN56XX we need to disable length ++ * checking so packet < 64 bytes and jumbo frames don't get ++ * errors. ++ */ ++ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && ++ !OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ int num_ports = cvmx_helper_ports_on_interface(interface); ++ int port; ++ for (port = 0; port < num_ports; port++) { ++ union cvmx_pip_prt_cfgx port_cfg; ++ int ipd_port = ++ cvmx_helper_get_ipd_port(interface, port); ++ port_cfg.u64 = ++ cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); ++ port_cfg.s.maxerr_en = 0; ++ port_cfg.s.minerr_en = 0; ++ cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), ++ port_cfg.u64); ++ } ++ } ++ ++ /* Enables are controlled by the remote host, so nothing to do here */ ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-npi.h +@@ -0,0 +1,60 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Functions for NPI initialization, configuration, ++ * and monitoring. ++ * ++ */ ++#ifndef __CVMX_HELPER_NPI_H__ ++#define __CVMX_HELPER_NPI_H__ ++ ++/** ++ * Probe a NPI interface and determine the number of ports ++ * connected to it. The NPI interface should still be down after ++ * this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++extern int __cvmx_helper_npi_probe(int interface); ++ ++/** ++ * Bringup and enable a NPI interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_npi_enable(int interface); ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-rgmii.c +@@ -0,0 +1,525 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Functions for RGMII/GMII/MII initialization, configuration, ++ * and monitoring. ++ */ ++#include ++ ++#include "cvmx-config.h" ++ ++ ++#include "cvmx-mdio.h" ++#include "cvmx-pko.h" ++#include "cvmx-helper.h" ++#include "cvmx-helper-board.h" ++ ++#include ++#include "cvmx-gmxx-defs.h" ++#include "cvmx-asxx-defs.h" ++#include "cvmx-dbg-defs.h" ++ ++void __cvmx_interrupt_gmxx_enable(int interface); ++void __cvmx_interrupt_asxx_enable(int block); ++ ++/** ++ * Probe RGMII ports and determine the number present ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of RGMII/GMII/MII ports (0-4). ++ */ ++int __cvmx_helper_rgmii_probe(int interface) ++{ ++ int num_ports = 0; ++ union cvmx_gmxx_inf_mode mode; ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ ++ if (mode.s.type) { ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ cvmx_dprintf("ERROR: RGMII initialize called in " ++ "SPI interface\n"); ++ } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) ++ || OCTEON_IS_MODEL(OCTEON_CN30XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ /* ++ * On these chips "type" says we're in ++ * GMII/MII mode. This limits us to 2 ports ++ */ ++ num_ports = 2; ++ } else { ++ cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", ++ __func__); ++ } ++ } else { ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ num_ports = 4; ++ } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) ++ || OCTEON_IS_MODEL(OCTEON_CN30XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ num_ports = 3; ++ } else { ++ cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", ++ __func__); ++ } ++ } ++ return num_ports; ++} ++ ++/** ++ * Put an RGMII interface in loopback mode. Internal packets sent ++ * out will be received back again on the same port. Externally ++ * received packets will echo back out. ++ * ++ * @port: IPD port number to loop. ++ */ ++void cvmx_helper_rgmii_internal_loopback(int port) ++{ ++ int interface = (port >> 4) & 1; ++ int index = port & 0xf; ++ uint64_t tmp; ++ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ gmx_cfg.u64 = 0; ++ gmx_cfg.s.duplex = 1; ++ gmx_cfg.s.slottime = 1; ++ gmx_cfg.s.speed = 1; ++ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ tmp = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); ++ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), (1 << index) | tmp); ++ tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface)); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), (1 << index) | tmp); ++ tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), (1 << index) | tmp); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++} ++ ++/** ++ * Workaround ASX setup errata with CN38XX pass1 ++ * ++ * @interface: Interface to setup ++ * @port: Port to setup (0..3) ++ * @cpu_clock_hz: ++ * Chip frequency in Hertz ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_errata_asx_pass1(int interface, int port, ++ int cpu_clock_hz) ++{ ++ /* Set hi water mark as per errata GMX-4 */ ++ if (cpu_clock_hz >= 325000000 && cpu_clock_hz < 375000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 12); ++ else if (cpu_clock_hz >= 375000000 && cpu_clock_hz < 437000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 11); ++ else if (cpu_clock_hz >= 437000000 && cpu_clock_hz < 550000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 10); ++ else if (cpu_clock_hz >= 550000000 && cpu_clock_hz < 687000000) ++ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 9); ++ else ++ cvmx_dprintf("Illegal clock frequency (%d). " ++ "CVMX_ASXX_TX_HI_WATERX not set\n", cpu_clock_hz); ++ return 0; ++} ++ ++/** ++ * Configure all of the ASX, GMX, and PKO regsiters required ++ * to get RGMII to function on the supplied interface. ++ * ++ * @interface: PKO Interface to configure (0 or 1) ++ * ++ * Returns Zero on success ++ */ ++int __cvmx_helper_rgmii_enable(int interface) ++{ ++ int num_ports = cvmx_helper_ports_on_interface(interface); ++ int port; ++ struct cvmx_sysinfo *sys_info_ptr = cvmx_sysinfo_get(); ++ union cvmx_gmxx_inf_mode mode; ++ union cvmx_asxx_tx_prt_en asx_tx; ++ union cvmx_asxx_rx_prt_en asx_rx; ++ ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ ++ if (mode.s.en == 0) ++ return -1; ++ if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || ++ OCTEON_IS_MODEL(OCTEON_CN58XX)) && mode.s.type == 1) ++ /* Ignore SPI interfaces */ ++ return -1; ++ ++ /* Configure the ASX registers needed to use the RGMII ports */ ++ asx_tx.u64 = 0; ++ asx_tx.s.prt_en = cvmx_build_mask(num_ports); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), asx_tx.u64); ++ ++ asx_rx.u64 = 0; ++ asx_rx.s.prt_en = cvmx_build_mask(num_ports); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), asx_rx.u64); ++ ++ /* Configure the GMX registers needed to use the RGMII ports */ ++ for (port = 0; port < num_ports; port++) { ++ /* Setting of CVMX_GMXX_TXX_THRESH has been moved to ++ __cvmx_helper_setup_gmx() */ ++ ++ if (cvmx_octeon_is_pass1()) ++ __cvmx_helper_errata_asx_pass1(interface, port, ++ sys_info_ptr-> ++ cpu_clock_hz); ++ else { ++ /* ++ * Configure more flexible RGMII preamble ++ * checking. Pass 1 doesn't support this ++ * feature. ++ */ ++ union cvmx_gmxx_rxx_frm_ctl frm_ctl; ++ frm_ctl.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL ++ (port, interface)); ++ /* New field, so must be compile time */ ++ frm_ctl.s.pre_free = 1; ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface), ++ frm_ctl.u64); ++ } ++ ++ /* ++ * Each pause frame transmitted will ask for about 10M ++ * bit times before resume. If buffer space comes ++ * available before that time has expired, an XON ++ * pause frame (0 time) will be transmitted to restart ++ * the flow. ++ */ ++ cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_TIME(port, interface), ++ 20000); ++ cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL ++ (port, interface), 19000); ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), ++ 16); ++ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), ++ 16); ++ } else { ++ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), ++ 24); ++ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), ++ 24); ++ } ++ } ++ ++ __cvmx_helper_setup_gmx(interface, num_ports); ++ ++ /* enable the ports now */ ++ for (port = 0; port < num_ports; port++) { ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port ++ (interface, port)); ++ gmx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(port, interface)); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(port, interface), ++ gmx_cfg.u64); ++ } ++ __cvmx_interrupt_asxx_enable(interface); ++ __cvmx_interrupt_gmxx_enable(interface); ++ ++ return 0; ++} ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++cvmx_helper_link_info_t __cvmx_helper_rgmii_link_get(int ipd_port) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ union cvmx_asxx_prt_loop asxx_prt_loop; ++ ++ asxx_prt_loop.u64 = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); ++ if (asxx_prt_loop.s.int_loop & (1 << index)) { ++ /* Force 1Gbps full duplex on internal loopback */ ++ cvmx_helper_link_info_t result; ++ result.u64 = 0; ++ result.s.full_duplex = 1; ++ result.s.link_up = 1; ++ result.s.speed = 1000; ++ return result; ++ } else ++ return __cvmx_helper_board_link_get(ipd_port); ++} ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_rgmii_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info) ++{ ++ int result = 0; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ union cvmx_gmxx_prtx_cfg original_gmx_cfg; ++ union cvmx_gmxx_prtx_cfg new_gmx_cfg; ++ union cvmx_pko_mem_queue_qos pko_mem_queue_qos; ++ union cvmx_pko_mem_queue_qos pko_mem_queue_qos_save[16]; ++ union cvmx_gmxx_tx_ovr_bp gmx_tx_ovr_bp; ++ union cvmx_gmxx_tx_ovr_bp gmx_tx_ovr_bp_save; ++ int i; ++ ++ /* Ignore speed sets in the simulator */ ++ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) ++ return 0; ++ ++ /* Read the current settings so we know the current enable state */ ++ original_gmx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ new_gmx_cfg = original_gmx_cfg; ++ ++ /* Disable the lowest level RX */ ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), ++ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) & ++ ~(1 << index)); ++ ++ /* Disable all queues so that TX should become idle */ ++ for (i = 0; i < cvmx_pko_get_num_queues(ipd_port); i++) { ++ int queue = cvmx_pko_get_base_queue(ipd_port) + i; ++ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue); ++ pko_mem_queue_qos.u64 = cvmx_read_csr(CVMX_PKO_MEM_QUEUE_QOS); ++ pko_mem_queue_qos.s.pid = ipd_port; ++ pko_mem_queue_qos.s.qid = queue; ++ pko_mem_queue_qos_save[i] = pko_mem_queue_qos; ++ pko_mem_queue_qos.s.qos_mask = 0; ++ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, pko_mem_queue_qos.u64); ++ } ++ ++ /* Disable backpressure */ ++ gmx_tx_ovr_bp.u64 = cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface)); ++ gmx_tx_ovr_bp_save = gmx_tx_ovr_bp; ++ gmx_tx_ovr_bp.s.bp &= ~(1 << index); ++ gmx_tx_ovr_bp.s.en |= 1 << index; ++ cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp.u64); ++ cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface)); ++ ++ /* ++ * Poll the GMX state machine waiting for it to become ++ * idle. Preferably we should only change speed when it is ++ * idle. If it doesn't become idle we will still do the speed ++ * change, but there is a slight chance that GMX will ++ * lockup. ++ */ ++ cvmx_write_csr(CVMX_NPI_DBG_SELECT, ++ interface * 0x800 + index * 0x100 + 0x880); ++ CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data, data & 7, ++ ==, 0, 10000); ++ CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data, data & 0xf, ++ ==, 0, 10000); ++ ++ /* Disable the port before we make any changes */ ++ new_gmx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64); ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ ++ /* Set full/half duplex */ ++ if (cvmx_octeon_is_pass1()) ++ /* Half duplex is broken for 38XX Pass 1 */ ++ new_gmx_cfg.s.duplex = 1; ++ else if (!link_info.s.link_up) ++ /* Force full duplex on down links */ ++ new_gmx_cfg.s.duplex = 1; ++ else ++ new_gmx_cfg.s.duplex = link_info.s.full_duplex; ++ ++ /* Set the link speed. Anything unknown is set to 1Gbps */ ++ if (link_info.s.speed == 10) { ++ new_gmx_cfg.s.slottime = 0; ++ new_gmx_cfg.s.speed = 0; ++ } else if (link_info.s.speed == 100) { ++ new_gmx_cfg.s.slottime = 0; ++ new_gmx_cfg.s.speed = 0; ++ } else { ++ new_gmx_cfg.s.slottime = 1; ++ new_gmx_cfg.s.speed = 1; ++ } ++ ++ /* Adjust the clocks */ ++ if (link_info.s.speed == 10) { ++ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 50); ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); ++ } else if (link_info.s.speed == 100) { ++ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 5); ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); ++ } else { ++ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); ++ } ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ if ((link_info.s.speed == 10) || (link_info.s.speed == 100)) { ++ union cvmx_gmxx_inf_mode mode; ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ ++ /* ++ * Port .en .type .p0mii Configuration ++ * ---- --- ----- ------ ----------------------------------------- ++ * X 0 X X All links are disabled. ++ * 0 1 X 0 Port 0 is RGMII ++ * 0 1 X 1 Port 0 is MII ++ * 1 1 0 X Ports 1 and 2 are configured as RGMII ports. ++ * 1 1 1 X Port 1: GMII/MII; Port 2: disabled. GMII or ++ * MII port is selected by GMX_PRT1_CFG[SPEED]. ++ */ ++ ++ /* In MII mode, CLK_CNT = 1. */ ++ if (((index == 0) && (mode.s.p0mii == 1)) ++ || ((index != 0) && (mode.s.type == 1))) { ++ cvmx_write_csr(CVMX_GMXX_TXX_CLK ++ (index, interface), 1); ++ } ++ } ++ } ++ ++ /* Do a read to make sure all setup stuff is complete */ ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ ++ /* Save the new GMX setting without enabling the port */ ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64); ++ ++ /* Enable the lowest level RX */ ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), ++ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) | (1 << ++ index)); ++ ++ /* Re-enable the TX path */ ++ for (i = 0; i < cvmx_pko_get_num_queues(ipd_port); i++) { ++ int queue = cvmx_pko_get_base_queue(ipd_port) + i; ++ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue); ++ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, ++ pko_mem_queue_qos_save[i].u64); ++ } ++ ++ /* Restore backpressure */ ++ cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp_save.u64); ++ ++ /* Restore the GMX enable state. Port config is complete */ ++ new_gmx_cfg.s.en = original_gmx_cfg.s.en; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64); ++ ++ return result; ++} ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++int __cvmx_helper_rgmii_configure_loopback(int ipd_port, int enable_internal, ++ int enable_external) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ int original_enable; ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ union cvmx_asxx_prt_loop asxx_prt_loop; ++ ++ /* Read the current enable state and save it */ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ original_enable = gmx_cfg.s.en; ++ /* Force port to be disabled */ ++ gmx_cfg.s.en = 0; ++ if (enable_internal) { ++ /* Force speed if we're doing internal loopback */ ++ gmx_cfg.s.duplex = 1; ++ gmx_cfg.s.slottime = 1; ++ gmx_cfg.s.speed = 1; ++ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); ++ } ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ ++ /* Set the loopback bits */ ++ asxx_prt_loop.u64 = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); ++ if (enable_internal) ++ asxx_prt_loop.s.int_loop |= 1 << index; ++ else ++ asxx_prt_loop.s.int_loop &= ~(1 << index); ++ if (enable_external) ++ asxx_prt_loop.s.ext_loop |= 1 << index; ++ else ++ asxx_prt_loop.s.ext_loop &= ~(1 << index); ++ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), asxx_prt_loop.u64); ++ ++ /* Force enables in internal loopback */ ++ if (enable_internal) { ++ uint64_t tmp; ++ tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface)); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), ++ (1 << index) | tmp); ++ tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), ++ (1 << index) | tmp); ++ original_enable = 1; ++ } ++ ++ /* Restore the enable state */ ++ gmx_cfg.s.en = original_enable; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-rgmii.h +@@ -0,0 +1,110 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Functions for RGMII/GMII/MII initialization, configuration, ++ * and monitoring. ++ * ++ */ ++#ifndef __CVMX_HELPER_RGMII_H__ ++#define __CVMX_HELPER_RGMII_H__ ++ ++/** ++ * Probe RGMII ports and determine the number present ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of RGMII/GMII/MII ports (0-4). ++ */ ++extern int __cvmx_helper_rgmii_probe(int interface); ++ ++/** ++ * Put an RGMII interface in loopback mode. Internal packets sent ++ * out will be received back again on the same port. Externally ++ * received packets will echo back out. ++ * ++ * @port: IPD port number to loop. ++ */ ++extern void cvmx_helper_rgmii_internal_loopback(int port); ++ ++/** ++ * Configure all of the ASX, GMX, and PKO regsiters required ++ * to get RGMII to function on the supplied interface. ++ * ++ * @interface: PKO Interface to configure (0 or 1) ++ * ++ * Returns Zero on success ++ */ ++extern int __cvmx_helper_rgmii_enable(int interface); ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++extern cvmx_helper_link_info_t __cvmx_helper_rgmii_link_get(int ipd_port); ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_rgmii_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info); ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++extern int __cvmx_helper_rgmii_configure_loopback(int ipd_port, ++ int enable_internal, ++ int enable_external); ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-sgmii.c +@@ -0,0 +1,550 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Functions for SGMII initialization, configuration, ++ * and monitoring. ++ */ ++ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-mdio.h" ++#include "cvmx-helper.h" ++#include "cvmx-helper-board.h" ++ ++#include "cvmx-gmxx-defs.h" ++#include "cvmx-pcsx-defs.h" ++ ++void __cvmx_interrupt_gmxx_enable(int interface); ++void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block); ++void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index); ++ ++/** ++ * Perform initialization required only once for an SGMII port. ++ * ++ * @interface: Interface to init ++ * @index: Index of prot on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index) ++{ ++ const uint64_t clock_mhz = cvmx_sysinfo_get()->cpu_clock_hz / 1000000; ++ union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg; ++ union cvmx_pcsx_linkx_timer_count_reg pcsx_linkx_timer_count_reg; ++ union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg; ++ ++ /* Disable GMX */ ++ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmxx_prtx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); ++ ++ /* ++ * Write PCS*_LINK*_TIMER_COUNT_REG[COUNT] with the ++ * appropriate value. 1000BASE-X specifies a 10ms ++ * interval. SGMII specifies a 1.6ms interval. ++ */ ++ pcs_misc_ctl_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); ++ pcsx_linkx_timer_count_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface)); ++ if (pcs_misc_ctl_reg.s.mode) { ++ /* 1000BASE-X */ ++ pcsx_linkx_timer_count_reg.s.count = ++ (10000ull * clock_mhz) >> 10; ++ } else { ++ /* SGMII */ ++ pcsx_linkx_timer_count_reg.s.count = ++ (1600ull * clock_mhz) >> 10; ++ } ++ cvmx_write_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface), ++ pcsx_linkx_timer_count_reg.u64); ++ ++ /* ++ * Write the advertisement register to be used as the ++ * tx_Config_Reg of the autonegotiation. In ++ * 1000BASE-X mode, tx_Config_Reg is PCS*_AN*_ADV_REG. ++ * In SGMII PHY mode, tx_Config_Reg is ++ * PCS*_SGM*_AN_ADV_REG. In SGMII MAC mode, ++ * tx_Config_Reg is the fixed value 0x4001, so this ++ * step can be skipped. ++ */ ++ if (pcs_misc_ctl_reg.s.mode) { ++ /* 1000BASE-X */ ++ union cvmx_pcsx_anx_adv_reg pcsx_anx_adv_reg; ++ pcsx_anx_adv_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface)); ++ pcsx_anx_adv_reg.s.rem_flt = 0; ++ pcsx_anx_adv_reg.s.pause = 3; ++ pcsx_anx_adv_reg.s.hfd = 1; ++ pcsx_anx_adv_reg.s.fd = 1; ++ cvmx_write_csr(CVMX_PCSX_ANX_ADV_REG(index, interface), ++ pcsx_anx_adv_reg.u64); ++ } else { ++ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; ++ pcsx_miscx_ctl_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); ++ if (pcsx_miscx_ctl_reg.s.mac_phy) { ++ /* PHY Mode */ ++ union cvmx_pcsx_sgmx_an_adv_reg pcsx_sgmx_an_adv_reg; ++ pcsx_sgmx_an_adv_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_SGMX_AN_ADV_REG ++ (index, interface)); ++ pcsx_sgmx_an_adv_reg.s.link = 1; ++ pcsx_sgmx_an_adv_reg.s.dup = 1; ++ pcsx_sgmx_an_adv_reg.s.speed = 2; ++ cvmx_write_csr(CVMX_PCSX_SGMX_AN_ADV_REG ++ (index, interface), ++ pcsx_sgmx_an_adv_reg.u64); ++ } else { ++ /* MAC Mode - Nothing to do */ ++ } ++ } ++ return 0; ++} ++ ++/** ++ * Initialize the SERTES link for the first time or after a loss ++ * of link. ++ * ++ * @interface: Interface to init ++ * @index: Index of prot on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index) ++{ ++ union cvmx_pcsx_mrx_control_reg control_reg; ++ ++ /* ++ * Take PCS through a reset sequence. ++ * PCS*_MR*_CONTROL_REG[PWR_DN] should be cleared to zero. ++ * Write PCS*_MR*_CONTROL_REG[RESET]=1 (while not changing the ++ * value of the other PCS*_MR*_CONTROL_REG bits). Read ++ * PCS*_MR*_CONTROL_REG[RESET] until it changes value to ++ * zero. ++ */ ++ control_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface)); ++ if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) { ++ control_reg.s.reset = 1; ++ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), ++ control_reg.u64); ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_PCSX_MRX_CONTROL_REG(index, interface), ++ union cvmx_pcsx_mrx_control_reg, reset, ==, 0, 10000)) { ++ cvmx_dprintf("SGMII%d: Timeout waiting for port %d " ++ "to finish reset\n", ++ interface, index); ++ return -1; ++ } ++ } ++ ++ /* ++ * Write PCS*_MR*_CONTROL_REG[RST_AN]=1 to ensure a fresh ++ * sgmii negotiation starts. ++ */ ++ control_reg.s.rst_an = 1; ++ control_reg.s.an_en = 1; ++ control_reg.s.pwr_dn = 0; ++ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), ++ control_reg.u64); ++ ++ /* ++ * Wait for PCS*_MR*_STATUS_REG[AN_CPT] to be set, indicating ++ * that sgmii autonegotiation is complete. In MAC mode this ++ * isn't an ethernet link, but a link between Octeon and the ++ * PHY. ++ */ ++ if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && ++ CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_STATUS_REG(index, interface), ++ union cvmx_pcsx_mrx_status_reg, an_cpt, ==, 1, ++ 10000)) { ++ /* cvmx_dprintf("SGMII%d: Port %d link timeout\n", interface, index); */ ++ return -1; ++ } ++ return 0; ++} ++ ++/** ++ * Configure an SGMII link to the specified speed after the SERTES ++ * link is up. ++ * ++ * @interface: Interface to init ++ * @index: Index of prot on the interface ++ * @link_info: Link state to configure ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_sgmii_hardware_init_link_speed(int interface, ++ int index, ++ cvmx_helper_link_info_t ++ link_info) ++{ ++ int is_enabled; ++ union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg; ++ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; ++ ++ /* Disable GMX before we make any changes. Remember the enable state */ ++ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ is_enabled = gmxx_prtx_cfg.s.en; ++ gmxx_prtx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); ++ ++ /* Wait for GMX to be idle */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_GMXX_PRTX_CFG(index, interface), union cvmx_gmxx_prtx_cfg, ++ rx_idle, ==, 1, 10000) ++ || CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), ++ union cvmx_gmxx_prtx_cfg, tx_idle, ==, 1, ++ 10000)) { ++ cvmx_dprintf ++ ("SGMII%d: Timeout waiting for port %d to be idle\n", ++ interface, index); ++ return -1; ++ } ++ ++ /* Read GMX CFG again to make sure the disable completed */ ++ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ ++ /* ++ * Get the misc control for PCS. We will need to set the ++ * duplication amount. ++ */ ++ pcsx_miscx_ctl_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); ++ ++ /* ++ * Use GMXENO to force the link down if the status we get says ++ * it should be down. ++ */ ++ pcsx_miscx_ctl_reg.s.gmxeno = !link_info.s.link_up; ++ ++ /* Only change the duplex setting if the link is up */ ++ if (link_info.s.link_up) ++ gmxx_prtx_cfg.s.duplex = link_info.s.full_duplex; ++ ++ /* Do speed based setting for GMX */ ++ switch (link_info.s.speed) { ++ case 10: ++ gmxx_prtx_cfg.s.speed = 0; ++ gmxx_prtx_cfg.s.speed_msb = 1; ++ gmxx_prtx_cfg.s.slottime = 0; ++ /* Setting from GMX-603 */ ++ pcsx_miscx_ctl_reg.s.samp_pt = 25; ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); ++ break; ++ case 100: ++ gmxx_prtx_cfg.s.speed = 0; ++ gmxx_prtx_cfg.s.speed_msb = 0; ++ gmxx_prtx_cfg.s.slottime = 0; ++ pcsx_miscx_ctl_reg.s.samp_pt = 0x5; ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); ++ break; ++ case 1000: ++ gmxx_prtx_cfg.s.speed = 1; ++ gmxx_prtx_cfg.s.speed_msb = 0; ++ gmxx_prtx_cfg.s.slottime = 1; ++ pcsx_miscx_ctl_reg.s.samp_pt = 1; ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 512); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 8192); ++ break; ++ default: ++ break; ++ } ++ ++ /* Write the new misc control for PCS */ ++ cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface), ++ pcsx_miscx_ctl_reg.u64); ++ ++ /* Write the new GMX settings with the port still disabled */ ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); ++ ++ /* Read GMX CFG again to make sure the config completed */ ++ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ ++ /* Restore the enabled / disabled state */ ++ gmxx_prtx_cfg.s.en = is_enabled; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); ++ ++ return 0; ++} ++ ++/** ++ * Bring up the SGMII interface to be ready for packet I/O but ++ * leave I/O disabled using the GMX override. This function ++ * follows the bringup documented in 10.6.3 of the manual. ++ * ++ * @interface: Interface to bringup ++ * @num_ports: Number of ports on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports) ++{ ++ int index; ++ ++ __cvmx_helper_setup_gmx(interface, num_ports); ++ ++ for (index = 0; index < num_ports; index++) { ++ int ipd_port = cvmx_helper_get_ipd_port(interface, index); ++ __cvmx_helper_sgmii_hardware_init_one_time(interface, index); ++ __cvmx_helper_sgmii_link_set(ipd_port, ++ __cvmx_helper_sgmii_link_get ++ (ipd_port)); ++ ++ } ++ ++ return 0; ++} ++ ++/** ++ * Probe a SGMII interface and determine the number of ports ++ * connected to it. The SGMII interface should still be down after ++ * this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++int __cvmx_helper_sgmii_probe(int interface) ++{ ++ union cvmx_gmxx_inf_mode mode; ++ ++ /* ++ * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the ++ * interface needs to be enabled before IPD otherwise per port ++ * backpressure may not work properly ++ */ ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ mode.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64); ++ return 4; ++} ++ ++/** ++ * Bringup and enable a SGMII interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_sgmii_enable(int interface) ++{ ++ int num_ports = cvmx_helper_ports_on_interface(interface); ++ int index; ++ ++ __cvmx_helper_sgmii_hardware_init(interface, num_ports); ++ ++ for (index = 0; index < num_ports; index++) { ++ union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg; ++ gmxx_prtx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmxx_prtx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), ++ gmxx_prtx_cfg.u64); ++ __cvmx_interrupt_pcsx_intx_en_reg_enable(index, interface); ++ } ++ __cvmx_interrupt_pcsxx_int_en_reg_enable(interface); ++ __cvmx_interrupt_gmxx_enable(interface); ++ return 0; ++} ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port) ++{ ++ cvmx_helper_link_info_t result; ++ union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg; ++ ++ result.u64 = 0; ++ ++ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) { ++ /* The simulator gives you a simulated 1Gbps full duplex link */ ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ return result; ++ } ++ ++ pcsx_mrx_control_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface)); ++ if (pcsx_mrx_control_reg.s.loopbck1) { ++ /* Force 1Gbps full duplex link for internal loopback */ ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 1000; ++ return result; ++ } ++ ++ pcs_misc_ctl_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); ++ if (pcs_misc_ctl_reg.s.mode) { ++ /* 1000BASE-X */ ++ /* FIXME */ ++ } else { ++ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; ++ pcsx_miscx_ctl_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); ++ if (pcsx_miscx_ctl_reg.s.mac_phy) { ++ /* PHY Mode */ ++ union cvmx_pcsx_mrx_status_reg pcsx_mrx_status_reg; ++ union cvmx_pcsx_anx_results_reg pcsx_anx_results_reg; ++ ++ /* ++ * Don't bother continuing if the SERTES low ++ * level link is down ++ */ ++ pcsx_mrx_status_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG ++ (index, interface)); ++ if (pcsx_mrx_status_reg.s.lnk_st == 0) { ++ if (__cvmx_helper_sgmii_hardware_init_link ++ (interface, index) != 0) ++ return result; ++ } ++ ++ /* Read the autoneg results */ ++ pcsx_anx_results_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_ANX_RESULTS_REG ++ (index, interface)); ++ if (pcsx_anx_results_reg.s.an_cpt) { ++ /* ++ * Auto negotiation is complete. Set ++ * status accordingly. ++ */ ++ result.s.full_duplex = ++ pcsx_anx_results_reg.s.dup; ++ result.s.link_up = ++ pcsx_anx_results_reg.s.link_ok; ++ switch (pcsx_anx_results_reg.s.spd) { ++ case 0: ++ result.s.speed = 10; ++ break; ++ case 1: ++ result.s.speed = 100; ++ break; ++ case 2: ++ result.s.speed = 1000; ++ break; ++ default: ++ result.s.speed = 0; ++ result.s.link_up = 0; ++ break; ++ } ++ } else { ++ /* ++ * Auto negotiation isn't ++ * complete. Return link down. ++ */ ++ result.s.speed = 0; ++ result.s.link_up = 0; ++ } ++ } else { /* MAC Mode */ ++ ++ result = __cvmx_helper_board_link_get(ipd_port); ++ } ++ } ++ return result; ++} ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_sgmii_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ __cvmx_helper_sgmii_hardware_init_link(interface, index); ++ return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index, ++ link_info); ++} ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal ++ * loopback causes packets sent by the port to be received by ++ * Octeon. External loopback causes packets received from the wire to ++ * sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++int __cvmx_helper_sgmii_configure_loopback(int ipd_port, int enable_internal, ++ int enable_external) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg; ++ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; ++ ++ pcsx_mrx_control_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface)); ++ pcsx_mrx_control_reg.s.loopbck1 = enable_internal; ++ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), ++ pcsx_mrx_control_reg.u64); ++ ++ pcsx_miscx_ctl_reg.u64 = ++ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); ++ pcsx_miscx_ctl_reg.s.loopbck2 = enable_external; ++ cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface), ++ pcsx_miscx_ctl_reg.u64); ++ ++ __cvmx_helper_sgmii_hardware_init_link(interface, index); ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-sgmii.h +@@ -0,0 +1,104 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Functions for SGMII initialization, configuration, ++ * and monitoring. ++ * ++ */ ++#ifndef __CVMX_HELPER_SGMII_H__ ++#define __CVMX_HELPER_SGMII_H__ ++ ++/** ++ * Probe a SGMII interface and determine the number of ports ++ * connected to it. The SGMII interface should still be down after ++ * this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++extern int __cvmx_helper_sgmii_probe(int interface); ++ ++/** ++ * Bringup and enable a SGMII interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_sgmii_enable(int interface); ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++extern cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port); ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_sgmii_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info); ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++extern int __cvmx_helper_sgmii_configure_loopback(int ipd_port, ++ int enable_internal, ++ int enable_external); ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-spi.c +@@ -0,0 +1,195 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++void __cvmx_interrupt_gmxx_enable(int interface); ++void __cvmx_interrupt_spxx_int_msk_enable(int index); ++void __cvmx_interrupt_stxx_int_msk_enable(int index); ++ ++/* ++ * Functions for SPI initialization, configuration, ++ * and monitoring. ++ */ ++#include ++ ++#include "cvmx-config.h" ++#include "cvmx-spi.h" ++#include "cvmx-helper.h" ++ ++#include "cvmx-pip-defs.h" ++#include "cvmx-pko-defs.h" ++ ++/* ++ * CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI ++ * initialization routines wait for SPI training. You can override the ++ * value using executive-config.h if necessary. ++ */ ++#ifndef CVMX_HELPER_SPI_TIMEOUT ++#define CVMX_HELPER_SPI_TIMEOUT 10 ++#endif ++ ++/** ++ * Probe a SPI interface and determine the number of ports ++ * connected to it. The SPI interface should still be down after ++ * this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++int __cvmx_helper_spi_probe(int interface) ++{ ++ int num_ports = 0; ++ ++ if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && ++ cvmx_spi4000_is_present(interface)) { ++ num_ports = 10; ++ } else { ++ union cvmx_pko_reg_crc_enable enable; ++ num_ports = 16; ++ /* ++ * Unlike the SPI4000, most SPI devices don't ++ * automatically put on the L2 CRC. For everything ++ * except for the SPI4000 have PKO append the L2 CRC ++ * to the packet. ++ */ ++ enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE); ++ enable.s.enable |= 0xffff << (interface * 16); ++ cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64); ++ } ++ __cvmx_helper_setup_gmx(interface, num_ports); ++ return num_ports; ++} ++ ++/** ++ * Bringup and enable a SPI interface. After this call packet I/O ++ * should be fully functional. This is called with IPD enabled but ++ * PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_spi_enable(int interface) ++{ ++ /* ++ * Normally the ethernet L2 CRC is checked and stripped in the ++ * GMX block. When you are using SPI, this isn' the case and ++ * IPD needs to check the L2 CRC. ++ */ ++ int num_ports = cvmx_helper_ports_on_interface(interface); ++ int ipd_port; ++ for (ipd_port = interface * 16; ipd_port < interface * 16 + num_ports; ++ ipd_port++) { ++ union cvmx_pip_prt_cfgx port_config; ++ port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); ++ port_config.s.crc_en = 1; ++ cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64); ++ } ++ ++ if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) { ++ cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX, ++ CVMX_HELPER_SPI_TIMEOUT, num_ports); ++ if (cvmx_spi4000_is_present(interface)) ++ cvmx_spi4000_initialize(interface); ++ } ++ __cvmx_interrupt_spxx_int_msk_enable(interface); ++ __cvmx_interrupt_stxx_int_msk_enable(interface); ++ __cvmx_interrupt_gmxx_enable(interface); ++ return 0; ++} ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port) ++{ ++ cvmx_helper_link_info_t result; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ result.u64 = 0; ++ ++ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) { ++ /* The simulator gives you a simulated full duplex link */ ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 10000; ++ } else if (cvmx_spi4000_is_present(interface)) { ++ union cvmx_gmxx_rxx_rx_inbnd inband = ++ cvmx_spi4000_check_speed(interface, index); ++ result.s.link_up = inband.s.status; ++ result.s.full_duplex = inband.s.duplex; ++ switch (inband.s.speed) { ++ case 0: /* 10 Mbps */ ++ result.s.speed = 10; ++ break; ++ case 1: /* 100 Mbps */ ++ result.s.speed = 100; ++ break; ++ case 2: /* 1 Gbps */ ++ result.s.speed = 1000; ++ break; ++ case 3: /* Illegal */ ++ result.s.speed = 0; ++ result.s.link_up = 0; ++ break; ++ } ++ } else { ++ /* For generic SPI we can't determine the link, just return some ++ sane results */ ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 10000; ++ } ++ return result; ++} ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_spi_link_set(int ipd_port, cvmx_helper_link_info_t link_info) ++{ ++ /* Nothing to do. If we have a SPI4000 then the setup was already performed ++ by cvmx_spi4000_check_speed(). If not then there isn't any link ++ info */ ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-spi.h +@@ -0,0 +1,84 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Functions for SPI initialization, configuration, ++ * and monitoring. ++ */ ++#ifndef __CVMX_HELPER_SPI_H__ ++#define __CVMX_HELPER_SPI_H__ ++ ++/** ++ * Probe a SPI interface and determine the number of ports ++ * connected to it. The SPI interface should still be down after ++ * this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++extern int __cvmx_helper_spi_probe(int interface); ++ ++/** ++ * Bringup and enable a SPI interface. After this call packet I/O ++ * should be fully functional. This is called with IPD enabled but ++ * PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_spi_enable(int interface); ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++extern cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port); ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_spi_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info); ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-util.c +@@ -0,0 +1,433 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Small helper utilities. ++ */ ++#include ++ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-fpa.h" ++#include "cvmx-pip.h" ++#include "cvmx-pko.h" ++#include "cvmx-ipd.h" ++#include "cvmx-spi.h" ++ ++#include "cvmx-helper.h" ++#include "cvmx-helper-util.h" ++ ++#include ++ ++/** ++ * Convert a interface mode into a human readable string ++ * ++ * @mode: Mode to convert ++ * ++ * Returns String ++ */ ++const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t ++ mode) ++{ ++ switch (mode) { ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ return "DISABLED"; ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ return "RGMII"; ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ return "GMII"; ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ return "SPI"; ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ return "PCIE"; ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ return "XAUI"; ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ return "SGMII"; ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ return "PICMG"; ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ return "NPI"; ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ return "LOOP"; ++ } ++ return "UNKNOWN"; ++} ++ ++/** ++ * Debug routine to dump the packet structure to the console ++ * ++ * @work: Work queue entry containing the packet to dump ++ * Returns ++ */ ++int cvmx_helper_dump_packet(cvmx_wqe_t *work) ++{ ++ uint64_t count; ++ uint64_t remaining_bytes; ++ union cvmx_buf_ptr buffer_ptr; ++ uint64_t start_of_buffer; ++ uint8_t *data_address; ++ uint8_t *end_of_data; ++ ++ cvmx_dprintf("Packet Length: %u\n", work->len); ++ cvmx_dprintf(" Input Port: %u\n", work->ipprt); ++ cvmx_dprintf(" QoS: %u\n", work->qos); ++ cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs); ++ ++ if (work->word2.s.bufs == 0) { ++ union cvmx_ipd_wqe_fpa_queue wqe_pool; ++ wqe_pool.u64 = cvmx_read_csr(CVMX_IPD_WQE_FPA_QUEUE); ++ buffer_ptr.u64 = 0; ++ buffer_ptr.s.pool = wqe_pool.s.wqe_pool; ++ buffer_ptr.s.size = 128; ++ buffer_ptr.s.addr = cvmx_ptr_to_phys(work->packet_data); ++ if (likely(!work->word2.s.not_IP)) { ++ union cvmx_pip_ip_offset pip_ip_offset; ++ pip_ip_offset.u64 = cvmx_read_csr(CVMX_PIP_IP_OFFSET); ++ buffer_ptr.s.addr += ++ (pip_ip_offset.s.offset << 3) - ++ work->word2.s.ip_offset; ++ buffer_ptr.s.addr += (work->word2.s.is_v6 ^ 1) << 2; ++ } else { ++ /* ++ * WARNING: This code assumes that the packet ++ * is not RAW. If it was, we would use ++ * PIP_GBL_CFG[RAW_SHF] instead of ++ * PIP_GBL_CFG[NIP_SHF]. ++ */ ++ union cvmx_pip_gbl_cfg pip_gbl_cfg; ++ pip_gbl_cfg.u64 = cvmx_read_csr(CVMX_PIP_GBL_CFG); ++ buffer_ptr.s.addr += pip_gbl_cfg.s.nip_shf; ++ } ++ } else ++ buffer_ptr = work->packet_ptr; ++ remaining_bytes = work->len; ++ ++ while (remaining_bytes) { ++ start_of_buffer = ++ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; ++ cvmx_dprintf(" Buffer Start:%llx\n", ++ (unsigned long long)start_of_buffer); ++ cvmx_dprintf(" Buffer I : %u\n", buffer_ptr.s.i); ++ cvmx_dprintf(" Buffer Back: %u\n", buffer_ptr.s.back); ++ cvmx_dprintf(" Buffer Pool: %u\n", buffer_ptr.s.pool); ++ cvmx_dprintf(" Buffer Data: %llx\n", ++ (unsigned long long)buffer_ptr.s.addr); ++ cvmx_dprintf(" Buffer Size: %u\n", buffer_ptr.s.size); ++ ++ cvmx_dprintf("\t\t"); ++ data_address = (uint8_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr); ++ end_of_data = data_address + buffer_ptr.s.size; ++ count = 0; ++ while (data_address < end_of_data) { ++ if (remaining_bytes == 0) ++ break; ++ else ++ remaining_bytes--; ++ cvmx_dprintf("%02x", (unsigned int)*data_address); ++ data_address++; ++ if (remaining_bytes && (count == 7)) { ++ cvmx_dprintf("\n\t\t"); ++ count = 0; ++ } else ++ count++; ++ } ++ cvmx_dprintf("\n"); ++ ++ if (remaining_bytes) ++ buffer_ptr = *(union cvmx_buf_ptr *) ++ cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); ++ } ++ return 0; ++} ++ ++/** ++ * Setup Random Early Drop on a specific input queue ++ * ++ * @queue: Input queue to setup RED on (0-7) ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh) ++{ ++ union cvmx_ipd_qosx_red_marks red_marks; ++ union cvmx_ipd_red_quex_param red_param; ++ ++ /* Set RED to begin dropping packets when there are pass_thresh buffers ++ left. It will linearly drop more packets until reaching drop_thresh ++ buffers */ ++ red_marks.u64 = 0; ++ red_marks.s.drop = drop_thresh; ++ red_marks.s.pass = pass_thresh; ++ cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64); ++ ++ /* Use the actual queue 0 counter, not the average */ ++ red_param.u64 = 0; ++ red_param.s.prb_con = ++ (255ul << 24) / (red_marks.s.pass - red_marks.s.drop); ++ red_param.s.avg_con = 1; ++ red_param.s.new_con = 255; ++ red_param.s.use_pcnt = 1; ++ cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64); ++ return 0; ++} ++ ++/** ++ * Setup Random Early Drop to automatically begin dropping packets. ++ * ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) ++{ ++ union cvmx_ipd_portx_bp_page_cnt page_cnt; ++ union cvmx_ipd_bp_prt_red_end ipd_bp_prt_red_end; ++ union cvmx_ipd_red_port_enable red_port_enable; ++ int queue; ++ int interface; ++ int port; ++ ++ /* Disable backpressure based on queued buffers. It needs SW support */ ++ page_cnt.u64 = 0; ++ page_cnt.s.bp_enb = 0; ++ page_cnt.s.page_cnt = 100; ++ for (interface = 0; interface < 2; interface++) { ++ for (port = cvmx_helper_get_first_ipd_port(interface); ++ port < cvmx_helper_get_last_ipd_port(interface); port++) ++ cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), ++ page_cnt.u64); ++ } ++ ++ for (queue = 0; queue < 8; queue++) ++ cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh); ++ ++ /* Shutoff the dropping based on the per port page count. SW isn't ++ decrementing it right now */ ++ ipd_bp_prt_red_end.u64 = 0; ++ ipd_bp_prt_red_end.s.prt_enb = 0; ++ cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64); ++ ++ red_port_enable.u64 = 0; ++ red_port_enable.s.prt_enb = 0xfffffffffull; ++ red_port_enable.s.avg_dly = 10000; ++ red_port_enable.s.prb_dly = 10000; ++ cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64); ++ ++ return 0; ++} ++ ++/** ++ * Setup the common GMX settings that determine the number of ++ * ports. These setting apply to almost all configurations of all ++ * chips. ++ * ++ * @interface: Interface to configure ++ * @num_ports: Number of ports on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_setup_gmx(int interface, int num_ports) ++{ ++ union cvmx_gmxx_tx_prts gmx_tx_prts; ++ union cvmx_gmxx_rx_prts gmx_rx_prts; ++ union cvmx_pko_reg_gmx_port_mode pko_mode; ++ union cvmx_gmxx_txx_thresh gmx_tx_thresh; ++ int index; ++ ++ /* Tell GMX the number of TX ports on this interface */ ++ gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface)); ++ gmx_tx_prts.s.prts = num_ports; ++ cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64); ++ ++ /* Tell GMX the number of RX ports on this interface. This only ++ ** applies to *GMII and XAUI ports */ ++ if (cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_RGMII ++ || cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_SGMII ++ || cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_GMII ++ || cvmx_helper_interface_get_mode(interface) == ++ CVMX_HELPER_INTERFACE_MODE_XAUI) { ++ if (num_ports > 4) { ++ cvmx_dprintf("__cvmx_helper_setup_gmx: Illegal " ++ "num_ports\n"); ++ return -1; ++ } ++ ++ gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface)); ++ gmx_rx_prts.s.prts = num_ports; ++ cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64); ++ } ++ ++ /* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, and 50XX */ ++ if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX) ++ && !OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ /* Tell PKO the number of ports on this interface */ ++ pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE); ++ if (interface == 0) { ++ if (num_ports == 1) ++ pko_mode.s.mode0 = 4; ++ else if (num_ports == 2) ++ pko_mode.s.mode0 = 3; ++ else if (num_ports <= 4) ++ pko_mode.s.mode0 = 2; ++ else if (num_ports <= 8) ++ pko_mode.s.mode0 = 1; ++ else ++ pko_mode.s.mode0 = 0; ++ } else { ++ if (num_ports == 1) ++ pko_mode.s.mode1 = 4; ++ else if (num_ports == 2) ++ pko_mode.s.mode1 = 3; ++ else if (num_ports <= 4) ++ pko_mode.s.mode1 = 2; ++ else if (num_ports <= 8) ++ pko_mode.s.mode1 = 1; ++ else ++ pko_mode.s.mode1 = 0; ++ } ++ cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64); ++ } ++ ++ /* ++ * Set GMX to buffer as much data as possible before starting ++ * transmit. This reduces the chances that we have a TX under ++ * run due to memory contention. Any packet that fits entirely ++ * in the GMX FIFO can never have an under run regardless of ++ * memory load. ++ */ ++ gmx_tx_thresh.u64 = cvmx_read_csr(CVMX_GMXX_TXX_THRESH(0, interface)); ++ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ /* These chips have a fixed max threshold of 0x40 */ ++ gmx_tx_thresh.s.cnt = 0x40; ++ } else { ++ /* Choose the max value for the number of ports */ ++ if (num_ports <= 1) ++ gmx_tx_thresh.s.cnt = 0x100 / 1; ++ else if (num_ports == 2) ++ gmx_tx_thresh.s.cnt = 0x100 / 2; ++ else ++ gmx_tx_thresh.s.cnt = 0x100 / 4; ++ } ++ /* ++ * SPI and XAUI can have lots of ports but the GMX hardware ++ * only ever has a max of 4. ++ */ ++ if (num_ports > 4) ++ num_ports = 4; ++ for (index = 0; index < num_ports; index++) ++ cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface), ++ gmx_tx_thresh.u64); ++ ++ return 0; ++} ++ ++/** ++ * Returns the IPD/PKO port number for a port on teh given ++ * interface. ++ * ++ * @interface: Interface to use ++ * @port: Port on the interface ++ * ++ * Returns IPD/PKO port number ++ */ ++int cvmx_helper_get_ipd_port(int interface, int port) ++{ ++ switch (interface) { ++ case 0: ++ return port; ++ case 1: ++ return port + 16; ++ case 2: ++ return port + 32; ++ case 3: ++ return port + 36; ++ } ++ return -1; ++} ++ ++/** ++ * Returns the interface number for an IPD/PKO port number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface number ++ */ ++int cvmx_helper_get_interface_num(int ipd_port) ++{ ++ if (ipd_port < 16) ++ return 0; ++ else if (ipd_port < 32) ++ return 1; ++ else if (ipd_port < 36) ++ return 2; ++ else if (ipd_port < 40) ++ return 3; ++ else ++ cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD " ++ "port number\n"); ++ ++ return -1; ++} ++ ++/** ++ * Returns the interface index number for an IPD/PKO port ++ * number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface index number ++ */ ++int cvmx_helper_get_interface_index_num(int ipd_port) ++{ ++ if (ipd_port < 32) ++ return ipd_port & 15; ++ else if (ipd_port < 36) ++ return ipd_port & 3; ++ else if (ipd_port < 40) ++ return ipd_port & 3; ++ else ++ cvmx_dprintf("cvmx_helper_get_interface_index_num: " ++ "Illegal IPD port number\n"); ++ ++ return -1; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-util.h +@@ -0,0 +1,215 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Small helper utilities. ++ * ++ */ ++ ++#ifndef __CVMX_HELPER_UTIL_H__ ++#define __CVMX_HELPER_UTIL_H__ ++ ++/** ++ * Convert a interface mode into a human readable string ++ * ++ * @mode: Mode to convert ++ * ++ * Returns String ++ */ ++extern const char ++ *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode); ++ ++/** ++ * Debug routine to dump the packet structure to the console ++ * ++ * @work: Work queue entry containing the packet to dump ++ * Returns ++ */ ++extern int cvmx_helper_dump_packet(cvmx_wqe_t *work); ++ ++/** ++ * Setup Random Early Drop on a specific input queue ++ * ++ * @queue: Input queue to setup RED on (0-7) ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++extern int cvmx_helper_setup_red_queue(int queue, int pass_thresh, ++ int drop_thresh); ++ ++/** ++ * Setup Random Early Drop to automatically begin dropping packets. ++ * ++ * @pass_thresh: ++ * Packets will begin slowly dropping when there are less than ++ * this many packet buffers free in FPA 0. ++ * @drop_thresh: ++ * All incomming packets will be dropped when there are less ++ * than this many free packet buffers in FPA 0. ++ * Returns Zero on success. Negative on failure ++ */ ++extern int cvmx_helper_setup_red(int pass_thresh, int drop_thresh); ++ ++/** ++ * Get the version of the CVMX libraries. ++ * ++ * Returns Version string. Note this buffer is allocated statically ++ * and will be shared by all callers. ++ */ ++extern const char *cvmx_helper_get_version(void); ++ ++/** ++ * Setup the common GMX settings that determine the number of ++ * ports. These setting apply to almost all configurations of all ++ * chips. ++ * ++ * @interface: Interface to configure ++ * @num_ports: Number of ports on the interface ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_setup_gmx(int interface, int num_ports); ++ ++/** ++ * Returns the IPD/PKO port number for a port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * @port: Port on the interface ++ * ++ * Returns IPD/PKO port number ++ */ ++extern int cvmx_helper_get_ipd_port(int interface, int port); ++ ++/** ++ * Returns the IPD/PKO port number for the first port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * ++ * Returns IPD/PKO port number ++ */ ++static inline int cvmx_helper_get_first_ipd_port(int interface) ++{ ++ return cvmx_helper_get_ipd_port(interface, 0); ++} ++ ++/** ++ * Returns the IPD/PKO port number for the last port on the given ++ * interface. ++ * ++ * @interface: Interface to use ++ * ++ * Returns IPD/PKO port number ++ */ ++static inline int cvmx_helper_get_last_ipd_port(int interface) ++{ ++ extern int cvmx_helper_ports_on_interface(int interface); ++ ++ return cvmx_helper_get_first_ipd_port(interface) + ++ cvmx_helper_ports_on_interface(interface) - 1; ++} ++ ++/** ++ * Free the packet buffers contained in a work queue entry. ++ * The work queue entry is not freed. ++ * ++ * @work: Work queue entry with packet to free ++ */ ++static inline void cvmx_helper_free_packet_data(cvmx_wqe_t *work) ++{ ++ uint64_t number_buffers; ++ union cvmx_buf_ptr buffer_ptr; ++ union cvmx_buf_ptr next_buffer_ptr; ++ uint64_t start_of_buffer; ++ ++ number_buffers = work->word2.s.bufs; ++ if (number_buffers == 0) ++ return; ++ buffer_ptr = work->packet_ptr; ++ ++ /* ++ * Since the number of buffers is not zero, we know this is ++ * not a dynamic short packet. We need to check if it is a ++ * packet received with IPD_CTL_STATUS[NO_WPTR]. If this is ++ * true, we need to free all buffers except for the first ++ * one. The caller doesn't expect their WQE pointer to be ++ * freed ++ */ ++ start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; ++ if (cvmx_ptr_to_phys(work) == start_of_buffer) { ++ next_buffer_ptr = ++ *(union cvmx_buf_ptr *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); ++ buffer_ptr = next_buffer_ptr; ++ number_buffers--; ++ } ++ ++ while (number_buffers--) { ++ /* ++ * Remember the back pointer is in cache lines, not ++ * 64bit words ++ */ ++ start_of_buffer = ++ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; ++ /* ++ * Read pointer to next buffer before we free the ++ * current buffer. ++ */ ++ next_buffer_ptr = ++ *(union cvmx_buf_ptr *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); ++ cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer), ++ buffer_ptr.s.pool, 0); ++ buffer_ptr = next_buffer_ptr; ++ } ++} ++ ++/** ++ * Returns the interface number for an IPD/PKO port number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface number ++ */ ++extern int cvmx_helper_get_interface_num(int ipd_port); ++ ++/** ++ * Returns the interface index number for an IPD/PKO port ++ * number. ++ * ++ * @ipd_port: IPD/PKO port number ++ * ++ * Returns Interface index number ++ */ ++extern int cvmx_helper_get_interface_index_num(int ipd_port); ++ ++#endif /* __CVMX_HELPER_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-xaui.c +@@ -0,0 +1,348 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Functions for XAUI initialization, configuration, ++ * and monitoring. ++ * ++ */ ++ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-helper.h" ++ ++#include "cvmx-pko-defs.h" ++#include "cvmx-gmxx-defs.h" ++#include "cvmx-pcsxx-defs.h" ++ ++void __cvmx_interrupt_gmxx_enable(int interface); ++void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block); ++void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index); ++/** ++ * Probe a XAUI interface and determine the number of ports ++ * connected to it. The XAUI interface should still be down ++ * after this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++int __cvmx_helper_xaui_probe(int interface) ++{ ++ int i; ++ union cvmx_gmxx_hg2_control gmx_hg2_control; ++ union cvmx_gmxx_inf_mode mode; ++ ++ /* ++ * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the ++ * interface needs to be enabled before IPD otherwise per port ++ * backpressure may not work properly. ++ */ ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ mode.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64); ++ ++ __cvmx_helper_setup_gmx(interface, 1); ++ ++ /* ++ * Setup PKO to support 16 ports for HiGig2 virtual ++ * ports. We're pointing all of the PKO packet ports for this ++ * interface to the XAUI. This allows us to use HiGig2 ++ * backpressure per port. ++ */ ++ for (i = 0; i < 16; i++) { ++ union cvmx_pko_mem_port_ptrs pko_mem_port_ptrs; ++ pko_mem_port_ptrs.u64 = 0; ++ /* ++ * We set each PKO port to have equal priority in a ++ * round robin fashion. ++ */ ++ pko_mem_port_ptrs.s.static_p = 0; ++ pko_mem_port_ptrs.s.qos_mask = 0xff; ++ /* All PKO ports map to the same XAUI hardware port */ ++ pko_mem_port_ptrs.s.eid = interface * 4; ++ pko_mem_port_ptrs.s.pid = interface * 16 + i; ++ cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64); ++ } ++ ++ /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */ ++ gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface)); ++ if (gmx_hg2_control.s.hg2tx_en) ++ return 16; ++ else ++ return 1; ++} ++ ++/** ++ * Bringup and enable a XAUI interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_xaui_enable(int interface) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ union cvmx_pcsxx_control1_reg xauiCtl; ++ union cvmx_pcsxx_misc_ctl_reg xauiMiscCtl; ++ union cvmx_gmxx_tx_xaui_ctl gmxXauiTxCtl; ++ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; ++ union cvmx_gmxx_tx_int_en gmx_tx_int_en; ++ union cvmx_pcsxx_int_en_reg pcsx_int_en_reg; ++ ++ /* (1) Interface has already been enabled. */ ++ ++ /* (2) Disable GMX. */ ++ xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface)); ++ xauiMiscCtl.s.gmxeno = 1; ++ cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); ++ ++ /* (3) Disable GMX and PCSX interrupts. */ ++ gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0, interface)); ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0); ++ gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface)); ++ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0); ++ pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface)); ++ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0); ++ ++ /* (4) Bring up the PCSX and GMX reconciliation layer. */ ++ /* (4)a Set polarity and lane swapping. */ ++ /* (4)b */ ++ gmxXauiTxCtl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); ++ /* Enable better IFG packing and improves performance */ ++ gmxXauiTxCtl.s.dic_en = 1; ++ gmxXauiTxCtl.s.uni_en = 0; ++ cvmx_write_csr(CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64); ++ ++ /* (4)c Aply reset sequence */ ++ xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); ++ xauiCtl.s.lo_pwr = 0; ++ xauiCtl.s.reset = 1; ++ cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64); ++ ++ /* Wait for PCS to come out of reset */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_PCSXX_CONTROL1_REG(interface), union cvmx_pcsxx_control1_reg, ++ reset, ==, 0, 10000)) ++ return -1; ++ /* Wait for PCS to be aligned */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_PCSXX_10GBX_STATUS_REG(interface), ++ union cvmx_pcsxx_10gbx_status_reg, alignd, ==, 1, 10000)) ++ return -1; ++ /* Wait for RX to be ready */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_GMXX_RX_XAUI_CTL(interface), union cvmx_gmxx_rx_xaui_ctl, ++ status, ==, 0, 10000)) ++ return -1; ++ ++ /* (6) Configure GMX */ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); ++ gmx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); ++ ++ /* Wait for GMX RX to be idle */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg, ++ rx_idle, ==, 1, 10000)) ++ return -1; ++ /* Wait for GMX TX to be idle */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg, ++ tx_idle, ==, 1, 10000)) ++ return -1; ++ ++ /* GMX configure */ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); ++ gmx_cfg.s.speed = 1; ++ gmx_cfg.s.speed_msb = 0; ++ gmx_cfg.s.slottime = 1; ++ cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1); ++ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512); ++ cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192); ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); ++ ++ /* (7) Clear out any error state */ ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0, interface), ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0, interface))); ++ cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface), ++ cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface))); ++ cvmx_write_csr(CVMX_PCSXX_INT_REG(interface), ++ cvmx_read_csr(CVMX_PCSXX_INT_REG(interface))); ++ ++ /* Wait for receive link */ ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_PCSXX_STATUS1_REG(interface), union cvmx_pcsxx_status1_reg, ++ rcv_lnk, ==, 1, 10000)) ++ return -1; ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg, ++ xmtflt, ==, 0, 10000)) ++ return -1; ++ if (CVMX_WAIT_FOR_FIELD64 ++ (CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg, ++ rcvflt, ==, 0, 10000)) ++ return -1; ++ ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), gmx_rx_int_en.u64); ++ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64); ++ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64); ++ ++ cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0)); ++ ++ /* (8) Enable packet reception */ ++ xauiMiscCtl.s.gmxeno = 0; ++ cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); ++ ++ __cvmx_interrupt_pcsx_intx_en_reg_enable(0, interface); ++ __cvmx_interrupt_pcsx_intx_en_reg_enable(1, interface); ++ __cvmx_interrupt_pcsx_intx_en_reg_enable(2, interface); ++ __cvmx_interrupt_pcsx_intx_en_reg_enable(3, interface); ++ __cvmx_interrupt_pcsxx_int_en_reg_enable(interface); ++ __cvmx_interrupt_gmxx_enable(interface); ++ ++ return 0; ++} ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ union cvmx_gmxx_tx_xaui_ctl gmxx_tx_xaui_ctl; ++ union cvmx_gmxx_rx_xaui_ctl gmxx_rx_xaui_ctl; ++ union cvmx_pcsxx_status1_reg pcsxx_status1_reg; ++ cvmx_helper_link_info_t result; ++ ++ gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); ++ gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); ++ pcsxx_status1_reg.u64 = ++ cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface)); ++ result.u64 = 0; ++ ++ /* Only return a link if both RX and TX are happy */ ++ if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) && ++ (pcsxx_status1_reg.s.rcv_lnk == 1)) { ++ result.s.link_up = 1; ++ result.s.full_duplex = 1; ++ result.s.speed = 10000; ++ } else { ++ /* Disable GMX and PCSX interrupts. */ ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0); ++ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0); ++ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0); ++ } ++ return result; ++} ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ union cvmx_gmxx_tx_xaui_ctl gmxx_tx_xaui_ctl; ++ union cvmx_gmxx_rx_xaui_ctl gmxx_rx_xaui_ctl; ++ ++ gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); ++ gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); ++ ++ /* If the link shouldn't be up, then just return */ ++ if (!link_info.s.link_up) ++ return 0; ++ ++ /* Do nothing if both RX and TX are happy */ ++ if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0)) ++ return 0; ++ ++ /* Bring the link up */ ++ return __cvmx_helper_xaui_enable(interface); ++} ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, ++ int enable_internal, ++ int enable_external) ++{ ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ union cvmx_pcsxx_control1_reg pcsxx_control1_reg; ++ union cvmx_gmxx_xaui_ext_loopback gmxx_xaui_ext_loopback; ++ ++ /* Set the internal loop */ ++ pcsxx_control1_reg.u64 = ++ cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); ++ pcsxx_control1_reg.s.loopbck1 = enable_internal; ++ cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), ++ pcsxx_control1_reg.u64); ++ ++ /* Set the external loop */ ++ gmxx_xaui_ext_loopback.u64 = ++ cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface)); ++ gmxx_xaui_ext_loopback.s.en = enable_external; ++ cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), ++ gmxx_xaui_ext_loopback.u64); ++ ++ /* Take the link through a reset */ ++ return __cvmx_helper_xaui_enable(interface); ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper-xaui.h +@@ -0,0 +1,103 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * @file ++ * ++ * Functions for XAUI initialization, configuration, ++ * and monitoring. ++ * ++ */ ++#ifndef __CVMX_HELPER_XAUI_H__ ++#define __CVMX_HELPER_XAUI_H__ ++ ++/** ++ * Probe a XAUI interface and determine the number of ports ++ * connected to it. The XAUI interface should still be down ++ * after this call. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Number of ports on the interface. Zero to disable. ++ */ ++extern int __cvmx_helper_xaui_probe(int interface); ++ ++/** ++ * Bringup and enable a XAUI interface. After this call packet ++ * I/O should be fully functional. This is called with IPD ++ * enabled but PKO disabled. ++ * ++ * @interface: Interface to bring up ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_xaui_enable(int interface); ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++extern cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port); ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int __cvmx_helper_xaui_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info); ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, ++ int enable_internal, ++ int enable_external); ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper.c +@@ -0,0 +1,1058 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Helper functions for common, but complicated tasks. ++ * ++ */ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-fpa.h" ++#include "cvmx-pip.h" ++#include "cvmx-pko.h" ++#include "cvmx-ipd.h" ++#include "cvmx-spi.h" ++#include "cvmx-helper.h" ++#include "cvmx-helper-board.h" ++ ++#include "cvmx-pip-defs.h" ++#include "cvmx-smix-defs.h" ++#include "cvmx-asxx-defs.h" ++ ++/** ++ * cvmx_override_pko_queue_priority(int ipd_port, uint64_t ++ * priorities[16]) is a function pointer. It is meant to allow ++ * customization of the PKO queue priorities based on the port ++ * number. Users should set this pointer to a function before ++ * calling any cvmx-helper operations. ++ */ ++void (*cvmx_override_pko_queue_priority) (int pko_port, ++ uint64_t priorities[16]); ++ ++/** ++ * cvmx_override_ipd_port_setup(int ipd_port) is a function ++ * pointer. It is meant to allow customization of the IPD port ++ * setup before packet input/output comes online. It is called ++ * after cvmx-helper does the default IPD configuration, but ++ * before IPD is enabled. Users should set this pointer to a ++ * function before calling any cvmx-helper operations. ++ */ ++void (*cvmx_override_ipd_port_setup) (int ipd_port); ++ ++/* Port count per interface */ ++static int interface_port_count[4] = { 0, 0, 0, 0 }; ++ ++/* Port last configured link info index by IPD/PKO port */ ++static cvmx_helper_link_info_t ++ port_link_info[CVMX_PIP_NUM_INPUT_PORTS]; ++ ++/** ++ * Return the number of interfaces the chip has. Each interface ++ * may have multiple ports. Most chips support two interfaces, ++ * but the CNX0XX and CNX1XX are exceptions. These only support ++ * one interface. ++ * ++ * Returns Number of interfaces on chip ++ */ ++int cvmx_helper_get_number_of_interfaces(void) ++{ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ return 4; ++ else ++ return 3; ++} ++ ++/** ++ * Return the number of ports on an interface. Depending on the ++ * chip and configuration, this can be 1-16. A value of 0 ++ * specifies that the interface doesn't exist or isn't usable. ++ * ++ * @interface: Interface to get the port count for ++ * ++ * Returns Number of ports on interface. Can be Zero. ++ */ ++int cvmx_helper_ports_on_interface(int interface) ++{ ++ return interface_port_count[interface]; ++} ++ ++/** ++ * Get the operating mode of an interface. Depending on the Octeon ++ * chip and configuration, this function returns an enumeration ++ * of the type of packet I/O supported by an interface. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Mode of the interface. Unknown or unsupported interfaces return ++ * DISABLED. ++ */ ++cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) ++{ ++ union cvmx_gmxx_inf_mode mode; ++ if (interface == 2) ++ return CVMX_HELPER_INTERFACE_MODE_NPI; ++ ++ if (interface == 3) { ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX) ++ || OCTEON_IS_MODEL(OCTEON_CN52XX)) ++ return CVMX_HELPER_INTERFACE_MODE_LOOP; ++ else ++ return CVMX_HELPER_INTERFACE_MODE_DISABLED; ++ } ++ ++ if (interface == 0 ++ && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 ++ && cvmx_sysinfo_get()->board_rev_major == 1) { ++ /* ++ * Lie about interface type of CN3005 board. This ++ * board has a switch on port 1 like the other ++ * evaluation boards, but it is connected over RGMII ++ * instead of GMII. Report GMII mode so that the ++ * speed is forced to 1 Gbit full duplex. Other than ++ * some initial configuration (which does not use the ++ * output of this function) there is no difference in ++ * setup between GMII and RGMII modes. ++ */ ++ return CVMX_HELPER_INTERFACE_MODE_GMII; ++ } ++ ++ /* Interface 1 is always disabled on CN31XX and CN30XX */ ++ if ((interface == 1) ++ && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) ++ || OCTEON_IS_MODEL(OCTEON_CN50XX) ++ || OCTEON_IS_MODEL(OCTEON_CN52XX))) ++ return CVMX_HELPER_INTERFACE_MODE_DISABLED; ++ ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ switch (mode.cn56xx.mode) { ++ case 0: ++ return CVMX_HELPER_INTERFACE_MODE_DISABLED; ++ case 1: ++ return CVMX_HELPER_INTERFACE_MODE_XAUI; ++ case 2: ++ return CVMX_HELPER_INTERFACE_MODE_SGMII; ++ case 3: ++ return CVMX_HELPER_INTERFACE_MODE_PICMG; ++ default: ++ return CVMX_HELPER_INTERFACE_MODE_DISABLED; ++ } ++ } else { ++ if (!mode.s.en) ++ return CVMX_HELPER_INTERFACE_MODE_DISABLED; ++ ++ if (mode.s.type) { ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX)) ++ return CVMX_HELPER_INTERFACE_MODE_SPI; ++ else ++ return CVMX_HELPER_INTERFACE_MODE_GMII; ++ } else ++ return CVMX_HELPER_INTERFACE_MODE_RGMII; ++ } ++} ++ ++/** ++ * Configure the IPD/PIP tagging and QoS options for a specific ++ * port. This function determines the POW work queue entry ++ * contents for a port. The setup performed here is controlled by ++ * the defines in executive-config.h. ++ * ++ * @ipd_port: Port to configure. This follows the IPD numbering, not the ++ * per interface numbering ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_port_setup_ipd(int ipd_port) ++{ ++ union cvmx_pip_prt_cfgx port_config; ++ union cvmx_pip_prt_tagx tag_config; ++ ++ port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); ++ tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); ++ ++ /* Have each port go to a different POW queue */ ++ port_config.s.qos = ipd_port & 0x7; ++ ++ /* Process the headers and place the IP header in the work queue */ ++ port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; ++ ++ tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; ++ tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; ++ tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; ++ tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; ++ tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; ++ tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; ++ tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; ++ tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; ++ tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; ++ tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; ++ tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; ++ tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; ++ tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; ++ tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; ++ tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; ++ tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; ++ /* Put all packets in group 0. Other groups can be used by the app */ ++ tag_config.s.grp = 0; ++ ++ cvmx_pip_config_port(ipd_port, port_config, tag_config); ++ ++ /* Give the user a chance to override our setting for each port */ ++ if (cvmx_override_ipd_port_setup) ++ cvmx_override_ipd_port_setup(ipd_port); ++ ++ return 0; ++} ++ ++/** ++ * This function probes an interface to determine the actual ++ * number of hardware ports connected to it. It doesn't setup the ++ * ports or enable them. The main goal here is to set the global ++ * interface_port_count[interface] correctly. Hardware setup of the ++ * ports will be performed later. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_helper_interface_probe(int interface) ++{ ++ /* At this stage in the game we don't want packets to be moving yet. ++ The following probe calls should perform hardware setup ++ needed to determine port counts. Receive must still be disabled */ ++ switch (cvmx_helper_interface_get_mode(interface)) { ++ /* These types don't support ports to IPD/PKO */ ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ interface_port_count[interface] = 0; ++ break; ++ /* XAUI is a single high speed port */ ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ interface_port_count[interface] = ++ __cvmx_helper_xaui_probe(interface); ++ break; ++ /* ++ * RGMII/GMII/MII are all treated about the same. Most ++ * functions refer to these ports as RGMII. ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ interface_port_count[interface] = ++ __cvmx_helper_rgmii_probe(interface); ++ break; ++ /* ++ * SPI4 can have 1-16 ports depending on the device at ++ * the other end. ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ interface_port_count[interface] = ++ __cvmx_helper_spi_probe(interface); ++ break; ++ /* ++ * SGMII can have 1-4 ports depending on how many are ++ * hooked up. ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ interface_port_count[interface] = ++ __cvmx_helper_sgmii_probe(interface); ++ break; ++ /* PCI target Network Packet Interface */ ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ interface_port_count[interface] = ++ __cvmx_helper_npi_probe(interface); ++ break; ++ /* ++ * Special loopback only ports. These are not the same ++ * as other ports in loopback mode. ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ interface_port_count[interface] = ++ __cvmx_helper_loop_probe(interface); ++ break; ++ } ++ ++ interface_port_count[interface] = ++ __cvmx_helper_board_interface_probe(interface, ++ interface_port_count ++ [interface]); ++ ++ /* Make sure all global variables propagate to other cores */ ++ CVMX_SYNCWS; ++ ++ return 0; ++} ++ ++/** ++ * Setup the IPD/PIP for the ports on an interface. Packet ++ * classification and tagging are set for every port on the ++ * interface. The number of ports on the interface must already ++ * have been probed. ++ * ++ * @interface: Interface to setup IPD/PIP for ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_interface_setup_ipd(int interface) ++{ ++ int ipd_port = cvmx_helper_get_ipd_port(interface, 0); ++ int num_ports = interface_port_count[interface]; ++ ++ while (num_ports--) { ++ __cvmx_helper_port_setup_ipd(ipd_port); ++ ipd_port++; ++ } ++ return 0; ++} ++ ++/** ++ * Setup global setting for IPD/PIP not related to a specific ++ * interface or port. This must be called before IPD is enabled. ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++static int __cvmx_helper_global_setup_ipd(void) ++{ ++ /* Setup the global packet input options */ ++ cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8, ++ CVMX_HELPER_FIRST_MBUFF_SKIP / 8, ++ CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8, ++ /* The +8 is to account for the next ptr */ ++ (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128, ++ /* The +8 is to account for the next ptr */ ++ (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128, ++ CVMX_FPA_WQE_POOL, ++ CVMX_IPD_OPC_MODE_STT, ++ CVMX_HELPER_ENABLE_BACK_PRESSURE); ++ return 0; ++} ++ ++/** ++ * Setup the PKO for the ports on an interface. The number of ++ * queues per port and the priority of each PKO output queue ++ * is set here. PKO must be disabled when this function is called. ++ * ++ * @interface: Interface to setup PKO for ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_interface_setup_pko(int interface) ++{ ++ /* ++ * Each packet output queue has an associated priority. The ++ * higher the priority, the more often it can send a packet. A ++ * priority of 8 means it can send in all 8 rounds of ++ * contention. We're going to make each queue one less than ++ * the last. The vector of priorities has been extended to ++ * support CN5xxx CPUs, where up to 16 queues can be ++ * associated to a port. To keep backward compatibility we ++ * don't change the initial 8 priorities and replicate them in ++ * the second half. With per-core PKO queues (PKO lockless ++ * operation) all queues have the same priority. ++ */ ++ uint64_t priorities[16] = ++ { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 }; ++ ++ /* ++ * Setup the IPD/PIP and PKO for the ports discovered ++ * above. Here packet classification, tagging and output ++ * priorities are set. ++ */ ++ int ipd_port = cvmx_helper_get_ipd_port(interface, 0); ++ int num_ports = interface_port_count[interface]; ++ while (num_ports--) { ++ /* ++ * Give the user a chance to override the per queue ++ * priorities. ++ */ ++ if (cvmx_override_pko_queue_priority) ++ cvmx_override_pko_queue_priority(ipd_port, priorities); ++ ++ cvmx_pko_config_port(ipd_port, ++ cvmx_pko_get_base_queue_per_core(ipd_port, ++ 0), ++ cvmx_pko_get_num_queues(ipd_port), ++ priorities); ++ ipd_port++; ++ } ++ return 0; ++} ++ ++/** ++ * Setup global setting for PKO not related to a specific ++ * interface or port. This must be called before PKO is enabled. ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++static int __cvmx_helper_global_setup_pko(void) ++{ ++ /* ++ * Disable tagwait FAU timeout. This needs to be done before ++ * anyone might start packet output using tags. ++ */ ++ union cvmx_iob_fau_timeout fau_to; ++ fau_to.u64 = 0; ++ fau_to.s.tout_val = 0xfff; ++ fau_to.s.tout_enb = 0; ++ cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); ++ return 0; ++} ++ ++/** ++ * Setup global backpressure setting. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_global_setup_backpressure(void) ++{ ++#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE ++ /* Disable backpressure if configured to do so */ ++ /* Disable backpressure (pause frame) generation */ ++ int num_interfaces = cvmx_helper_get_number_of_interfaces(); ++ int interface; ++ for (interface = 0; interface < num_interfaces; interface++) { ++ switch (cvmx_helper_interface_get_mode(interface)) { ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ cvmx_gmx_set_backpressure_override(interface, 0xf); ++ break; ++ } ++ } ++#endif ++ ++ return 0; ++} ++ ++/** ++ * Enable packet input/output from the hardware. This function is ++ * called after all internal setup is complete and IPD is enabled. ++ * After this function completes, packets will be accepted from the ++ * hardware ports. PKO should still be disabled to make sure packets ++ * aren't sent out partially setup hardware. ++ * ++ * @interface: Interface to enable ++ * ++ * Returns Zero on success, negative on failure ++ */ ++static int __cvmx_helper_packet_hardware_enable(int interface) ++{ ++ int result = 0; ++ switch (cvmx_helper_interface_get_mode(interface)) { ++ /* These types don't support ports to IPD/PKO */ ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ /* Nothing to do */ ++ break; ++ /* XAUI is a single high speed port */ ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ result = __cvmx_helper_xaui_enable(interface); ++ break; ++ /* ++ * RGMII/GMII/MII are all treated about the same. Most ++ * functions refer to these ports as RGMII ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ result = __cvmx_helper_rgmii_enable(interface); ++ break; ++ /* ++ * SPI4 can have 1-16 ports depending on the device at ++ * the other end ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ result = __cvmx_helper_spi_enable(interface); ++ break; ++ /* ++ * SGMII can have 1-4 ports depending on how many are ++ * hooked up ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ result = __cvmx_helper_sgmii_enable(interface); ++ break; ++ /* PCI target Network Packet Interface */ ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ result = __cvmx_helper_npi_enable(interface); ++ break; ++ /* ++ * Special loopback only ports. These are not the same ++ * as other ports in loopback mode ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ result = __cvmx_helper_loop_enable(interface); ++ break; ++ } ++ result |= __cvmx_helper_board_hardware_enable(interface); ++ return result; ++} ++ ++/** ++ * Function to adjust internal IPD pointer alignments ++ * ++ * Returns 0 on success ++ * !0 on failure ++ */ ++int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) ++{ ++#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \ ++ (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP) ++#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \ ++ (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP) ++#define FIX_IPD_OUTPORT 0 ++ /* Ports 0-15 are interface 0, 16-31 are interface 1 */ ++#define INTERFACE(port) (port >> 4) ++#define INDEX(port) (port & 0xf) ++ uint64_t *p64; ++ cvmx_pko_command_word0_t pko_command; ++ union cvmx_buf_ptr g_buffer, pkt_buffer; ++ cvmx_wqe_t *work; ++ int size, num_segs = 0, wqe_pcnt, pkt_pcnt; ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ int retry_cnt; ++ int retry_loop_cnt; ++ int mtu; ++ int i; ++ cvmx_helper_link_info_t link_info; ++ ++ /* Save values for restore at end */ ++ uint64_t prtx_cfg = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t tx_ptr_en = ++ cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t rx_ptr_en = ++ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t rxx_jabber = ++ cvmx_read_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); ++ uint64_t frame_max = ++ cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); ++ ++ /* Configure port to gig FDX as required for loopback mode */ ++ cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT); ++ ++ /* ++ * Disable reception on all ports so if traffic is present it ++ * will not interfere. ++ */ ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0); ++ ++ cvmx_wait(100000000ull); ++ ++ for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) { ++ retry_cnt = 100000; ++ wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT); ++ pkt_pcnt = (wqe_pcnt >> 7) & 0x7f; ++ wqe_pcnt &= 0x7f; ++ ++ num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3; ++ ++ if (num_segs == 0) ++ goto fix_ipd_exit; ++ ++ num_segs += 1; ++ ++ size = ++ FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES + ++ ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) - ++ (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2); ++ ++ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), ++ 1 << INDEX(FIX_IPD_OUTPORT)); ++ CVMX_SYNC; ++ ++ g_buffer.u64 = 0; ++ g_buffer.s.addr = ++ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL)); ++ if (g_buffer.s.addr == 0) { ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " ++ "buffer allocation failure.\n"); ++ goto fix_ipd_exit; ++ } ++ ++ g_buffer.s.pool = CVMX_FPA_WQE_POOL; ++ g_buffer.s.size = num_segs; ++ ++ pkt_buffer.u64 = 0; ++ pkt_buffer.s.addr = ++ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL)); ++ if (pkt_buffer.s.addr == 0) { ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " ++ "buffer allocation failure.\n"); ++ goto fix_ipd_exit; ++ } ++ pkt_buffer.s.i = 1; ++ pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL; ++ pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES; ++ ++ p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr); ++ p64[0] = 0xffffffffffff0000ull; ++ p64[1] = 0x08004510ull; ++ p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull; ++ p64[3] = 0x3a5fc0a81073c0a8ull; ++ ++ for (i = 0; i < num_segs; i++) { ++ if (i > 0) ++ pkt_buffer.s.size = ++ FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES; ++ ++ if (i == (num_segs - 1)) ++ pkt_buffer.s.i = 0; ++ ++ *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr + ++ 8 * i) = pkt_buffer.u64; ++ } ++ ++ /* Build the PKO command */ ++ pko_command.u64 = 0; ++ pko_command.s.segs = num_segs; ++ pko_command.s.total_bytes = size; ++ pko_command.s.dontfree = 0; ++ pko_command.s.gather = 1; ++ ++ gmx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ 1 << INDEX(FIX_IPD_OUTPORT)); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ 1 << INDEX(FIX_IPD_OUTPORT)); ++ ++ mtu = ++ cvmx_read_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT))); ++ cvmx_write_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX ++ (INDEX(FIX_IPD_OUTPORT), ++ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); ++ ++ cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, ++ cvmx_pko_get_base_queue ++ (FIX_IPD_OUTPORT), ++ CVMX_PKO_LOCK_CMD_QUEUE); ++ cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, ++ cvmx_pko_get_base_queue ++ (FIX_IPD_OUTPORT), pko_command, ++ g_buffer, CVMX_PKO_LOCK_CMD_QUEUE); ++ ++ CVMX_SYNC; ++ ++ do { ++ work = cvmx_pow_work_request_sync(CVMX_POW_WAIT); ++ retry_cnt--; ++ } while ((work == NULL) && (retry_cnt > 0)); ++ ++ if (!retry_cnt) ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " ++ "get_work() timeout occured.\n"); ++ ++ /* Free packet */ ++ if (work) ++ cvmx_helper_free_packet_data(work); ++ } ++ ++fix_ipd_exit: ++ ++ /* Return CSR configs to saved values */ ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), ++ prtx_cfg); ++ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ tx_ptr_en); ++ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), ++ rx_ptr_en); ++ cvmx_write_csr(CVMX_GMXX_RXX_JABBER ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), ++ rxx_jabber); ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX ++ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), ++ frame_max); ++ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0); ++ /* Set link to down so autonegotiation will set it up again */ ++ link_info.u64 = 0; ++ cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info); ++ ++ /* ++ * Bring the link back up as autonegotiation is not done in ++ * user applications. ++ */ ++ cvmx_helper_link_autoconf(FIX_IPD_OUTPORT); ++ ++ CVMX_SYNC; ++ if (num_segs) ++ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n"); ++ ++ return !!num_segs; ++ ++} ++ ++/** ++ * Called after all internal packet IO paths are setup. This ++ * function enables IPD/PIP and begins packet input and output. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_helper_ipd_and_packet_input_enable(void) ++{ ++ int num_interfaces; ++ int interface; ++ ++ /* Enable IPD */ ++ cvmx_ipd_enable(); ++ ++ /* ++ * Time to enable hardware ports packet input and output. Note ++ * that at this point IPD/PIP must be fully functional and PKO ++ * must be disabled ++ */ ++ num_interfaces = cvmx_helper_get_number_of_interfaces(); ++ for (interface = 0; interface < num_interfaces; interface++) { ++ if (cvmx_helper_ports_on_interface(interface) > 0) ++ __cvmx_helper_packet_hardware_enable(interface); ++ } ++ ++ /* Finally enable PKO now that the entire path is up and running */ ++ cvmx_pko_enable(); ++ ++ if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) ++ || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) ++ && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) ++ __cvmx_helper_errata_fix_ipd_ptr_alignment(); ++ return 0; ++} ++ ++/** ++ * Initialize the PIP, IPD, and PKO hardware to support ++ * simple priority based queues for the ethernet ports. Each ++ * port is configured with a number of priority queues based ++ * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower ++ * priority than the previous. ++ * ++ * Returns Zero on success, non-zero on failure ++ */ ++int cvmx_helper_initialize_packet_io_global(void) ++{ ++ int result = 0; ++ int interface; ++ union cvmx_l2c_cfg l2c_cfg; ++ union cvmx_smix_en smix_en; ++ const int num_interfaces = cvmx_helper_get_number_of_interfaces(); ++ ++ /* ++ * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to ++ * be disabled. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) ++ __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); ++ ++ /* ++ * Tell L2 to give the IOB statically higher priority compared ++ * to the cores. This avoids conditions where IO blocks might ++ * be starved under very high L2 loads. ++ */ ++ l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); ++ l2c_cfg.s.lrf_arb_mode = 0; ++ l2c_cfg.s.rfb_arb_mode = 0; ++ cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); ++ ++ /* Make sure SMI/MDIO is enabled so we can query PHYs */ ++ smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0)); ++ if (!smix_en.s.en) { ++ smix_en.s.en = 1; ++ cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64); ++ } ++ ++ /* Newer chips actually have two SMI/MDIO interfaces */ ++ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && ++ !OCTEON_IS_MODEL(OCTEON_CN58XX) && ++ !OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1)); ++ if (!smix_en.s.en) { ++ smix_en.s.en = 1; ++ cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64); ++ } ++ } ++ ++ cvmx_pko_initialize_global(); ++ for (interface = 0; interface < num_interfaces; interface++) { ++ result |= cvmx_helper_interface_probe(interface); ++ if (cvmx_helper_ports_on_interface(interface) > 0) ++ cvmx_dprintf("Interface %d has %d ports (%s)\n", ++ interface, ++ cvmx_helper_ports_on_interface(interface), ++ cvmx_helper_interface_mode_to_string ++ (cvmx_helper_interface_get_mode ++ (interface))); ++ result |= __cvmx_helper_interface_setup_ipd(interface); ++ result |= __cvmx_helper_interface_setup_pko(interface); ++ } ++ ++ result |= __cvmx_helper_global_setup_ipd(); ++ result |= __cvmx_helper_global_setup_pko(); ++ ++ /* Enable any flow control and backpressure */ ++ result |= __cvmx_helper_global_setup_backpressure(); ++ ++#if CVMX_HELPER_ENABLE_IPD ++ result |= cvmx_helper_ipd_and_packet_input_enable(); ++#endif ++ return result; ++} ++ ++/** ++ * Does core local initialization for packet io ++ * ++ * Returns Zero on success, non-zero on failure ++ */ ++int cvmx_helper_initialize_packet_io_local(void) ++{ ++ return cvmx_pko_initialize_local(); ++} ++ ++/** ++ * Auto configure an IPD/PKO port link state and speed. This ++ * function basically does the equivalent of: ++ * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); ++ * ++ * @ipd_port: IPD/PKO port to auto configure ++ * ++ * Returns Link state after configure ++ */ ++cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) ++{ ++ cvmx_helper_link_info_t link_info; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ ++ if (index >= cvmx_helper_ports_on_interface(interface)) { ++ link_info.u64 = 0; ++ return link_info; ++ } ++ ++ link_info = cvmx_helper_link_get(ipd_port); ++ if (link_info.u64 == port_link_info[ipd_port].u64) ++ return link_info; ++ ++ /* If we fail to set the link speed, port_link_info will not change */ ++ cvmx_helper_link_set(ipd_port, link_info); ++ ++ /* ++ * port_link_info should be the current value, which will be ++ * different than expect if cvmx_helper_link_set() failed. ++ */ ++ return port_link_info[ipd_port]; ++} ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) ++{ ++ cvmx_helper_link_info_t result; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ ++ /* The default result will be a down link unless the code below ++ changes it */ ++ result.u64 = 0; ++ ++ if (index >= cvmx_helper_ports_on_interface(interface)) ++ return result; ++ ++ switch (cvmx_helper_interface_get_mode(interface)) { ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ /* Network links are not supported */ ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ result = __cvmx_helper_xaui_link_get(ipd_port); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ if (index == 0) ++ result = __cvmx_helper_rgmii_link_get(ipd_port); ++ else { ++ result.s.full_duplex = 1; ++ result.s.link_up = 1; ++ result.s.speed = 1000; ++ } ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ result = __cvmx_helper_rgmii_link_get(ipd_port); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ result = __cvmx_helper_spi_link_get(ipd_port); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ result = __cvmx_helper_sgmii_link_get(ipd_port); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ /* Network links are not supported */ ++ break; ++ } ++ return result; ++} ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) ++{ ++ int result = -1; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ ++ if (index >= cvmx_helper_ports_on_interface(interface)) ++ return -1; ++ ++ switch (cvmx_helper_interface_get_mode(interface)) { ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ result = __cvmx_helper_xaui_link_set(ipd_port, link_info); ++ break; ++ /* ++ * RGMII/GMII/MII are all treated about the same. Most ++ * functions refer to these ports as RGMII. ++ */ ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ result = __cvmx_helper_spi_link_set(ipd_port, link_info); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ break; ++ } ++ /* Set the port_link_info here so that the link status is updated ++ no matter how cvmx_helper_link_set is called. We don't change ++ the value if link_set failed */ ++ if (result == 0) ++ port_link_info[ipd_port].u64 = link_info.u64; ++ return result; ++} ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, ++ int enable_external) ++{ ++ int result = -1; ++ int interface = cvmx_helper_get_interface_num(ipd_port); ++ int index = cvmx_helper_get_interface_index_num(ipd_port); ++ ++ if (index >= cvmx_helper_ports_on_interface(interface)) ++ return -1; ++ ++ switch (cvmx_helper_interface_get_mode(interface)) { ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ result = ++ __cvmx_helper_xaui_configure_loopback(ipd_port, ++ enable_internal, ++ enable_external); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ result = ++ __cvmx_helper_rgmii_configure_loopback(ipd_port, ++ enable_internal, ++ enable_external); ++ break; ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ result = ++ __cvmx_helper_sgmii_configure_loopback(ipd_port, ++ enable_internal, ++ enable_external); ++ break; ++ } ++ return result; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-helper.h +@@ -0,0 +1,227 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Helper functions for common, but complicated tasks. ++ * ++ */ ++ ++#ifndef __CVMX_HELPER_H__ ++#define __CVMX_HELPER_H__ ++ ++#include "cvmx-config.h" ++#include "cvmx-fpa.h" ++#include "cvmx-wqe.h" ++ ++typedef enum { ++ CVMX_HELPER_INTERFACE_MODE_DISABLED, ++ CVMX_HELPER_INTERFACE_MODE_RGMII, ++ CVMX_HELPER_INTERFACE_MODE_GMII, ++ CVMX_HELPER_INTERFACE_MODE_SPI, ++ CVMX_HELPER_INTERFACE_MODE_PCIE, ++ CVMX_HELPER_INTERFACE_MODE_XAUI, ++ CVMX_HELPER_INTERFACE_MODE_SGMII, ++ CVMX_HELPER_INTERFACE_MODE_PICMG, ++ CVMX_HELPER_INTERFACE_MODE_NPI, ++ CVMX_HELPER_INTERFACE_MODE_LOOP, ++} cvmx_helper_interface_mode_t; ++ ++typedef union { ++ uint64_t u64; ++ struct { ++ uint64_t reserved_20_63:44; ++ uint64_t link_up:1; /**< Is the physical link up? */ ++ uint64_t full_duplex:1; /**< 1 if the link is full duplex */ ++ uint64_t speed:18; /**< Speed of the link in Mbps */ ++ } s; ++} cvmx_helper_link_info_t; ++ ++#include "cvmx-helper-fpa.h" ++ ++#include ++#include "cvmx-helper-loop.h" ++#include "cvmx-helper-npi.h" ++#include "cvmx-helper-rgmii.h" ++#include "cvmx-helper-sgmii.h" ++#include "cvmx-helper-spi.h" ++#include "cvmx-helper-util.h" ++#include "cvmx-helper-xaui.h" ++ ++/** ++ * cvmx_override_pko_queue_priority(int ipd_port, uint64_t ++ * priorities[16]) is a function pointer. It is meant to allow ++ * customization of the PKO queue priorities based on the port ++ * number. Users should set this pointer to a function before ++ * calling any cvmx-helper operations. ++ */ ++extern void (*cvmx_override_pko_queue_priority) (int pko_port, ++ uint64_t priorities[16]); ++ ++/** ++ * cvmx_override_ipd_port_setup(int ipd_port) is a function ++ * pointer. It is meant to allow customization of the IPD port ++ * setup before packet input/output comes online. It is called ++ * after cvmx-helper does the default IPD configuration, but ++ * before IPD is enabled. Users should set this pointer to a ++ * function before calling any cvmx-helper operations. ++ */ ++extern void (*cvmx_override_ipd_port_setup) (int ipd_port); ++ ++/** ++ * This function enables the IPD and also enables the packet interfaces. ++ * The packet interfaces (RGMII and SPI) must be enabled after the ++ * IPD. This should be called by the user program after any additional ++ * IPD configuration changes are made if CVMX_HELPER_ENABLE_IPD ++ * is not set in the executive-config.h file. ++ * ++ * Returns 0 on success ++ * -1 on failure ++ */ ++extern int cvmx_helper_ipd_and_packet_input_enable(void); ++ ++/** ++ * Initialize the PIP, IPD, and PKO hardware to support ++ * simple priority based queues for the ethernet ports. Each ++ * port is configured with a number of priority queues based ++ * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower ++ * priority than the previous. ++ * ++ * Returns Zero on success, non-zero on failure ++ */ ++extern int cvmx_helper_initialize_packet_io_global(void); ++ ++/** ++ * Does core local initialization for packet io ++ * ++ * Returns Zero on success, non-zero on failure ++ */ ++extern int cvmx_helper_initialize_packet_io_local(void); ++ ++/** ++ * Returns the number of ports on the given interface. ++ * The interface must be initialized before the port count ++ * can be returned. ++ * ++ * @interface: Which interface to return port count for. ++ * ++ * Returns Port count for interface ++ * -1 for uninitialized interface ++ */ ++extern int cvmx_helper_ports_on_interface(int interface); ++ ++/** ++ * Return the number of interfaces the chip has. Each interface ++ * may have multiple ports. Most chips support two interfaces, ++ * but the CNX0XX and CNX1XX are exceptions. These only support ++ * one interface. ++ * ++ * Returns Number of interfaces on chip ++ */ ++extern int cvmx_helper_get_number_of_interfaces(void); ++ ++/** ++ * Get the operating mode of an interface. Depending on the Octeon ++ * chip and configuration, this function returns an enumeration ++ * of the type of packet I/O supported by an interface. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Mode of the interface. Unknown or unsupported interfaces return ++ * DISABLED. ++ */ ++extern cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int ++ interface); ++ ++/** ++ * Auto configure an IPD/PKO port link state and speed. This ++ * function basically does the equivalent of: ++ * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); ++ * ++ * @ipd_port: IPD/PKO port to auto configure ++ * ++ * Returns Link state after configure ++ */ ++extern cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port); ++ ++/** ++ * Return the link state of an IPD/PKO port as returned by ++ * auto negotiation. The result of this function may not match ++ * Octeon's link config if auto negotiation has changed since ++ * the last call to cvmx_helper_link_set(). ++ * ++ * @ipd_port: IPD/PKO port to query ++ * ++ * Returns Link state ++ */ ++extern cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port); ++ ++/** ++ * Configure an IPD/PKO port for the specified link state. This ++ * function does not influence auto negotiation at the PHY level. ++ * The passed link state must always match the link state returned ++ * by cvmx_helper_link_get(). It is normally best to use ++ * cvmx_helper_link_autoconf() instead. ++ * ++ * @ipd_port: IPD/PKO port to configure ++ * @link_info: The new link state ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int cvmx_helper_link_set(int ipd_port, ++ cvmx_helper_link_info_t link_info); ++ ++/** ++ * This function probes an interface to determine the actual ++ * number of hardware ports connected to it. It doesn't setup the ++ * ports or enable them. The main goal here is to set the global ++ * interface_port_count[interface] correctly. Hardware setup of the ++ * ports will be performed later. ++ * ++ * @interface: Interface to probe ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int cvmx_helper_interface_probe(int interface); ++ ++/** ++ * Configure a port for internal and/or external loopback. Internal loopback ++ * causes packets sent by the port to be received by Octeon. External loopback ++ * causes packets received from the wire to sent out again. ++ * ++ * @ipd_port: IPD/PKO port to loopback. ++ * @enable_internal: ++ * Non zero if you want internal loopback ++ * @enable_external: ++ * Non zero if you want external loopback ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++extern int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, ++ int enable_external); ++ ++#endif /* __CVMX_HELPER_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-interrupt-decodes.c +@@ -0,0 +1,371 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2009 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Automatically generated functions useful for enabling ++ * and decoding RSL_INT_BLOCKS interrupts. ++ * ++ */ ++ ++#include ++ ++#include "cvmx-gmxx-defs.h" ++#include "cvmx-pcsx-defs.h" ++#include "cvmx-pcsxx-defs.h" ++#include "cvmx-spxx-defs.h" ++#include "cvmx-stxx-defs.h" ++ ++#ifndef PRINT_ERROR ++#define PRINT_ERROR(format, ...) ++#endif ++ ++ ++/** ++ * __cvmx_interrupt_gmxx_rxx_int_en_enable enables all interrupt bits in cvmx_gmxx_rxx_int_en_t ++ */ ++void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block) ++{ ++ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, block), ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, block))); ++ gmx_rx_int_en.u64 = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_29_63 */ ++ gmx_rx_int_en.s.hg2cc = 1; ++ gmx_rx_int_en.s.hg2fld = 1; ++ gmx_rx_int_en.s.undat = 1; ++ gmx_rx_int_en.s.uneop = 1; ++ gmx_rx_int_en.s.unsop = 1; ++ gmx_rx_int_en.s.bad_term = 1; ++ gmx_rx_int_en.s.bad_seq = 1; ++ gmx_rx_int_en.s.rem_fault = 1; ++ gmx_rx_int_en.s.loc_fault = 1; ++ gmx_rx_int_en.s.pause_drp = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_16_18 */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_9_9 */ ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_5_6 */ ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_2_2 */ ++ gmx_rx_int_en.s.carext = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_0_0 */ ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN30XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_19_63 */ ++ /*gmx_rx_int_en.s.phy_dupx = 1; */ ++ /*gmx_rx_int_en.s.phy_spd = 1; */ ++ /*gmx_rx_int_en.s.phy_link = 1; */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ gmx_rx_int_en.s.niberr = 1; ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ ++ gmx_rx_int_en.s.alnerr = 1; ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ gmx_rx_int_en.s.maxerr = 1; ++ gmx_rx_int_en.s.carext = 1; ++ gmx_rx_int_en.s.minerr = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN50XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_20_63 */ ++ gmx_rx_int_en.s.pause_drp = 1; ++ /*gmx_rx_int_en.s.phy_dupx = 1; */ ++ /*gmx_rx_int_en.s.phy_spd = 1; */ ++ /*gmx_rx_int_en.s.phy_link = 1; */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ gmx_rx_int_en.s.niberr = 1; ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_6_6 */ ++ gmx_rx_int_en.s.alnerr = 1; ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_2_2 */ ++ gmx_rx_int_en.s.carext = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_0_0 */ ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_19_63 */ ++ /*gmx_rx_int_en.s.phy_dupx = 1; */ ++ /*gmx_rx_int_en.s.phy_spd = 1; */ ++ /*gmx_rx_int_en.s.phy_link = 1; */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ gmx_rx_int_en.s.niberr = 1; ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ ++ gmx_rx_int_en.s.alnerr = 1; ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ gmx_rx_int_en.s.maxerr = 1; ++ gmx_rx_int_en.s.carext = 1; ++ gmx_rx_int_en.s.minerr = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN31XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_19_63 */ ++ /*gmx_rx_int_en.s.phy_dupx = 1; */ ++ /*gmx_rx_int_en.s.phy_spd = 1; */ ++ /*gmx_rx_int_en.s.phy_link = 1; */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ gmx_rx_int_en.s.niberr = 1; ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ ++ gmx_rx_int_en.s.alnerr = 1; ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ gmx_rx_int_en.s.maxerr = 1; ++ gmx_rx_int_en.s.carext = 1; ++ gmx_rx_int_en.s.minerr = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_20_63 */ ++ gmx_rx_int_en.s.pause_drp = 1; ++ /*gmx_rx_int_en.s.phy_dupx = 1; */ ++ /*gmx_rx_int_en.s.phy_spd = 1; */ ++ /*gmx_rx_int_en.s.phy_link = 1; */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ gmx_rx_int_en.s.niberr = 1; ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ ++ gmx_rx_int_en.s.alnerr = 1; ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ gmx_rx_int_en.s.maxerr = 1; ++ gmx_rx_int_en.s.carext = 1; ++ gmx_rx_int_en.s.minerr = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ /* Skipping gmx_rx_int_en.s.reserved_29_63 */ ++ gmx_rx_int_en.s.hg2cc = 1; ++ gmx_rx_int_en.s.hg2fld = 1; ++ gmx_rx_int_en.s.undat = 1; ++ gmx_rx_int_en.s.uneop = 1; ++ gmx_rx_int_en.s.unsop = 1; ++ gmx_rx_int_en.s.bad_term = 1; ++ gmx_rx_int_en.s.bad_seq = 0; ++ gmx_rx_int_en.s.rem_fault = 1; ++ gmx_rx_int_en.s.loc_fault = 0; ++ gmx_rx_int_en.s.pause_drp = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_16_18 */ ++ /*gmx_rx_int_en.s.ifgerr = 1; */ ++ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ ++ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ ++ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ ++ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ ++ gmx_rx_int_en.s.ovrerr = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_9_9 */ ++ gmx_rx_int_en.s.skperr = 1; ++ gmx_rx_int_en.s.rcverr = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_5_6 */ ++ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ ++ gmx_rx_int_en.s.jabber = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_2_2 */ ++ gmx_rx_int_en.s.carext = 1; ++ /* Skipping gmx_rx_int_en.s.reserved_0_0 */ ++ } ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, block), gmx_rx_int_en.u64); ++} ++/** ++ * __cvmx_interrupt_pcsx_intx_en_reg_enable enables all interrupt bits in cvmx_pcsx_intx_en_reg_t ++ */ ++void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block) ++{ ++ union cvmx_pcsx_intx_en_reg pcs_int_en_reg; ++ cvmx_write_csr(CVMX_PCSX_INTX_REG(index, block), ++ cvmx_read_csr(CVMX_PCSX_INTX_REG(index, block))); ++ pcs_int_en_reg.u64 = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) { ++ /* Skipping pcs_int_en_reg.s.reserved_12_63 */ ++ /*pcs_int_en_reg.s.dup = 1; // This happens during normal operation */ ++ pcs_int_en_reg.s.sync_bad_en = 1; ++ pcs_int_en_reg.s.an_bad_en = 1; ++ pcs_int_en_reg.s.rxlock_en = 1; ++ pcs_int_en_reg.s.rxbad_en = 1; ++ /*pcs_int_en_reg.s.rxerr_en = 1; // This happens during normal operation */ ++ pcs_int_en_reg.s.txbad_en = 1; ++ pcs_int_en_reg.s.txfifo_en = 1; ++ pcs_int_en_reg.s.txfifu_en = 1; ++ pcs_int_en_reg.s.an_err_en = 1; ++ /*pcs_int_en_reg.s.xmit_en = 1; // This happens during normal operation */ ++ /*pcs_int_en_reg.s.lnkspd_en = 1; // This happens during normal operation */ ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ /* Skipping pcs_int_en_reg.s.reserved_12_63 */ ++ /*pcs_int_en_reg.s.dup = 1; // This happens during normal operation */ ++ pcs_int_en_reg.s.sync_bad_en = 1; ++ pcs_int_en_reg.s.an_bad_en = 1; ++ pcs_int_en_reg.s.rxlock_en = 1; ++ pcs_int_en_reg.s.rxbad_en = 1; ++ /*pcs_int_en_reg.s.rxerr_en = 1; // This happens during normal operation */ ++ pcs_int_en_reg.s.txbad_en = 1; ++ pcs_int_en_reg.s.txfifo_en = 1; ++ pcs_int_en_reg.s.txfifu_en = 1; ++ pcs_int_en_reg.s.an_err_en = 1; ++ /*pcs_int_en_reg.s.xmit_en = 1; // This happens during normal operation */ ++ /*pcs_int_en_reg.s.lnkspd_en = 1; // This happens during normal operation */ ++ } ++ cvmx_write_csr(CVMX_PCSX_INTX_EN_REG(index, block), pcs_int_en_reg.u64); ++} ++/** ++ * __cvmx_interrupt_pcsxx_int_en_reg_enable enables all interrupt bits in cvmx_pcsxx_int_en_reg_t ++ */ ++void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index) ++{ ++ union cvmx_pcsxx_int_en_reg pcsx_int_en_reg; ++ cvmx_write_csr(CVMX_PCSXX_INT_REG(index), ++ cvmx_read_csr(CVMX_PCSXX_INT_REG(index))); ++ pcsx_int_en_reg.u64 = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) { ++ /* Skipping pcsx_int_en_reg.s.reserved_6_63 */ ++ pcsx_int_en_reg.s.algnlos_en = 1; ++ pcsx_int_en_reg.s.synlos_en = 1; ++ pcsx_int_en_reg.s.bitlckls_en = 1; ++ pcsx_int_en_reg.s.rxsynbad_en = 1; ++ pcsx_int_en_reg.s.rxbad_en = 1; ++ pcsx_int_en_reg.s.txflt_en = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ /* Skipping pcsx_int_en_reg.s.reserved_6_63 */ ++ pcsx_int_en_reg.s.algnlos_en = 1; ++ pcsx_int_en_reg.s.synlos_en = 1; ++ pcsx_int_en_reg.s.bitlckls_en = 0; /* Happens if XAUI module is not installed */ ++ pcsx_int_en_reg.s.rxsynbad_en = 1; ++ pcsx_int_en_reg.s.rxbad_en = 1; ++ pcsx_int_en_reg.s.txflt_en = 1; ++ } ++ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(index), pcsx_int_en_reg.u64); ++} ++ ++/** ++ * __cvmx_interrupt_spxx_int_msk_enable enables all interrupt bits in cvmx_spxx_int_msk_t ++ */ ++void __cvmx_interrupt_spxx_int_msk_enable(int index) ++{ ++ union cvmx_spxx_int_msk spx_int_msk; ++ cvmx_write_csr(CVMX_SPXX_INT_REG(index), ++ cvmx_read_csr(CVMX_SPXX_INT_REG(index))); ++ spx_int_msk.u64 = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { ++ /* Skipping spx_int_msk.s.reserved_12_63 */ ++ spx_int_msk.s.calerr = 1; ++ spx_int_msk.s.syncerr = 1; ++ spx_int_msk.s.diperr = 1; ++ spx_int_msk.s.tpaovr = 1; ++ spx_int_msk.s.rsverr = 1; ++ spx_int_msk.s.drwnng = 1; ++ spx_int_msk.s.clserr = 1; ++ spx_int_msk.s.spiovr = 1; ++ /* Skipping spx_int_msk.s.reserved_2_3 */ ++ spx_int_msk.s.abnorm = 1; ++ spx_int_msk.s.prtnxa = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ /* Skipping spx_int_msk.s.reserved_12_63 */ ++ spx_int_msk.s.calerr = 1; ++ spx_int_msk.s.syncerr = 1; ++ spx_int_msk.s.diperr = 1; ++ spx_int_msk.s.tpaovr = 1; ++ spx_int_msk.s.rsverr = 1; ++ spx_int_msk.s.drwnng = 1; ++ spx_int_msk.s.clserr = 1; ++ spx_int_msk.s.spiovr = 1; ++ /* Skipping spx_int_msk.s.reserved_2_3 */ ++ spx_int_msk.s.abnorm = 1; ++ spx_int_msk.s.prtnxa = 1; ++ } ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(index), spx_int_msk.u64); ++} ++/** ++ * __cvmx_interrupt_stxx_int_msk_enable enables all interrupt bits in cvmx_stxx_int_msk_t ++ */ ++void __cvmx_interrupt_stxx_int_msk_enable(int index) ++{ ++ union cvmx_stxx_int_msk stx_int_msk; ++ cvmx_write_csr(CVMX_STXX_INT_REG(index), ++ cvmx_read_csr(CVMX_STXX_INT_REG(index))); ++ stx_int_msk.u64 = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { ++ /* Skipping stx_int_msk.s.reserved_8_63 */ ++ stx_int_msk.s.frmerr = 1; ++ stx_int_msk.s.unxfrm = 1; ++ stx_int_msk.s.nosync = 1; ++ stx_int_msk.s.diperr = 1; ++ stx_int_msk.s.datovr = 1; ++ stx_int_msk.s.ovrbst = 1; ++ stx_int_msk.s.calpar1 = 1; ++ stx_int_msk.s.calpar0 = 1; ++ } ++ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ /* Skipping stx_int_msk.s.reserved_8_63 */ ++ stx_int_msk.s.frmerr = 1; ++ stx_int_msk.s.unxfrm = 1; ++ stx_int_msk.s.nosync = 1; ++ stx_int_msk.s.diperr = 1; ++ stx_int_msk.s.datovr = 1; ++ stx_int_msk.s.ovrbst = 1; ++ stx_int_msk.s.calpar1 = 1; ++ stx_int_msk.s.calpar0 = 1; ++ } ++ cvmx_write_csr(CVMX_STXX_INT_MSK(index), stx_int_msk.u64); ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-interrupt-rsl.c +@@ -0,0 +1,140 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Utility functions to decode Octeon's RSL_INT_BLOCKS ++ * interrupts into error messages. ++ */ ++ ++#include ++ ++#include "cvmx-asxx-defs.h" ++#include "cvmx-gmxx-defs.h" ++ ++#ifndef PRINT_ERROR ++#define PRINT_ERROR(format, ...) ++#endif ++ ++void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block); ++ ++/** ++ * Enable ASX error interrupts that exist on CN3XXX, CN50XX, and ++ * CN58XX. ++ * ++ * @block: Interface to enable 0-1 ++ */ ++void __cvmx_interrupt_asxx_enable(int block) ++{ ++ int mask; ++ union cvmx_asxx_int_en csr; ++ /* ++ * CN38XX and CN58XX have two interfaces with 4 ports per ++ * interface. All other chips have a max of 3 ports on ++ * interface 0 ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) ++ mask = 0xf; /* Set enables for 4 ports */ ++ else ++ mask = 0x7; /* Set enables for 3 ports */ ++ ++ /* Enable interface interrupts */ ++ csr.u64 = cvmx_read_csr(CVMX_ASXX_INT_EN(block)); ++ csr.s.txpsh = mask; ++ csr.s.txpop = mask; ++ csr.s.ovrflw = mask; ++ cvmx_write_csr(CVMX_ASXX_INT_EN(block), csr.u64); ++} ++/** ++ * Enable GMX error reporting for the supplied interface ++ * ++ * @interface: Interface to enable ++ */ ++void __cvmx_interrupt_gmxx_enable(int interface) ++{ ++ union cvmx_gmxx_inf_mode mode; ++ union cvmx_gmxx_tx_int_en gmx_tx_int_en; ++ int num_ports; ++ int index; ++ ++ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ if (mode.s.en) { ++ switch (mode.cn56xx.mode) { ++ case 1: /* XAUI */ ++ num_ports = 1; ++ break; ++ case 2: /* SGMII */ ++ case 3: /* PICMG */ ++ num_ports = 4; ++ break; ++ default: /* Disabled */ ++ num_ports = 0; ++ break; ++ } ++ } else ++ num_ports = 0; ++ } else { ++ if (mode.s.en) { ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ /* ++ * SPI on CN38XX and CN58XX report all ++ * errors through port 0. RGMII needs ++ * to check all 4 ports ++ */ ++ if (mode.s.type) ++ num_ports = 1; ++ else ++ num_ports = 4; ++ } else { ++ /* ++ * CN30XX, CN31XX, and CN50XX have two ++ * or three ports. GMII and MII has 2, ++ * RGMII has three ++ */ ++ if (mode.s.type) ++ num_ports = 2; ++ else ++ num_ports = 3; ++ } ++ } else ++ num_ports = 0; ++ } ++ ++ gmx_tx_int_en.u64 = 0; ++ if (num_ports) { ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX)) ++ gmx_tx_int_en.s.ncb_nxa = 1; ++ gmx_tx_int_en.s.pko_nxa = 1; ++ } ++ gmx_tx_int_en.s.undflw = (1 << num_ports) - 1; ++ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64); ++ for (index = 0; index < num_ports; index++) ++ __cvmx_interrupt_gmxx_rxx_int_en_enable(index, interface); ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-ipd.h +@@ -0,0 +1,338 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Interface to the hardware Input Packet Data unit. ++ */ ++ ++#ifndef __CVMX_IPD_H__ ++#define __CVMX_IPD_H__ ++ ++#include ++ ++#include ++ ++enum cvmx_ipd_mode { ++ CVMX_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */ ++ CVMX_IPD_OPC_MODE_STF = 1LL, /* All bloccks into L2 */ ++ CVMX_IPD_OPC_MODE_STF1_STT = 2LL, /* 1st block L2, rest DRAM */ ++ CVMX_IPD_OPC_MODE_STF2_STT = 3LL /* 1st, 2nd blocks L2, rest DRAM */ ++}; ++ ++#ifndef CVMX_ENABLE_LEN_M8_FIX ++#define CVMX_ENABLE_LEN_M8_FIX 0 ++#endif ++ ++/* CSR typedefs have been moved to cvmx-csr-*.h */ ++typedef union cvmx_ipd_1st_mbuff_skip cvmx_ipd_mbuff_first_skip_t; ++typedef union cvmx_ipd_1st_next_ptr_back cvmx_ipd_first_next_ptr_back_t; ++ ++typedef cvmx_ipd_mbuff_first_skip_t cvmx_ipd_mbuff_not_first_skip_t; ++typedef cvmx_ipd_first_next_ptr_back_t cvmx_ipd_second_next_ptr_back_t; ++ ++/** ++ * Configure IPD ++ * ++ * @mbuff_size: Packets buffer size in 8 byte words ++ * @first_mbuff_skip: ++ * Number of 8 byte words to skip in the first buffer ++ * @not_first_mbuff_skip: ++ * Number of 8 byte words to skip in each following buffer ++ * @first_back: Must be same as first_mbuff_skip / 128 ++ * @second_back: ++ * Must be same as not_first_mbuff_skip / 128 ++ * @wqe_fpa_pool: ++ * FPA pool to get work entries from ++ * @cache_mode: ++ * @back_pres_enable_flag: ++ * Enable or disable port back pressure ++ */ ++static inline void cvmx_ipd_config(uint64_t mbuff_size, ++ uint64_t first_mbuff_skip, ++ uint64_t not_first_mbuff_skip, ++ uint64_t first_back, ++ uint64_t second_back, ++ uint64_t wqe_fpa_pool, ++ enum cvmx_ipd_mode cache_mode, ++ uint64_t back_pres_enable_flag) ++{ ++ cvmx_ipd_mbuff_first_skip_t first_skip; ++ cvmx_ipd_mbuff_not_first_skip_t not_first_skip; ++ union cvmx_ipd_packet_mbuff_size size; ++ cvmx_ipd_first_next_ptr_back_t first_back_struct; ++ cvmx_ipd_second_next_ptr_back_t second_back_struct; ++ union cvmx_ipd_wqe_fpa_queue wqe_pool; ++ union cvmx_ipd_ctl_status ipd_ctl_reg; ++ ++ first_skip.u64 = 0; ++ first_skip.s.skip_sz = first_mbuff_skip; ++ cvmx_write_csr(CVMX_IPD_1ST_MBUFF_SKIP, first_skip.u64); ++ ++ not_first_skip.u64 = 0; ++ not_first_skip.s.skip_sz = not_first_mbuff_skip; ++ cvmx_write_csr(CVMX_IPD_NOT_1ST_MBUFF_SKIP, not_first_skip.u64); ++ ++ size.u64 = 0; ++ size.s.mb_size = mbuff_size; ++ cvmx_write_csr(CVMX_IPD_PACKET_MBUFF_SIZE, size.u64); ++ ++ first_back_struct.u64 = 0; ++ first_back_struct.s.back = first_back; ++ cvmx_write_csr(CVMX_IPD_1st_NEXT_PTR_BACK, first_back_struct.u64); ++ ++ second_back_struct.u64 = 0; ++ second_back_struct.s.back = second_back; ++ cvmx_write_csr(CVMX_IPD_2nd_NEXT_PTR_BACK, second_back_struct.u64); ++ ++ wqe_pool.u64 = 0; ++ wqe_pool.s.wqe_pool = wqe_fpa_pool; ++ cvmx_write_csr(CVMX_IPD_WQE_FPA_QUEUE, wqe_pool.u64); ++ ++ ipd_ctl_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); ++ ipd_ctl_reg.s.opc_mode = cache_mode; ++ ipd_ctl_reg.s.pbp_en = back_pres_enable_flag; ++ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_reg.u64); ++ ++ /* Note: the example RED code that used to be here has been moved to ++ cvmx_helper_setup_red */ ++} ++ ++/** ++ * Enable IPD ++ */ ++static inline void cvmx_ipd_enable(void) ++{ ++ union cvmx_ipd_ctl_status ipd_reg; ++ ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); ++ if (ipd_reg.s.ipd_en) { ++ cvmx_dprintf ++ ("Warning: Enabling IPD when IPD already enabled.\n"); ++ } ++ ipd_reg.s.ipd_en = 1; ++#if CVMX_ENABLE_LEN_M8_FIX ++ if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) ++ ipd_reg.s.len_m8 = TRUE; ++#endif ++ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); ++} ++ ++/** ++ * Disable IPD ++ */ ++static inline void cvmx_ipd_disable(void) ++{ ++ union cvmx_ipd_ctl_status ipd_reg; ++ ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); ++ ipd_reg.s.ipd_en = 0; ++ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); ++} ++ ++/** ++ * Supportive function for cvmx_fpa_shutdown_pool. ++ */ ++static inline void cvmx_ipd_free_ptr(void) ++{ ++ /* Only CN38XXp{1,2} cannot read pointer out of the IPD */ ++ if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1) ++ && !OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) { ++ int no_wptr = 0; ++ union cvmx_ipd_ptr_count ipd_ptr_count; ++ ipd_ptr_count.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); ++ ++ /* Handle Work Queue Entry in cn56xx and cn52xx */ ++ if (octeon_has_feature(OCTEON_FEATURE_NO_WPTR)) { ++ union cvmx_ipd_ctl_status ipd_ctl_status; ++ ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); ++ if (ipd_ctl_status.s.no_wptr) ++ no_wptr = 1; ++ } ++ ++ /* Free the prefetched WQE */ ++ if (ipd_ptr_count.s.wqev_cnt) { ++ union cvmx_ipd_wqe_ptr_valid ipd_wqe_ptr_valid; ++ ipd_wqe_ptr_valid.u64 = ++ cvmx_read_csr(CVMX_IPD_WQE_PTR_VALID); ++ if (no_wptr) ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ipd_wqe_ptr_valid.s. ++ ptr << 7), CVMX_FPA_PACKET_POOL, ++ 0); ++ else ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ipd_wqe_ptr_valid.s. ++ ptr << 7), CVMX_FPA_WQE_POOL, 0); ++ } ++ ++ /* Free all WQE in the fifo */ ++ if (ipd_ptr_count.s.wqe_pcnt) { ++ int i; ++ union cvmx_ipd_pwp_ptr_fifo_ctl ipd_pwp_ptr_fifo_ctl; ++ ipd_pwp_ptr_fifo_ctl.u64 = ++ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); ++ for (i = 0; i < ipd_ptr_count.s.wqe_pcnt; i++) { ++ ipd_pwp_ptr_fifo_ctl.s.cena = 0; ++ ipd_pwp_ptr_fifo_ctl.s.raddr = ++ ipd_pwp_ptr_fifo_ctl.s.max_cnts + ++ (ipd_pwp_ptr_fifo_ctl.s.wraddr + ++ i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts; ++ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ++ ipd_pwp_ptr_fifo_ctl.u64); ++ ipd_pwp_ptr_fifo_ctl.u64 = ++ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); ++ if (no_wptr) ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ++ ipd_pwp_ptr_fifo_ctl.s. ++ ptr << 7), ++ CVMX_FPA_PACKET_POOL, 0); ++ else ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ++ ipd_pwp_ptr_fifo_ctl.s. ++ ptr << 7), ++ CVMX_FPA_WQE_POOL, 0); ++ } ++ ipd_pwp_ptr_fifo_ctl.s.cena = 1; ++ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ++ ipd_pwp_ptr_fifo_ctl.u64); ++ } ++ ++ /* Free the prefetched packet */ ++ if (ipd_ptr_count.s.pktv_cnt) { ++ union cvmx_ipd_pkt_ptr_valid ipd_pkt_ptr_valid; ++ ipd_pkt_ptr_valid.u64 = ++ cvmx_read_csr(CVMX_IPD_PKT_PTR_VALID); ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ (ipd_pkt_ptr_valid.s.ptr << 7), ++ CVMX_FPA_PACKET_POOL, 0); ++ } ++ ++ /* Free the per port prefetched packets */ ++ if (1) { ++ int i; ++ union cvmx_ipd_prc_port_ptr_fifo_ctl ++ ipd_prc_port_ptr_fifo_ctl; ++ ipd_prc_port_ptr_fifo_ctl.u64 = ++ cvmx_read_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL); ++ ++ for (i = 0; i < ipd_prc_port_ptr_fifo_ctl.s.max_pkt; ++ i++) { ++ ipd_prc_port_ptr_fifo_ctl.s.cena = 0; ++ ipd_prc_port_ptr_fifo_ctl.s.raddr = ++ i % ipd_prc_port_ptr_fifo_ctl.s.max_pkt; ++ cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL, ++ ipd_prc_port_ptr_fifo_ctl.u64); ++ ipd_prc_port_ptr_fifo_ctl.u64 = ++ cvmx_read_csr ++ (CVMX_IPD_PRC_PORT_PTR_FIFO_CTL); ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ++ ipd_prc_port_ptr_fifo_ctl.s. ++ ptr << 7), CVMX_FPA_PACKET_POOL, ++ 0); ++ } ++ ipd_prc_port_ptr_fifo_ctl.s.cena = 1; ++ cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL, ++ ipd_prc_port_ptr_fifo_ctl.u64); ++ } ++ ++ /* Free all packets in the holding fifo */ ++ if (ipd_ptr_count.s.pfif_cnt) { ++ int i; ++ union cvmx_ipd_prc_hold_ptr_fifo_ctl ++ ipd_prc_hold_ptr_fifo_ctl; ++ ++ ipd_prc_hold_ptr_fifo_ctl.u64 = ++ cvmx_read_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL); ++ ++ for (i = 0; i < ipd_ptr_count.s.pfif_cnt; i++) { ++ ipd_prc_hold_ptr_fifo_ctl.s.cena = 0; ++ ipd_prc_hold_ptr_fifo_ctl.s.raddr = ++ (ipd_prc_hold_ptr_fifo_ctl.s.praddr + ++ i) % ipd_prc_hold_ptr_fifo_ctl.s.max_pkt; ++ cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL, ++ ipd_prc_hold_ptr_fifo_ctl.u64); ++ ipd_prc_hold_ptr_fifo_ctl.u64 = ++ cvmx_read_csr ++ (CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL); ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ++ ipd_prc_hold_ptr_fifo_ctl.s. ++ ptr << 7), CVMX_FPA_PACKET_POOL, ++ 0); ++ } ++ ipd_prc_hold_ptr_fifo_ctl.s.cena = 1; ++ cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL, ++ ipd_prc_hold_ptr_fifo_ctl.u64); ++ } ++ ++ /* Free all packets in the fifo */ ++ if (ipd_ptr_count.s.pkt_pcnt) { ++ int i; ++ union cvmx_ipd_pwp_ptr_fifo_ctl ipd_pwp_ptr_fifo_ctl; ++ ipd_pwp_ptr_fifo_ctl.u64 = ++ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); ++ ++ for (i = 0; i < ipd_ptr_count.s.pkt_pcnt; i++) { ++ ipd_pwp_ptr_fifo_ctl.s.cena = 0; ++ ipd_pwp_ptr_fifo_ctl.s.raddr = ++ (ipd_pwp_ptr_fifo_ctl.s.praddr + ++ i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts; ++ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ++ ipd_pwp_ptr_fifo_ctl.u64); ++ ipd_pwp_ptr_fifo_ctl.u64 = ++ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); ++ cvmx_fpa_free(cvmx_phys_to_ptr ++ ((uint64_t) ipd_pwp_ptr_fifo_ctl. ++ s.ptr << 7), ++ CVMX_FPA_PACKET_POOL, 0); ++ } ++ ipd_pwp_ptr_fifo_ctl.s.cena = 1; ++ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ++ ipd_pwp_ptr_fifo_ctl.u64); ++ } ++ ++ /* Reset the IPD to get all buffers out of it */ ++ { ++ union cvmx_ipd_ctl_status ipd_ctl_status; ++ ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); ++ ipd_ctl_status.s.reset = 1; ++ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); ++ } ++ ++ /* Reset the PIP */ ++ { ++ union cvmx_pip_sft_rst pip_sft_rst; ++ pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST); ++ pip_sft_rst.s.rst = 1; ++ cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64); ++ } ++ } ++} ++ ++#endif /* __CVMX_IPD_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-mdio.h +@@ -0,0 +1,506 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3 ++ * clause 22 and clause 45 operations. ++ * ++ */ ++ ++#ifndef __CVMX_MIO_H__ ++#define __CVMX_MIO_H__ ++ ++#include "cvmx-smix-defs.h" ++ ++/** ++ * PHY register 0 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_CONTROL 0 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t reset:1; ++ uint16_t loopback:1; ++ uint16_t speed_lsb:1; ++ uint16_t autoneg_enable:1; ++ uint16_t power_down:1; ++ uint16_t isolate:1; ++ uint16_t restart_autoneg:1; ++ uint16_t duplex:1; ++ uint16_t collision_test:1; ++ uint16_t speed_msb:1; ++ uint16_t unidirectional_enable:1; ++ uint16_t reserved_0_4:5; ++ } s; ++} cvmx_mdio_phy_reg_control_t; ++ ++/** ++ * PHY register 1 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_STATUS 1 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t capable_100base_t4:1; ++ uint16_t capable_100base_x_full:1; ++ uint16_t capable_100base_x_half:1; ++ uint16_t capable_10_full:1; ++ uint16_t capable_10_half:1; ++ uint16_t capable_100base_t2_full:1; ++ uint16_t capable_100base_t2_half:1; ++ uint16_t capable_extended_status:1; ++ uint16_t capable_unidirectional:1; ++ uint16_t capable_mf_preamble_suppression:1; ++ uint16_t autoneg_complete:1; ++ uint16_t remote_fault:1; ++ uint16_t capable_autoneg:1; ++ uint16_t link_status:1; ++ uint16_t jabber_detect:1; ++ uint16_t capable_extended_registers:1; ++ ++ } s; ++} cvmx_mdio_phy_reg_status_t; ++ ++/** ++ * PHY register 2 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_ID1 2 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t oui_bits_3_18; ++ } s; ++} cvmx_mdio_phy_reg_id1_t; ++ ++/** ++ * PHY register 3 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_ID2 3 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t oui_bits_19_24:6; ++ uint16_t model:6; ++ uint16_t revision:4; ++ } s; ++} cvmx_mdio_phy_reg_id2_t; ++ ++/** ++ * PHY register 4 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t next_page:1; ++ uint16_t reserved_14:1; ++ uint16_t remote_fault:1; ++ uint16_t reserved_12:1; ++ uint16_t asymmetric_pause:1; ++ uint16_t pause:1; ++ uint16_t advert_100base_t4:1; ++ uint16_t advert_100base_tx_full:1; ++ uint16_t advert_100base_tx_half:1; ++ uint16_t advert_10base_tx_full:1; ++ uint16_t advert_10base_tx_half:1; ++ uint16_t selector:5; ++ } s; ++} cvmx_mdio_phy_reg_autoneg_adver_t; ++ ++/** ++ * PHY register 5 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t next_page:1; ++ uint16_t ack:1; ++ uint16_t remote_fault:1; ++ uint16_t reserved_12:1; ++ uint16_t asymmetric_pause:1; ++ uint16_t pause:1; ++ uint16_t advert_100base_t4:1; ++ uint16_t advert_100base_tx_full:1; ++ uint16_t advert_100base_tx_half:1; ++ uint16_t advert_10base_tx_full:1; ++ uint16_t advert_10base_tx_half:1; ++ uint16_t selector:5; ++ } s; ++} cvmx_mdio_phy_reg_link_partner_ability_t; ++ ++/** ++ * PHY register 6 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t reserved_5_15:11; ++ uint16_t parallel_detection_fault:1; ++ uint16_t link_partner_next_page_capable:1; ++ uint16_t local_next_page_capable:1; ++ uint16_t page_received:1; ++ uint16_t link_partner_autoneg_capable:1; ++ ++ } s; ++} cvmx_mdio_phy_reg_autoneg_expansion_t; ++ ++/** ++ * PHY register 9 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_CONTROL_1000 9 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t test_mode:3; ++ uint16_t manual_master_slave:1; ++ uint16_t master:1; ++ uint16_t port_type:1; ++ uint16_t advert_1000base_t_full:1; ++ uint16_t advert_1000base_t_half:1; ++ uint16_t reserved_0_7:8; ++ } s; ++} cvmx_mdio_phy_reg_control_1000_t; ++ ++/** ++ * PHY register 10 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_STATUS_1000 10 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t master_slave_fault:1; ++ uint16_t is_master:1; ++ uint16_t local_receiver_ok:1; ++ uint16_t remote_receiver_ok:1; ++ uint16_t remote_capable_1000base_t_full:1; ++ uint16_t remote_capable_1000base_t_half:1; ++ uint16_t reserved_8_9:2; ++ uint16_t idle_error_count:8; ++ } s; ++} cvmx_mdio_phy_reg_status_1000_t; ++ ++/** ++ * PHY register 15 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t capable_1000base_x_full:1; ++ uint16_t capable_1000base_x_half:1; ++ uint16_t capable_1000base_t_full:1; ++ uint16_t capable_1000base_t_half:1; ++ uint16_t reserved_0_11:12; ++ } s; ++} cvmx_mdio_phy_reg_extended_status_t; ++ ++/** ++ * PHY register 13 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t function:2; ++ uint16_t reserved_5_13:9; ++ uint16_t devad:5; ++ } s; ++} cvmx_mdio_phy_reg_mmd_control_t; ++ ++/** ++ * PHY register 14 from the 802.3 spec ++ */ ++#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14 ++typedef union { ++ uint16_t u16; ++ struct { ++ uint16_t address_data:16; ++ } s; ++} cvmx_mdio_phy_reg_mmd_address_data_t; ++ ++/* Operating request encodings. */ ++#define MDIO_CLAUSE_22_WRITE 0 ++#define MDIO_CLAUSE_22_READ 1 ++ ++#define MDIO_CLAUSE_45_ADDRESS 0 ++#define MDIO_CLAUSE_45_WRITE 1 ++#define MDIO_CLAUSE_45_READ_INC 2 ++#define MDIO_CLAUSE_45_READ 3 ++ ++/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */ ++#define CVMX_MMD_DEVICE_PMA_PMD 1 ++#define CVMX_MMD_DEVICE_WIS 2 ++#define CVMX_MMD_DEVICE_PCS 3 ++#define CVMX_MMD_DEVICE_PHY_XS 4 ++#define CVMX_MMD_DEVICE_DTS_XS 5 ++#define CVMX_MMD_DEVICE_TC 6 ++#define CVMX_MMD_DEVICE_CL22_EXT 29 ++#define CVMX_MMD_DEVICE_VENDOR_1 30 ++#define CVMX_MMD_DEVICE_VENDOR_2 31 ++ ++/* Helper function to put MDIO interface into clause 45 mode */ ++static inline void __cvmx_mdio_set_clause45_mode(int bus_id) ++{ ++ union cvmx_smix_clk smi_clk; ++ /* Put bus into clause 45 mode */ ++ smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); ++ smi_clk.s.mode = 1; ++ smi_clk.s.preamble = 1; ++ cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); ++} ++ ++/* Helper function to put MDIO interface into clause 22 mode */ ++static inline void __cvmx_mdio_set_clause22_mode(int bus_id) ++{ ++ union cvmx_smix_clk smi_clk; ++ /* Put bus into clause 22 mode */ ++ smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); ++ smi_clk.s.mode = 0; ++ cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); ++} ++ ++/** ++ * Perform an MII read. This function is used to read PHY ++ * registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @location: Register location to read ++ * ++ * Returns Result from the read or -1 on failure ++ */ ++static inline int cvmx_mdio_read(int bus_id, int phy_id, int location) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_rd_dat smi_rd; ++ int timeout = 1000; ++ ++ if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) ++ __cvmx_mdio_set_clause22_mode(bus_id); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = location; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); ++ } while (smi_rd.s.pending && timeout--); ++ ++ if (smi_rd.s.val) ++ return smi_rd.s.dat; ++ else ++ return -1; ++} ++ ++/** ++ * Perform an MII write. This function is used to write PHY ++ * registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @location: Register location to write ++ * @val: Value to write ++ * ++ * Returns -1 on error ++ * 0 on success ++ */ ++static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_wr_dat smi_wr; ++ int timeout = 1000; ++ ++ if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) ++ __cvmx_mdio_set_clause22_mode(bus_id); ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = val; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = location; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ return 0; ++} ++ ++/** ++ * Perform an IEEE 802.3 clause 45 MII read. This function is used to ++ * read PHY registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @device: MDIO Managable Device (MMD) id ++ * @location: Register location to read ++ * ++ * Returns Result from the read or -1 on failure ++ */ ++ ++static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, ++ int location) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_rd_dat smi_rd; ++ union cvmx_smix_wr_dat smi_wr; ++ int timeout = 1000; ++ ++ if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) ++ return -1; ++ ++ __cvmx_mdio_set_clause45_mode(bus_id); ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = location; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) { ++ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " ++ "device %2d register %2d TIME OUT(address)\n", ++ bus_id, phy_id, device, location); ++ return -1; ++ } ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); ++ } while (smi_rd.s.pending && timeout--); ++ ++ if (timeout <= 0) { ++ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " ++ "device %2d register %2d TIME OUT(data)\n", ++ bus_id, phy_id, device, location); ++ return -1; ++ } ++ ++ if (smi_rd.s.val) ++ return smi_rd.s.dat; ++ else { ++ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " ++ "device %2d register %2d INVALID READ\n", ++ bus_id, phy_id, device, location); ++ return -1; ++ } ++} ++ ++/** ++ * Perform an IEEE 802.3 clause 45 MII write. This function is used to ++ * write PHY registers controlling auto negotiation. ++ * ++ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) ++ * support multiple busses. ++ * @phy_id: The MII phy id ++ * @device: MDIO Managable Device (MMD) id ++ * @location: Register location to write ++ * @val: Value to write ++ * ++ * Returns -1 on error ++ * 0 on success ++ */ ++static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, ++ int location, int val) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_wr_dat smi_wr; ++ int timeout = 1000; ++ ++ if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) ++ return -1; ++ ++ __cvmx_mdio_set_clause45_mode(bus_id); ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = location; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = val; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = device; ++ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); ++ ++ do { ++ cvmx_wait(1000); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); ++ } while (smi_wr.s.pending && --timeout); ++ if (timeout <= 0) ++ return -1; ++ ++ return 0; ++} ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-packet.h +@@ -0,0 +1,65 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Packet buffer defines. ++ */ ++ ++#ifndef __CVMX_PACKET_H__ ++#define __CVMX_PACKET_H__ ++ ++/** ++ * This structure defines a buffer pointer on Octeon ++ */ ++union cvmx_buf_ptr { ++ void *ptr; ++ uint64_t u64; ++ struct { ++ /* ++ * if set, invert the "free" pick of the overall ++ * packet. HW always sets this bit to 0 on inbound ++ * packet ++ */ ++ uint64_t i:1; ++ /* ++ * Indicates the amount to back up to get to the ++ * buffer start in cache lines. In most cases this is ++ * less than one complete cache line, so the value is ++ * zero. ++ */ ++ uint64_t back:4; ++ /* The pool that the buffer came from / goes to */ ++ uint64_t pool:3; ++ /* The size of the segment pointed to by addr (in bytes) */ ++ uint64_t size:16; ++ /* Pointer to the first byte of the data, NOT buffer */ ++ uint64_t addr:40; ++ } s; ++}; ++ ++#endif /* __CVMX_PACKET_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pcsx-defs.h +@@ -0,0 +1,370 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PCSX_DEFS_H__ ++#define __CVMX_PCSX_DEFS_H__ ++ ++#define CVMX_PCSX_ANX_ADV_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001010ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_ANX_EXT_ST_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001028ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_ANX_LP_ABIL_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001018ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_ANX_RESULTS_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001020ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_INTX_EN_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001088ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_INTX_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001080ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_LINKX_TIMER_COUNT_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001040ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_LOG_ANLX_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001090ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_MISCX_CTL_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001078ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_MRX_CONTROL_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001000ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_MRX_STATUS_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001008ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_RXX_STATES_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001058ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_RXX_SYNC_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001050ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_SGMX_AN_ADV_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001068ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_SGMX_LP_ADV_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001070ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_TXX_STATES_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001060ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSX_TX_RXX_POLARITY_REG(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0001048ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_pcsx_anx_adv_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_anx_adv_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t np:1; ++ uint64_t reserved_14_14:1; ++ uint64_t rem_flt:2; ++ uint64_t reserved_9_11:3; ++ uint64_t pause:2; ++ uint64_t hfd:1; ++ uint64_t fd:1; ++ uint64_t reserved_0_4:5; ++ } s; ++ struct cvmx_pcsx_anx_adv_reg_s cn52xx; ++ struct cvmx_pcsx_anx_adv_reg_s cn52xxp1; ++ struct cvmx_pcsx_anx_adv_reg_s cn56xx; ++ struct cvmx_pcsx_anx_adv_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_anx_ext_st_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_anx_ext_st_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t thou_xfd:1; ++ uint64_t thou_xhd:1; ++ uint64_t thou_tfd:1; ++ uint64_t thou_thd:1; ++ uint64_t reserved_0_11:12; ++ } s; ++ struct cvmx_pcsx_anx_ext_st_reg_s cn52xx; ++ struct cvmx_pcsx_anx_ext_st_reg_s cn52xxp1; ++ struct cvmx_pcsx_anx_ext_st_reg_s cn56xx; ++ struct cvmx_pcsx_anx_ext_st_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_anx_lp_abil_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_anx_lp_abil_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t np:1; ++ uint64_t ack:1; ++ uint64_t rem_flt:2; ++ uint64_t reserved_9_11:3; ++ uint64_t pause:2; ++ uint64_t hfd:1; ++ uint64_t fd:1; ++ uint64_t reserved_0_4:5; ++ } s; ++ struct cvmx_pcsx_anx_lp_abil_reg_s cn52xx; ++ struct cvmx_pcsx_anx_lp_abil_reg_s cn52xxp1; ++ struct cvmx_pcsx_anx_lp_abil_reg_s cn56xx; ++ struct cvmx_pcsx_anx_lp_abil_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_anx_results_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_anx_results_reg_s { ++ uint64_t reserved_7_63:57; ++ uint64_t pause:2; ++ uint64_t spd:2; ++ uint64_t an_cpt:1; ++ uint64_t dup:1; ++ uint64_t link_ok:1; ++ } s; ++ struct cvmx_pcsx_anx_results_reg_s cn52xx; ++ struct cvmx_pcsx_anx_results_reg_s cn52xxp1; ++ struct cvmx_pcsx_anx_results_reg_s cn56xx; ++ struct cvmx_pcsx_anx_results_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_intx_en_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_intx_en_reg_s { ++ uint64_t reserved_12_63:52; ++ uint64_t dup:1; ++ uint64_t sync_bad_en:1; ++ uint64_t an_bad_en:1; ++ uint64_t rxlock_en:1; ++ uint64_t rxbad_en:1; ++ uint64_t rxerr_en:1; ++ uint64_t txbad_en:1; ++ uint64_t txfifo_en:1; ++ uint64_t txfifu_en:1; ++ uint64_t an_err_en:1; ++ uint64_t xmit_en:1; ++ uint64_t lnkspd_en:1; ++ } s; ++ struct cvmx_pcsx_intx_en_reg_s cn52xx; ++ struct cvmx_pcsx_intx_en_reg_s cn52xxp1; ++ struct cvmx_pcsx_intx_en_reg_s cn56xx; ++ struct cvmx_pcsx_intx_en_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_intx_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_intx_reg_s { ++ uint64_t reserved_12_63:52; ++ uint64_t dup:1; ++ uint64_t sync_bad:1; ++ uint64_t an_bad:1; ++ uint64_t rxlock:1; ++ uint64_t rxbad:1; ++ uint64_t rxerr:1; ++ uint64_t txbad:1; ++ uint64_t txfifo:1; ++ uint64_t txfifu:1; ++ uint64_t an_err:1; ++ uint64_t xmit:1; ++ uint64_t lnkspd:1; ++ } s; ++ struct cvmx_pcsx_intx_reg_s cn52xx; ++ struct cvmx_pcsx_intx_reg_s cn52xxp1; ++ struct cvmx_pcsx_intx_reg_s cn56xx; ++ struct cvmx_pcsx_intx_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_linkx_timer_count_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_linkx_timer_count_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t count:16; ++ } s; ++ struct cvmx_pcsx_linkx_timer_count_reg_s cn52xx; ++ struct cvmx_pcsx_linkx_timer_count_reg_s cn52xxp1; ++ struct cvmx_pcsx_linkx_timer_count_reg_s cn56xx; ++ struct cvmx_pcsx_linkx_timer_count_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_log_anlx_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_log_anlx_reg_s { ++ uint64_t reserved_4_63:60; ++ uint64_t lafifovfl:1; ++ uint64_t la_en:1; ++ uint64_t pkt_sz:2; ++ } s; ++ struct cvmx_pcsx_log_anlx_reg_s cn52xx; ++ struct cvmx_pcsx_log_anlx_reg_s cn52xxp1; ++ struct cvmx_pcsx_log_anlx_reg_s cn56xx; ++ struct cvmx_pcsx_log_anlx_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_miscx_ctl_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_miscx_ctl_reg_s { ++ uint64_t reserved_13_63:51; ++ uint64_t sgmii:1; ++ uint64_t gmxeno:1; ++ uint64_t loopbck2:1; ++ uint64_t mac_phy:1; ++ uint64_t mode:1; ++ uint64_t an_ovrd:1; ++ uint64_t samp_pt:7; ++ } s; ++ struct cvmx_pcsx_miscx_ctl_reg_s cn52xx; ++ struct cvmx_pcsx_miscx_ctl_reg_s cn52xxp1; ++ struct cvmx_pcsx_miscx_ctl_reg_s cn56xx; ++ struct cvmx_pcsx_miscx_ctl_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_mrx_control_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_mrx_control_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t reset:1; ++ uint64_t loopbck1:1; ++ uint64_t spdlsb:1; ++ uint64_t an_en:1; ++ uint64_t pwr_dn:1; ++ uint64_t reserved_10_10:1; ++ uint64_t rst_an:1; ++ uint64_t dup:1; ++ uint64_t coltst:1; ++ uint64_t spdmsb:1; ++ uint64_t uni:1; ++ uint64_t reserved_0_4:5; ++ } s; ++ struct cvmx_pcsx_mrx_control_reg_s cn52xx; ++ struct cvmx_pcsx_mrx_control_reg_s cn52xxp1; ++ struct cvmx_pcsx_mrx_control_reg_s cn56xx; ++ struct cvmx_pcsx_mrx_control_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_mrx_status_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_mrx_status_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t hun_t4:1; ++ uint64_t hun_xfd:1; ++ uint64_t hun_xhd:1; ++ uint64_t ten_fd:1; ++ uint64_t ten_hd:1; ++ uint64_t hun_t2fd:1; ++ uint64_t hun_t2hd:1; ++ uint64_t ext_st:1; ++ uint64_t reserved_7_7:1; ++ uint64_t prb_sup:1; ++ uint64_t an_cpt:1; ++ uint64_t rm_flt:1; ++ uint64_t an_abil:1; ++ uint64_t lnk_st:1; ++ uint64_t reserved_1_1:1; ++ uint64_t extnd:1; ++ } s; ++ struct cvmx_pcsx_mrx_status_reg_s cn52xx; ++ struct cvmx_pcsx_mrx_status_reg_s cn52xxp1; ++ struct cvmx_pcsx_mrx_status_reg_s cn56xx; ++ struct cvmx_pcsx_mrx_status_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_rxx_states_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_rxx_states_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t rx_bad:1; ++ uint64_t rx_st:5; ++ uint64_t sync_bad:1; ++ uint64_t sync:4; ++ uint64_t an_bad:1; ++ uint64_t an_st:4; ++ } s; ++ struct cvmx_pcsx_rxx_states_reg_s cn52xx; ++ struct cvmx_pcsx_rxx_states_reg_s cn52xxp1; ++ struct cvmx_pcsx_rxx_states_reg_s cn56xx; ++ struct cvmx_pcsx_rxx_states_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_rxx_sync_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_rxx_sync_reg_s { ++ uint64_t reserved_2_63:62; ++ uint64_t sync:1; ++ uint64_t bit_lock:1; ++ } s; ++ struct cvmx_pcsx_rxx_sync_reg_s cn52xx; ++ struct cvmx_pcsx_rxx_sync_reg_s cn52xxp1; ++ struct cvmx_pcsx_rxx_sync_reg_s cn56xx; ++ struct cvmx_pcsx_rxx_sync_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_sgmx_an_adv_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_sgmx_an_adv_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t link:1; ++ uint64_t ack:1; ++ uint64_t reserved_13_13:1; ++ uint64_t dup:1; ++ uint64_t speed:2; ++ uint64_t reserved_1_9:9; ++ uint64_t one:1; ++ } s; ++ struct cvmx_pcsx_sgmx_an_adv_reg_s cn52xx; ++ struct cvmx_pcsx_sgmx_an_adv_reg_s cn52xxp1; ++ struct cvmx_pcsx_sgmx_an_adv_reg_s cn56xx; ++ struct cvmx_pcsx_sgmx_an_adv_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_sgmx_lp_adv_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_sgmx_lp_adv_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t link:1; ++ uint64_t reserved_13_14:2; ++ uint64_t dup:1; ++ uint64_t speed:2; ++ uint64_t reserved_1_9:9; ++ uint64_t one:1; ++ } s; ++ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn52xx; ++ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn52xxp1; ++ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn56xx; ++ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_txx_states_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_txx_states_reg_s { ++ uint64_t reserved_7_63:57; ++ uint64_t xmit:2; ++ uint64_t tx_bad:1; ++ uint64_t ord_st:4; ++ } s; ++ struct cvmx_pcsx_txx_states_reg_s cn52xx; ++ struct cvmx_pcsx_txx_states_reg_s cn52xxp1; ++ struct cvmx_pcsx_txx_states_reg_s cn56xx; ++ struct cvmx_pcsx_txx_states_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsx_tx_rxx_polarity_reg { ++ uint64_t u64; ++ struct cvmx_pcsx_tx_rxx_polarity_reg_s { ++ uint64_t reserved_4_63:60; ++ uint64_t rxovrd:1; ++ uint64_t autorxpl:1; ++ uint64_t rxplrt:1; ++ uint64_t txplrt:1; ++ } s; ++ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn52xx; ++ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn52xxp1; ++ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn56xx; ++ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pcsxx-defs.h +@@ -0,0 +1,316 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PCSXX_DEFS_H__ ++#define __CVMX_PCSXX_DEFS_H__ ++ ++#define CVMX_PCSXX_10GBX_STATUS_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000828ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_BIST_STATUS_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000870ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_BIT_LOCK_STATUS_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000850ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_CONTROL1_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000800ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_CONTROL2_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000818ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_INT_EN_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000860ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_INT_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000858ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_LOG_ANL_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000868ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_MISC_CTL_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000848ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_RX_SYNC_STATES_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000838ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_SPD_ABIL_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000810ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_STATUS1_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000808ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_STATUS2_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000820ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_TX_RX_POLARITY_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000840ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_PCSXX_TX_RX_STATES_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800B0000830ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_pcsxx_10gbx_status_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_10gbx_status_reg_s { ++ uint64_t reserved_13_63:51; ++ uint64_t alignd:1; ++ uint64_t pattst:1; ++ uint64_t reserved_4_10:7; ++ uint64_t l3sync:1; ++ uint64_t l2sync:1; ++ uint64_t l1sync:1; ++ uint64_t l0sync:1; ++ } s; ++ struct cvmx_pcsxx_10gbx_status_reg_s cn52xx; ++ struct cvmx_pcsxx_10gbx_status_reg_s cn52xxp1; ++ struct cvmx_pcsxx_10gbx_status_reg_s cn56xx; ++ struct cvmx_pcsxx_10gbx_status_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_bist_status_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_bist_status_reg_s { ++ uint64_t reserved_1_63:63; ++ uint64_t bist_status:1; ++ } s; ++ struct cvmx_pcsxx_bist_status_reg_s cn52xx; ++ struct cvmx_pcsxx_bist_status_reg_s cn52xxp1; ++ struct cvmx_pcsxx_bist_status_reg_s cn56xx; ++ struct cvmx_pcsxx_bist_status_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_bit_lock_status_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_bit_lock_status_reg_s { ++ uint64_t reserved_4_63:60; ++ uint64_t bitlck3:1; ++ uint64_t bitlck2:1; ++ uint64_t bitlck1:1; ++ uint64_t bitlck0:1; ++ } s; ++ struct cvmx_pcsxx_bit_lock_status_reg_s cn52xx; ++ struct cvmx_pcsxx_bit_lock_status_reg_s cn52xxp1; ++ struct cvmx_pcsxx_bit_lock_status_reg_s cn56xx; ++ struct cvmx_pcsxx_bit_lock_status_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_control1_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_control1_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t reset:1; ++ uint64_t loopbck1:1; ++ uint64_t spdsel1:1; ++ uint64_t reserved_12_12:1; ++ uint64_t lo_pwr:1; ++ uint64_t reserved_7_10:4; ++ uint64_t spdsel0:1; ++ uint64_t spd:4; ++ uint64_t reserved_0_1:2; ++ } s; ++ struct cvmx_pcsxx_control1_reg_s cn52xx; ++ struct cvmx_pcsxx_control1_reg_s cn52xxp1; ++ struct cvmx_pcsxx_control1_reg_s cn56xx; ++ struct cvmx_pcsxx_control1_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_control2_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_control2_reg_s { ++ uint64_t reserved_2_63:62; ++ uint64_t type:2; ++ } s; ++ struct cvmx_pcsxx_control2_reg_s cn52xx; ++ struct cvmx_pcsxx_control2_reg_s cn52xxp1; ++ struct cvmx_pcsxx_control2_reg_s cn56xx; ++ struct cvmx_pcsxx_control2_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_int_en_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_int_en_reg_s { ++ uint64_t reserved_6_63:58; ++ uint64_t algnlos_en:1; ++ uint64_t synlos_en:1; ++ uint64_t bitlckls_en:1; ++ uint64_t rxsynbad_en:1; ++ uint64_t rxbad_en:1; ++ uint64_t txflt_en:1; ++ } s; ++ struct cvmx_pcsxx_int_en_reg_s cn52xx; ++ struct cvmx_pcsxx_int_en_reg_s cn52xxp1; ++ struct cvmx_pcsxx_int_en_reg_s cn56xx; ++ struct cvmx_pcsxx_int_en_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_int_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_int_reg_s { ++ uint64_t reserved_6_63:58; ++ uint64_t algnlos:1; ++ uint64_t synlos:1; ++ uint64_t bitlckls:1; ++ uint64_t rxsynbad:1; ++ uint64_t rxbad:1; ++ uint64_t txflt:1; ++ } s; ++ struct cvmx_pcsxx_int_reg_s cn52xx; ++ struct cvmx_pcsxx_int_reg_s cn52xxp1; ++ struct cvmx_pcsxx_int_reg_s cn56xx; ++ struct cvmx_pcsxx_int_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_log_anl_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_log_anl_reg_s { ++ uint64_t reserved_7_63:57; ++ uint64_t enc_mode:1; ++ uint64_t drop_ln:2; ++ uint64_t lafifovfl:1; ++ uint64_t la_en:1; ++ uint64_t pkt_sz:2; ++ } s; ++ struct cvmx_pcsxx_log_anl_reg_s cn52xx; ++ struct cvmx_pcsxx_log_anl_reg_s cn52xxp1; ++ struct cvmx_pcsxx_log_anl_reg_s cn56xx; ++ struct cvmx_pcsxx_log_anl_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_misc_ctl_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_misc_ctl_reg_s { ++ uint64_t reserved_4_63:60; ++ uint64_t tx_swap:1; ++ uint64_t rx_swap:1; ++ uint64_t xaui:1; ++ uint64_t gmxeno:1; ++ } s; ++ struct cvmx_pcsxx_misc_ctl_reg_s cn52xx; ++ struct cvmx_pcsxx_misc_ctl_reg_s cn52xxp1; ++ struct cvmx_pcsxx_misc_ctl_reg_s cn56xx; ++ struct cvmx_pcsxx_misc_ctl_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_rx_sync_states_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_rx_sync_states_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t sync3st:4; ++ uint64_t sync2st:4; ++ uint64_t sync1st:4; ++ uint64_t sync0st:4; ++ } s; ++ struct cvmx_pcsxx_rx_sync_states_reg_s cn52xx; ++ struct cvmx_pcsxx_rx_sync_states_reg_s cn52xxp1; ++ struct cvmx_pcsxx_rx_sync_states_reg_s cn56xx; ++ struct cvmx_pcsxx_rx_sync_states_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_spd_abil_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_spd_abil_reg_s { ++ uint64_t reserved_2_63:62; ++ uint64_t tenpasst:1; ++ uint64_t tengb:1; ++ } s; ++ struct cvmx_pcsxx_spd_abil_reg_s cn52xx; ++ struct cvmx_pcsxx_spd_abil_reg_s cn52xxp1; ++ struct cvmx_pcsxx_spd_abil_reg_s cn56xx; ++ struct cvmx_pcsxx_spd_abil_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_status1_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_status1_reg_s { ++ uint64_t reserved_8_63:56; ++ uint64_t flt:1; ++ uint64_t reserved_3_6:4; ++ uint64_t rcv_lnk:1; ++ uint64_t lpable:1; ++ uint64_t reserved_0_0:1; ++ } s; ++ struct cvmx_pcsxx_status1_reg_s cn52xx; ++ struct cvmx_pcsxx_status1_reg_s cn52xxp1; ++ struct cvmx_pcsxx_status1_reg_s cn56xx; ++ struct cvmx_pcsxx_status1_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_status2_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_status2_reg_s { ++ uint64_t reserved_16_63:48; ++ uint64_t dev:2; ++ uint64_t reserved_12_13:2; ++ uint64_t xmtflt:1; ++ uint64_t rcvflt:1; ++ uint64_t reserved_3_9:7; ++ uint64_t tengb_w:1; ++ uint64_t tengb_x:1; ++ uint64_t tengb_r:1; ++ } s; ++ struct cvmx_pcsxx_status2_reg_s cn52xx; ++ struct cvmx_pcsxx_status2_reg_s cn52xxp1; ++ struct cvmx_pcsxx_status2_reg_s cn56xx; ++ struct cvmx_pcsxx_status2_reg_s cn56xxp1; ++}; ++ ++union cvmx_pcsxx_tx_rx_polarity_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_tx_rx_polarity_reg_s { ++ uint64_t reserved_10_63:54; ++ uint64_t xor_rxplrt:4; ++ uint64_t xor_txplrt:4; ++ uint64_t rxplrt:1; ++ uint64_t txplrt:1; ++ } s; ++ struct cvmx_pcsxx_tx_rx_polarity_reg_s cn52xx; ++ struct cvmx_pcsxx_tx_rx_polarity_reg_cn52xxp1 { ++ uint64_t reserved_2_63:62; ++ uint64_t rxplrt:1; ++ uint64_t txplrt:1; ++ } cn52xxp1; ++ struct cvmx_pcsxx_tx_rx_polarity_reg_s cn56xx; ++ struct cvmx_pcsxx_tx_rx_polarity_reg_cn52xxp1 cn56xxp1; ++}; ++ ++union cvmx_pcsxx_tx_rx_states_reg { ++ uint64_t u64; ++ struct cvmx_pcsxx_tx_rx_states_reg_s { ++ uint64_t reserved_14_63:50; ++ uint64_t term_err:1; ++ uint64_t syn3bad:1; ++ uint64_t syn2bad:1; ++ uint64_t syn1bad:1; ++ uint64_t syn0bad:1; ++ uint64_t rxbad:1; ++ uint64_t algn_st:3; ++ uint64_t rx_st:2; ++ uint64_t tx_st:3; ++ } s; ++ struct cvmx_pcsxx_tx_rx_states_reg_s cn52xx; ++ struct cvmx_pcsxx_tx_rx_states_reg_cn52xxp1 { ++ uint64_t reserved_13_63:51; ++ uint64_t syn3bad:1; ++ uint64_t syn2bad:1; ++ uint64_t syn1bad:1; ++ uint64_t syn0bad:1; ++ uint64_t rxbad:1; ++ uint64_t algn_st:3; ++ uint64_t rx_st:2; ++ uint64_t tx_st:3; ++ } cn52xxp1; ++ struct cvmx_pcsxx_tx_rx_states_reg_s cn56xx; ++ struct cvmx_pcsxx_tx_rx_states_reg_cn52xxp1 cn56xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pip-defs.h +@@ -0,0 +1,1267 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PIP_DEFS_H__ ++#define __CVMX_PIP_DEFS_H__ ++ ++/* ++ * Enumeration representing the amount of packet processing ++ * and validation performed by the input hardware. ++ */ ++enum cvmx_pip_port_parse_mode { ++ /* ++ * Packet input doesn't perform any processing of the input ++ * packet. ++ */ ++ CVMX_PIP_PORT_CFG_MODE_NONE = 0ull, ++ /* ++ * Full packet processing is performed with pointer starting ++ * at the L2 (ethernet MAC) header. ++ */ ++ CVMX_PIP_PORT_CFG_MODE_SKIPL2 = 1ull, ++ /* ++ * Input packets are assumed to be IP. Results from non IP ++ * packets is undefined. Pointers reference the beginning of ++ * the IP header. ++ */ ++ CVMX_PIP_PORT_CFG_MODE_SKIPIP = 2ull ++}; ++ ++#define CVMX_PIP_BCK_PRS \ ++ CVMX_ADD_IO_SEG(0x00011800A0000038ull) ++#define CVMX_PIP_BIST_STATUS \ ++ CVMX_ADD_IO_SEG(0x00011800A0000000ull) ++#define CVMX_PIP_CRC_CTLX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000040ull + (((offset) & 1) * 8)) ++#define CVMX_PIP_CRC_IVX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000050ull + (((offset) & 1) * 8)) ++#define CVMX_PIP_DEC_IPSECX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000080ull + (((offset) & 3) * 8)) ++#define CVMX_PIP_DSA_SRC_GRP \ ++ CVMX_ADD_IO_SEG(0x00011800A0000190ull) ++#define CVMX_PIP_DSA_VID_GRP \ ++ CVMX_ADD_IO_SEG(0x00011800A0000198ull) ++#define CVMX_PIP_FRM_LEN_CHKX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000180ull + (((offset) & 1) * 8)) ++#define CVMX_PIP_GBL_CFG \ ++ CVMX_ADD_IO_SEG(0x00011800A0000028ull) ++#define CVMX_PIP_GBL_CTL \ ++ CVMX_ADD_IO_SEG(0x00011800A0000020ull) ++#define CVMX_PIP_HG_PRI_QOS \ ++ CVMX_ADD_IO_SEG(0x00011800A00001A0ull) ++#define CVMX_PIP_INT_EN \ ++ CVMX_ADD_IO_SEG(0x00011800A0000010ull) ++#define CVMX_PIP_INT_REG \ ++ CVMX_ADD_IO_SEG(0x00011800A0000008ull) ++#define CVMX_PIP_IP_OFFSET \ ++ CVMX_ADD_IO_SEG(0x00011800A0000060ull) ++#define CVMX_PIP_PRT_CFGX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000200ull + (((offset) & 63) * 8)) ++#define CVMX_PIP_PRT_TAGX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000400ull + (((offset) & 63) * 8)) ++#define CVMX_PIP_QOS_DIFFX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000600ull + (((offset) & 63) * 8)) ++#define CVMX_PIP_QOS_VLANX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A00000C0ull + (((offset) & 7) * 8)) ++#define CVMX_PIP_QOS_WATCHX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000100ull + (((offset) & 7) * 8)) ++#define CVMX_PIP_RAW_WORD \ ++ CVMX_ADD_IO_SEG(0x00011800A00000B0ull) ++#define CVMX_PIP_SFT_RST \ ++ CVMX_ADD_IO_SEG(0x00011800A0000030ull) ++#define CVMX_PIP_STAT0_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000800ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT1_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000808ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT2_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000810ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT3_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000818ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT4_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000820ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT5_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000828ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT6_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000830ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT7_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000838ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT8_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000840ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT9_PRTX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0000848ull + (((offset) & 63) * 80)) ++#define CVMX_PIP_STAT_CTL \ ++ CVMX_ADD_IO_SEG(0x00011800A0000018ull) ++#define CVMX_PIP_STAT_INB_ERRSX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0001A10ull + (((offset) & 63) * 32)) ++#define CVMX_PIP_STAT_INB_OCTSX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0001A08ull + (((offset) & 63) * 32)) ++#define CVMX_PIP_STAT_INB_PKTSX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0001A00ull + (((offset) & 63) * 32)) ++#define CVMX_PIP_TAG_INCX(offset) \ ++ CVMX_ADD_IO_SEG(0x00011800A0001800ull + (((offset) & 63) * 8)) ++#define CVMX_PIP_TAG_MASK \ ++ CVMX_ADD_IO_SEG(0x00011800A0000070ull) ++#define CVMX_PIP_TAG_SECRET \ ++ CVMX_ADD_IO_SEG(0x00011800A0000068ull) ++#define CVMX_PIP_TODO_ENTRY \ ++ CVMX_ADD_IO_SEG(0x00011800A0000078ull) ++ ++union cvmx_pip_bck_prs { ++ uint64_t u64; ++ struct cvmx_pip_bck_prs_s { ++ uint64_t bckprs:1; ++ uint64_t reserved_13_62:50; ++ uint64_t hiwater:5; ++ uint64_t reserved_5_7:3; ++ uint64_t lowater:5; ++ } s; ++ struct cvmx_pip_bck_prs_s cn38xx; ++ struct cvmx_pip_bck_prs_s cn38xxp2; ++ struct cvmx_pip_bck_prs_s cn56xx; ++ struct cvmx_pip_bck_prs_s cn56xxp1; ++ struct cvmx_pip_bck_prs_s cn58xx; ++ struct cvmx_pip_bck_prs_s cn58xxp1; ++}; ++ ++union cvmx_pip_bist_status { ++ uint64_t u64; ++ struct cvmx_pip_bist_status_s { ++ uint64_t reserved_18_63:46; ++ uint64_t bist:18; ++ } s; ++ struct cvmx_pip_bist_status_s cn30xx; ++ struct cvmx_pip_bist_status_s cn31xx; ++ struct cvmx_pip_bist_status_s cn38xx; ++ struct cvmx_pip_bist_status_s cn38xxp2; ++ struct cvmx_pip_bist_status_cn50xx { ++ uint64_t reserved_17_63:47; ++ uint64_t bist:17; ++ } cn50xx; ++ struct cvmx_pip_bist_status_s cn52xx; ++ struct cvmx_pip_bist_status_s cn52xxp1; ++ struct cvmx_pip_bist_status_s cn56xx; ++ struct cvmx_pip_bist_status_s cn56xxp1; ++ struct cvmx_pip_bist_status_s cn58xx; ++ struct cvmx_pip_bist_status_s cn58xxp1; ++}; ++ ++union cvmx_pip_crc_ctlx { ++ uint64_t u64; ++ struct cvmx_pip_crc_ctlx_s { ++ uint64_t reserved_2_63:62; ++ uint64_t invres:1; ++ uint64_t reflect:1; ++ } s; ++ struct cvmx_pip_crc_ctlx_s cn38xx; ++ struct cvmx_pip_crc_ctlx_s cn38xxp2; ++ struct cvmx_pip_crc_ctlx_s cn58xx; ++ struct cvmx_pip_crc_ctlx_s cn58xxp1; ++}; ++ ++union cvmx_pip_crc_ivx { ++ uint64_t u64; ++ struct cvmx_pip_crc_ivx_s { ++ uint64_t reserved_32_63:32; ++ uint64_t iv:32; ++ } s; ++ struct cvmx_pip_crc_ivx_s cn38xx; ++ struct cvmx_pip_crc_ivx_s cn38xxp2; ++ struct cvmx_pip_crc_ivx_s cn58xx; ++ struct cvmx_pip_crc_ivx_s cn58xxp1; ++}; ++ ++union cvmx_pip_dec_ipsecx { ++ uint64_t u64; ++ struct cvmx_pip_dec_ipsecx_s { ++ uint64_t reserved_18_63:46; ++ uint64_t tcp:1; ++ uint64_t udp:1; ++ uint64_t dprt:16; ++ } s; ++ struct cvmx_pip_dec_ipsecx_s cn30xx; ++ struct cvmx_pip_dec_ipsecx_s cn31xx; ++ struct cvmx_pip_dec_ipsecx_s cn38xx; ++ struct cvmx_pip_dec_ipsecx_s cn38xxp2; ++ struct cvmx_pip_dec_ipsecx_s cn50xx; ++ struct cvmx_pip_dec_ipsecx_s cn52xx; ++ struct cvmx_pip_dec_ipsecx_s cn52xxp1; ++ struct cvmx_pip_dec_ipsecx_s cn56xx; ++ struct cvmx_pip_dec_ipsecx_s cn56xxp1; ++ struct cvmx_pip_dec_ipsecx_s cn58xx; ++ struct cvmx_pip_dec_ipsecx_s cn58xxp1; ++}; ++ ++union cvmx_pip_dsa_src_grp { ++ uint64_t u64; ++ struct cvmx_pip_dsa_src_grp_s { ++ uint64_t map15:4; ++ uint64_t map14:4; ++ uint64_t map13:4; ++ uint64_t map12:4; ++ uint64_t map11:4; ++ uint64_t map10:4; ++ uint64_t map9:4; ++ uint64_t map8:4; ++ uint64_t map7:4; ++ uint64_t map6:4; ++ uint64_t map5:4; ++ uint64_t map4:4; ++ uint64_t map3:4; ++ uint64_t map2:4; ++ uint64_t map1:4; ++ uint64_t map0:4; ++ } s; ++ struct cvmx_pip_dsa_src_grp_s cn52xx; ++ struct cvmx_pip_dsa_src_grp_s cn52xxp1; ++ struct cvmx_pip_dsa_src_grp_s cn56xx; ++}; ++ ++union cvmx_pip_dsa_vid_grp { ++ uint64_t u64; ++ struct cvmx_pip_dsa_vid_grp_s { ++ uint64_t map15:4; ++ uint64_t map14:4; ++ uint64_t map13:4; ++ uint64_t map12:4; ++ uint64_t map11:4; ++ uint64_t map10:4; ++ uint64_t map9:4; ++ uint64_t map8:4; ++ uint64_t map7:4; ++ uint64_t map6:4; ++ uint64_t map5:4; ++ uint64_t map4:4; ++ uint64_t map3:4; ++ uint64_t map2:4; ++ uint64_t map1:4; ++ uint64_t map0:4; ++ } s; ++ struct cvmx_pip_dsa_vid_grp_s cn52xx; ++ struct cvmx_pip_dsa_vid_grp_s cn52xxp1; ++ struct cvmx_pip_dsa_vid_grp_s cn56xx; ++}; ++ ++union cvmx_pip_frm_len_chkx { ++ uint64_t u64; ++ struct cvmx_pip_frm_len_chkx_s { ++ uint64_t reserved_32_63:32; ++ uint64_t maxlen:16; ++ uint64_t minlen:16; ++ } s; ++ struct cvmx_pip_frm_len_chkx_s cn50xx; ++ struct cvmx_pip_frm_len_chkx_s cn52xx; ++ struct cvmx_pip_frm_len_chkx_s cn52xxp1; ++ struct cvmx_pip_frm_len_chkx_s cn56xx; ++ struct cvmx_pip_frm_len_chkx_s cn56xxp1; ++}; ++ ++union cvmx_pip_gbl_cfg { ++ uint64_t u64; ++ struct cvmx_pip_gbl_cfg_s { ++ uint64_t reserved_19_63:45; ++ uint64_t tag_syn:1; ++ uint64_t ip6_udp:1; ++ uint64_t max_l2:1; ++ uint64_t reserved_11_15:5; ++ uint64_t raw_shf:3; ++ uint64_t reserved_3_7:5; ++ uint64_t nip_shf:3; ++ } s; ++ struct cvmx_pip_gbl_cfg_s cn30xx; ++ struct cvmx_pip_gbl_cfg_s cn31xx; ++ struct cvmx_pip_gbl_cfg_s cn38xx; ++ struct cvmx_pip_gbl_cfg_s cn38xxp2; ++ struct cvmx_pip_gbl_cfg_s cn50xx; ++ struct cvmx_pip_gbl_cfg_s cn52xx; ++ struct cvmx_pip_gbl_cfg_s cn52xxp1; ++ struct cvmx_pip_gbl_cfg_s cn56xx; ++ struct cvmx_pip_gbl_cfg_s cn56xxp1; ++ struct cvmx_pip_gbl_cfg_s cn58xx; ++ struct cvmx_pip_gbl_cfg_s cn58xxp1; ++}; ++ ++union cvmx_pip_gbl_ctl { ++ uint64_t u64; ++ struct cvmx_pip_gbl_ctl_s { ++ uint64_t reserved_27_63:37; ++ uint64_t dsa_grp_tvid:1; ++ uint64_t dsa_grp_scmd:1; ++ uint64_t dsa_grp_sid:1; ++ uint64_t reserved_21_23:3; ++ uint64_t ring_en:1; ++ uint64_t reserved_17_19:3; ++ uint64_t ignrs:1; ++ uint64_t vs_wqe:1; ++ uint64_t vs_qos:1; ++ uint64_t l2_mal:1; ++ uint64_t tcp_flag:1; ++ uint64_t l4_len:1; ++ uint64_t l4_chk:1; ++ uint64_t l4_prt:1; ++ uint64_t l4_mal:1; ++ uint64_t reserved_6_7:2; ++ uint64_t ip6_eext:2; ++ uint64_t ip4_opts:1; ++ uint64_t ip_hop:1; ++ uint64_t ip_mal:1; ++ uint64_t ip_chk:1; ++ } s; ++ struct cvmx_pip_gbl_ctl_cn30xx { ++ uint64_t reserved_17_63:47; ++ uint64_t ignrs:1; ++ uint64_t vs_wqe:1; ++ uint64_t vs_qos:1; ++ uint64_t l2_mal:1; ++ uint64_t tcp_flag:1; ++ uint64_t l4_len:1; ++ uint64_t l4_chk:1; ++ uint64_t l4_prt:1; ++ uint64_t l4_mal:1; ++ uint64_t reserved_6_7:2; ++ uint64_t ip6_eext:2; ++ uint64_t ip4_opts:1; ++ uint64_t ip_hop:1; ++ uint64_t ip_mal:1; ++ uint64_t ip_chk:1; ++ } cn30xx; ++ struct cvmx_pip_gbl_ctl_cn30xx cn31xx; ++ struct cvmx_pip_gbl_ctl_cn30xx cn38xx; ++ struct cvmx_pip_gbl_ctl_cn30xx cn38xxp2; ++ struct cvmx_pip_gbl_ctl_cn30xx cn50xx; ++ struct cvmx_pip_gbl_ctl_s cn52xx; ++ struct cvmx_pip_gbl_ctl_s cn52xxp1; ++ struct cvmx_pip_gbl_ctl_s cn56xx; ++ struct cvmx_pip_gbl_ctl_cn56xxp1 { ++ uint64_t reserved_21_63:43; ++ uint64_t ring_en:1; ++ uint64_t reserved_17_19:3; ++ uint64_t ignrs:1; ++ uint64_t vs_wqe:1; ++ uint64_t vs_qos:1; ++ uint64_t l2_mal:1; ++ uint64_t tcp_flag:1; ++ uint64_t l4_len:1; ++ uint64_t l4_chk:1; ++ uint64_t l4_prt:1; ++ uint64_t l4_mal:1; ++ uint64_t reserved_6_7:2; ++ uint64_t ip6_eext:2; ++ uint64_t ip4_opts:1; ++ uint64_t ip_hop:1; ++ uint64_t ip_mal:1; ++ uint64_t ip_chk:1; ++ } cn56xxp1; ++ struct cvmx_pip_gbl_ctl_cn30xx cn58xx; ++ struct cvmx_pip_gbl_ctl_cn30xx cn58xxp1; ++}; ++ ++union cvmx_pip_hg_pri_qos { ++ uint64_t u64; ++ struct cvmx_pip_hg_pri_qos_s { ++ uint64_t reserved_11_63:53; ++ uint64_t qos:3; ++ uint64_t reserved_6_7:2; ++ uint64_t pri:6; ++ } s; ++ struct cvmx_pip_hg_pri_qos_s cn52xx; ++ struct cvmx_pip_hg_pri_qos_s cn52xxp1; ++ struct cvmx_pip_hg_pri_qos_s cn56xx; ++}; ++ ++union cvmx_pip_int_en { ++ uint64_t u64; ++ struct cvmx_pip_int_en_s { ++ uint64_t reserved_13_63:51; ++ uint64_t punyerr:1; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } s; ++ struct cvmx_pip_int_en_cn30xx { ++ uint64_t reserved_9_63:55; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } cn30xx; ++ struct cvmx_pip_int_en_cn30xx cn31xx; ++ struct cvmx_pip_int_en_cn30xx cn38xx; ++ struct cvmx_pip_int_en_cn30xx cn38xxp2; ++ struct cvmx_pip_int_en_cn50xx { ++ uint64_t reserved_12_63:52; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t reserved_1_1:1; ++ uint64_t pktdrp:1; ++ } cn50xx; ++ struct cvmx_pip_int_en_cn52xx { ++ uint64_t reserved_13_63:51; ++ uint64_t punyerr:1; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t reserved_1_1:1; ++ uint64_t pktdrp:1; ++ } cn52xx; ++ struct cvmx_pip_int_en_cn52xx cn52xxp1; ++ struct cvmx_pip_int_en_s cn56xx; ++ struct cvmx_pip_int_en_cn56xxp1 { ++ uint64_t reserved_12_63:52; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } cn56xxp1; ++ struct cvmx_pip_int_en_cn58xx { ++ uint64_t reserved_13_63:51; ++ uint64_t punyerr:1; ++ uint64_t reserved_9_11:3; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } cn58xx; ++ struct cvmx_pip_int_en_cn30xx cn58xxp1; ++}; ++ ++union cvmx_pip_int_reg { ++ uint64_t u64; ++ struct cvmx_pip_int_reg_s { ++ uint64_t reserved_13_63:51; ++ uint64_t punyerr:1; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } s; ++ struct cvmx_pip_int_reg_cn30xx { ++ uint64_t reserved_9_63:55; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } cn30xx; ++ struct cvmx_pip_int_reg_cn30xx cn31xx; ++ struct cvmx_pip_int_reg_cn30xx cn38xx; ++ struct cvmx_pip_int_reg_cn30xx cn38xxp2; ++ struct cvmx_pip_int_reg_cn50xx { ++ uint64_t reserved_12_63:52; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t reserved_1_1:1; ++ uint64_t pktdrp:1; ++ } cn50xx; ++ struct cvmx_pip_int_reg_cn52xx { ++ uint64_t reserved_13_63:51; ++ uint64_t punyerr:1; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t reserved_1_1:1; ++ uint64_t pktdrp:1; ++ } cn52xx; ++ struct cvmx_pip_int_reg_cn52xx cn52xxp1; ++ struct cvmx_pip_int_reg_s cn56xx; ++ struct cvmx_pip_int_reg_cn56xxp1 { ++ uint64_t reserved_12_63:52; ++ uint64_t lenerr:1; ++ uint64_t maxerr:1; ++ uint64_t minerr:1; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } cn56xxp1; ++ struct cvmx_pip_int_reg_cn58xx { ++ uint64_t reserved_13_63:51; ++ uint64_t punyerr:1; ++ uint64_t reserved_9_11:3; ++ uint64_t beperr:1; ++ uint64_t feperr:1; ++ uint64_t todoovr:1; ++ uint64_t skprunt:1; ++ uint64_t badtag:1; ++ uint64_t prtnxa:1; ++ uint64_t bckprs:1; ++ uint64_t crcerr:1; ++ uint64_t pktdrp:1; ++ } cn58xx; ++ struct cvmx_pip_int_reg_cn30xx cn58xxp1; ++}; ++ ++union cvmx_pip_ip_offset { ++ uint64_t u64; ++ struct cvmx_pip_ip_offset_s { ++ uint64_t reserved_3_63:61; ++ uint64_t offset:3; ++ } s; ++ struct cvmx_pip_ip_offset_s cn30xx; ++ struct cvmx_pip_ip_offset_s cn31xx; ++ struct cvmx_pip_ip_offset_s cn38xx; ++ struct cvmx_pip_ip_offset_s cn38xxp2; ++ struct cvmx_pip_ip_offset_s cn50xx; ++ struct cvmx_pip_ip_offset_s cn52xx; ++ struct cvmx_pip_ip_offset_s cn52xxp1; ++ struct cvmx_pip_ip_offset_s cn56xx; ++ struct cvmx_pip_ip_offset_s cn56xxp1; ++ struct cvmx_pip_ip_offset_s cn58xx; ++ struct cvmx_pip_ip_offset_s cn58xxp1; ++}; ++ ++union cvmx_pip_prt_cfgx { ++ uint64_t u64; ++ struct cvmx_pip_prt_cfgx_s { ++ uint64_t reserved_53_63:11; ++ uint64_t pad_len:1; ++ uint64_t vlan_len:1; ++ uint64_t lenerr_en:1; ++ uint64_t maxerr_en:1; ++ uint64_t minerr_en:1; ++ uint64_t grp_wat_47:4; ++ uint64_t qos_wat_47:4; ++ uint64_t reserved_37_39:3; ++ uint64_t rawdrp:1; ++ uint64_t tag_inc:2; ++ uint64_t dyn_rs:1; ++ uint64_t inst_hdr:1; ++ uint64_t grp_wat:4; ++ uint64_t hg_qos:1; ++ uint64_t qos:3; ++ uint64_t qos_wat:4; ++ uint64_t qos_vsel:1; ++ uint64_t qos_vod:1; ++ uint64_t qos_diff:1; ++ uint64_t qos_vlan:1; ++ uint64_t reserved_13_15:3; ++ uint64_t crc_en:1; ++ uint64_t higig_en:1; ++ uint64_t dsa_en:1; ++ uint64_t mode:2; ++ uint64_t reserved_7_7:1; ++ uint64_t skip:7; ++ } s; ++ struct cvmx_pip_prt_cfgx_cn30xx { ++ uint64_t reserved_37_63:27; ++ uint64_t rawdrp:1; ++ uint64_t tag_inc:2; ++ uint64_t dyn_rs:1; ++ uint64_t inst_hdr:1; ++ uint64_t grp_wat:4; ++ uint64_t reserved_27_27:1; ++ uint64_t qos:3; ++ uint64_t qos_wat:4; ++ uint64_t reserved_18_19:2; ++ uint64_t qos_diff:1; ++ uint64_t qos_vlan:1; ++ uint64_t reserved_10_15:6; ++ uint64_t mode:2; ++ uint64_t reserved_7_7:1; ++ uint64_t skip:7; ++ } cn30xx; ++ struct cvmx_pip_prt_cfgx_cn30xx cn31xx; ++ struct cvmx_pip_prt_cfgx_cn38xx { ++ uint64_t reserved_37_63:27; ++ uint64_t rawdrp:1; ++ uint64_t tag_inc:2; ++ uint64_t dyn_rs:1; ++ uint64_t inst_hdr:1; ++ uint64_t grp_wat:4; ++ uint64_t reserved_27_27:1; ++ uint64_t qos:3; ++ uint64_t qos_wat:4; ++ uint64_t reserved_18_19:2; ++ uint64_t qos_diff:1; ++ uint64_t qos_vlan:1; ++ uint64_t reserved_13_15:3; ++ uint64_t crc_en:1; ++ uint64_t reserved_10_11:2; ++ uint64_t mode:2; ++ uint64_t reserved_7_7:1; ++ uint64_t skip:7; ++ } cn38xx; ++ struct cvmx_pip_prt_cfgx_cn38xx cn38xxp2; ++ struct cvmx_pip_prt_cfgx_cn50xx { ++ uint64_t reserved_53_63:11; ++ uint64_t pad_len:1; ++ uint64_t vlan_len:1; ++ uint64_t lenerr_en:1; ++ uint64_t maxerr_en:1; ++ uint64_t minerr_en:1; ++ uint64_t grp_wat_47:4; ++ uint64_t qos_wat_47:4; ++ uint64_t reserved_37_39:3; ++ uint64_t rawdrp:1; ++ uint64_t tag_inc:2; ++ uint64_t dyn_rs:1; ++ uint64_t inst_hdr:1; ++ uint64_t grp_wat:4; ++ uint64_t reserved_27_27:1; ++ uint64_t qos:3; ++ uint64_t qos_wat:4; ++ uint64_t reserved_19_19:1; ++ uint64_t qos_vod:1; ++ uint64_t qos_diff:1; ++ uint64_t qos_vlan:1; ++ uint64_t reserved_13_15:3; ++ uint64_t crc_en:1; ++ uint64_t reserved_10_11:2; ++ uint64_t mode:2; ++ uint64_t reserved_7_7:1; ++ uint64_t skip:7; ++ } cn50xx; ++ struct cvmx_pip_prt_cfgx_s cn52xx; ++ struct cvmx_pip_prt_cfgx_s cn52xxp1; ++ struct cvmx_pip_prt_cfgx_s cn56xx; ++ struct cvmx_pip_prt_cfgx_cn50xx cn56xxp1; ++ struct cvmx_pip_prt_cfgx_cn58xx { ++ uint64_t reserved_37_63:27; ++ uint64_t rawdrp:1; ++ uint64_t tag_inc:2; ++ uint64_t dyn_rs:1; ++ uint64_t inst_hdr:1; ++ uint64_t grp_wat:4; ++ uint64_t reserved_27_27:1; ++ uint64_t qos:3; ++ uint64_t qos_wat:4; ++ uint64_t reserved_19_19:1; ++ uint64_t qos_vod:1; ++ uint64_t qos_diff:1; ++ uint64_t qos_vlan:1; ++ uint64_t reserved_13_15:3; ++ uint64_t crc_en:1; ++ uint64_t reserved_10_11:2; ++ uint64_t mode:2; ++ uint64_t reserved_7_7:1; ++ uint64_t skip:7; ++ } cn58xx; ++ struct cvmx_pip_prt_cfgx_cn58xx cn58xxp1; ++}; ++ ++union cvmx_pip_prt_tagx { ++ uint64_t u64; ++ struct cvmx_pip_prt_tagx_s { ++ uint64_t reserved_40_63:24; ++ uint64_t grptagbase:4; ++ uint64_t grptagmask:4; ++ uint64_t grptag:1; ++ uint64_t grptag_mskip:1; ++ uint64_t tag_mode:2; ++ uint64_t inc_vs:2; ++ uint64_t inc_vlan:1; ++ uint64_t inc_prt_flag:1; ++ uint64_t ip6_dprt_flag:1; ++ uint64_t ip4_dprt_flag:1; ++ uint64_t ip6_sprt_flag:1; ++ uint64_t ip4_sprt_flag:1; ++ uint64_t ip6_nxth_flag:1; ++ uint64_t ip4_pctl_flag:1; ++ uint64_t ip6_dst_flag:1; ++ uint64_t ip4_dst_flag:1; ++ uint64_t ip6_src_flag:1; ++ uint64_t ip4_src_flag:1; ++ uint64_t tcp6_tag_type:2; ++ uint64_t tcp4_tag_type:2; ++ uint64_t ip6_tag_type:2; ++ uint64_t ip4_tag_type:2; ++ uint64_t non_tag_type:2; ++ uint64_t grp:4; ++ } s; ++ struct cvmx_pip_prt_tagx_cn30xx { ++ uint64_t reserved_40_63:24; ++ uint64_t grptagbase:4; ++ uint64_t grptagmask:4; ++ uint64_t grptag:1; ++ uint64_t reserved_30_30:1; ++ uint64_t tag_mode:2; ++ uint64_t inc_vs:2; ++ uint64_t inc_vlan:1; ++ uint64_t inc_prt_flag:1; ++ uint64_t ip6_dprt_flag:1; ++ uint64_t ip4_dprt_flag:1; ++ uint64_t ip6_sprt_flag:1; ++ uint64_t ip4_sprt_flag:1; ++ uint64_t ip6_nxth_flag:1; ++ uint64_t ip4_pctl_flag:1; ++ uint64_t ip6_dst_flag:1; ++ uint64_t ip4_dst_flag:1; ++ uint64_t ip6_src_flag:1; ++ uint64_t ip4_src_flag:1; ++ uint64_t tcp6_tag_type:2; ++ uint64_t tcp4_tag_type:2; ++ uint64_t ip6_tag_type:2; ++ uint64_t ip4_tag_type:2; ++ uint64_t non_tag_type:2; ++ uint64_t grp:4; ++ } cn30xx; ++ struct cvmx_pip_prt_tagx_cn30xx cn31xx; ++ struct cvmx_pip_prt_tagx_cn30xx cn38xx; ++ struct cvmx_pip_prt_tagx_cn30xx cn38xxp2; ++ struct cvmx_pip_prt_tagx_s cn50xx; ++ struct cvmx_pip_prt_tagx_s cn52xx; ++ struct cvmx_pip_prt_tagx_s cn52xxp1; ++ struct cvmx_pip_prt_tagx_s cn56xx; ++ struct cvmx_pip_prt_tagx_s cn56xxp1; ++ struct cvmx_pip_prt_tagx_cn30xx cn58xx; ++ struct cvmx_pip_prt_tagx_cn30xx cn58xxp1; ++}; ++ ++union cvmx_pip_qos_diffx { ++ uint64_t u64; ++ struct cvmx_pip_qos_diffx_s { ++ uint64_t reserved_3_63:61; ++ uint64_t qos:3; ++ } s; ++ struct cvmx_pip_qos_diffx_s cn30xx; ++ struct cvmx_pip_qos_diffx_s cn31xx; ++ struct cvmx_pip_qos_diffx_s cn38xx; ++ struct cvmx_pip_qos_diffx_s cn38xxp2; ++ struct cvmx_pip_qos_diffx_s cn50xx; ++ struct cvmx_pip_qos_diffx_s cn52xx; ++ struct cvmx_pip_qos_diffx_s cn52xxp1; ++ struct cvmx_pip_qos_diffx_s cn56xx; ++ struct cvmx_pip_qos_diffx_s cn56xxp1; ++ struct cvmx_pip_qos_diffx_s cn58xx; ++ struct cvmx_pip_qos_diffx_s cn58xxp1; ++}; ++ ++union cvmx_pip_qos_vlanx { ++ uint64_t u64; ++ struct cvmx_pip_qos_vlanx_s { ++ uint64_t reserved_7_63:57; ++ uint64_t qos1:3; ++ uint64_t reserved_3_3:1; ++ uint64_t qos:3; ++ } s; ++ struct cvmx_pip_qos_vlanx_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t qos:3; ++ } cn30xx; ++ struct cvmx_pip_qos_vlanx_cn30xx cn31xx; ++ struct cvmx_pip_qos_vlanx_cn30xx cn38xx; ++ struct cvmx_pip_qos_vlanx_cn30xx cn38xxp2; ++ struct cvmx_pip_qos_vlanx_cn30xx cn50xx; ++ struct cvmx_pip_qos_vlanx_s cn52xx; ++ struct cvmx_pip_qos_vlanx_s cn52xxp1; ++ struct cvmx_pip_qos_vlanx_s cn56xx; ++ struct cvmx_pip_qos_vlanx_cn30xx cn56xxp1; ++ struct cvmx_pip_qos_vlanx_cn30xx cn58xx; ++ struct cvmx_pip_qos_vlanx_cn30xx cn58xxp1; ++}; ++ ++union cvmx_pip_qos_watchx { ++ uint64_t u64; ++ struct cvmx_pip_qos_watchx_s { ++ uint64_t reserved_48_63:16; ++ uint64_t mask:16; ++ uint64_t reserved_28_31:4; ++ uint64_t grp:4; ++ uint64_t reserved_23_23:1; ++ uint64_t qos:3; ++ uint64_t reserved_19_19:1; ++ uint64_t match_type:3; ++ uint64_t match_value:16; ++ } s; ++ struct cvmx_pip_qos_watchx_cn30xx { ++ uint64_t reserved_48_63:16; ++ uint64_t mask:16; ++ uint64_t reserved_28_31:4; ++ uint64_t grp:4; ++ uint64_t reserved_23_23:1; ++ uint64_t qos:3; ++ uint64_t reserved_18_19:2; ++ uint64_t match_type:2; ++ uint64_t match_value:16; ++ } cn30xx; ++ struct cvmx_pip_qos_watchx_cn30xx cn31xx; ++ struct cvmx_pip_qos_watchx_cn30xx cn38xx; ++ struct cvmx_pip_qos_watchx_cn30xx cn38xxp2; ++ struct cvmx_pip_qos_watchx_s cn50xx; ++ struct cvmx_pip_qos_watchx_s cn52xx; ++ struct cvmx_pip_qos_watchx_s cn52xxp1; ++ struct cvmx_pip_qos_watchx_s cn56xx; ++ struct cvmx_pip_qos_watchx_s cn56xxp1; ++ struct cvmx_pip_qos_watchx_cn30xx cn58xx; ++ struct cvmx_pip_qos_watchx_cn30xx cn58xxp1; ++}; ++ ++union cvmx_pip_raw_word { ++ uint64_t u64; ++ struct cvmx_pip_raw_word_s { ++ uint64_t reserved_56_63:8; ++ uint64_t word:56; ++ } s; ++ struct cvmx_pip_raw_word_s cn30xx; ++ struct cvmx_pip_raw_word_s cn31xx; ++ struct cvmx_pip_raw_word_s cn38xx; ++ struct cvmx_pip_raw_word_s cn38xxp2; ++ struct cvmx_pip_raw_word_s cn50xx; ++ struct cvmx_pip_raw_word_s cn52xx; ++ struct cvmx_pip_raw_word_s cn52xxp1; ++ struct cvmx_pip_raw_word_s cn56xx; ++ struct cvmx_pip_raw_word_s cn56xxp1; ++ struct cvmx_pip_raw_word_s cn58xx; ++ struct cvmx_pip_raw_word_s cn58xxp1; ++}; ++ ++union cvmx_pip_sft_rst { ++ uint64_t u64; ++ struct cvmx_pip_sft_rst_s { ++ uint64_t reserved_1_63:63; ++ uint64_t rst:1; ++ } s; ++ struct cvmx_pip_sft_rst_s cn30xx; ++ struct cvmx_pip_sft_rst_s cn31xx; ++ struct cvmx_pip_sft_rst_s cn38xx; ++ struct cvmx_pip_sft_rst_s cn50xx; ++ struct cvmx_pip_sft_rst_s cn52xx; ++ struct cvmx_pip_sft_rst_s cn52xxp1; ++ struct cvmx_pip_sft_rst_s cn56xx; ++ struct cvmx_pip_sft_rst_s cn56xxp1; ++ struct cvmx_pip_sft_rst_s cn58xx; ++ struct cvmx_pip_sft_rst_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat0_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat0_prtx_s { ++ uint64_t drp_pkts:32; ++ uint64_t drp_octs:32; ++ } s; ++ struct cvmx_pip_stat0_prtx_s cn30xx; ++ struct cvmx_pip_stat0_prtx_s cn31xx; ++ struct cvmx_pip_stat0_prtx_s cn38xx; ++ struct cvmx_pip_stat0_prtx_s cn38xxp2; ++ struct cvmx_pip_stat0_prtx_s cn50xx; ++ struct cvmx_pip_stat0_prtx_s cn52xx; ++ struct cvmx_pip_stat0_prtx_s cn52xxp1; ++ struct cvmx_pip_stat0_prtx_s cn56xx; ++ struct cvmx_pip_stat0_prtx_s cn56xxp1; ++ struct cvmx_pip_stat0_prtx_s cn58xx; ++ struct cvmx_pip_stat0_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat1_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat1_prtx_s { ++ uint64_t reserved_48_63:16; ++ uint64_t octs:48; ++ } s; ++ struct cvmx_pip_stat1_prtx_s cn30xx; ++ struct cvmx_pip_stat1_prtx_s cn31xx; ++ struct cvmx_pip_stat1_prtx_s cn38xx; ++ struct cvmx_pip_stat1_prtx_s cn38xxp2; ++ struct cvmx_pip_stat1_prtx_s cn50xx; ++ struct cvmx_pip_stat1_prtx_s cn52xx; ++ struct cvmx_pip_stat1_prtx_s cn52xxp1; ++ struct cvmx_pip_stat1_prtx_s cn56xx; ++ struct cvmx_pip_stat1_prtx_s cn56xxp1; ++ struct cvmx_pip_stat1_prtx_s cn58xx; ++ struct cvmx_pip_stat1_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat2_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat2_prtx_s { ++ uint64_t pkts:32; ++ uint64_t raw:32; ++ } s; ++ struct cvmx_pip_stat2_prtx_s cn30xx; ++ struct cvmx_pip_stat2_prtx_s cn31xx; ++ struct cvmx_pip_stat2_prtx_s cn38xx; ++ struct cvmx_pip_stat2_prtx_s cn38xxp2; ++ struct cvmx_pip_stat2_prtx_s cn50xx; ++ struct cvmx_pip_stat2_prtx_s cn52xx; ++ struct cvmx_pip_stat2_prtx_s cn52xxp1; ++ struct cvmx_pip_stat2_prtx_s cn56xx; ++ struct cvmx_pip_stat2_prtx_s cn56xxp1; ++ struct cvmx_pip_stat2_prtx_s cn58xx; ++ struct cvmx_pip_stat2_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat3_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat3_prtx_s { ++ uint64_t bcst:32; ++ uint64_t mcst:32; ++ } s; ++ struct cvmx_pip_stat3_prtx_s cn30xx; ++ struct cvmx_pip_stat3_prtx_s cn31xx; ++ struct cvmx_pip_stat3_prtx_s cn38xx; ++ struct cvmx_pip_stat3_prtx_s cn38xxp2; ++ struct cvmx_pip_stat3_prtx_s cn50xx; ++ struct cvmx_pip_stat3_prtx_s cn52xx; ++ struct cvmx_pip_stat3_prtx_s cn52xxp1; ++ struct cvmx_pip_stat3_prtx_s cn56xx; ++ struct cvmx_pip_stat3_prtx_s cn56xxp1; ++ struct cvmx_pip_stat3_prtx_s cn58xx; ++ struct cvmx_pip_stat3_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat4_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat4_prtx_s { ++ uint64_t h65to127:32; ++ uint64_t h64:32; ++ } s; ++ struct cvmx_pip_stat4_prtx_s cn30xx; ++ struct cvmx_pip_stat4_prtx_s cn31xx; ++ struct cvmx_pip_stat4_prtx_s cn38xx; ++ struct cvmx_pip_stat4_prtx_s cn38xxp2; ++ struct cvmx_pip_stat4_prtx_s cn50xx; ++ struct cvmx_pip_stat4_prtx_s cn52xx; ++ struct cvmx_pip_stat4_prtx_s cn52xxp1; ++ struct cvmx_pip_stat4_prtx_s cn56xx; ++ struct cvmx_pip_stat4_prtx_s cn56xxp1; ++ struct cvmx_pip_stat4_prtx_s cn58xx; ++ struct cvmx_pip_stat4_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat5_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat5_prtx_s { ++ uint64_t h256to511:32; ++ uint64_t h128to255:32; ++ } s; ++ struct cvmx_pip_stat5_prtx_s cn30xx; ++ struct cvmx_pip_stat5_prtx_s cn31xx; ++ struct cvmx_pip_stat5_prtx_s cn38xx; ++ struct cvmx_pip_stat5_prtx_s cn38xxp2; ++ struct cvmx_pip_stat5_prtx_s cn50xx; ++ struct cvmx_pip_stat5_prtx_s cn52xx; ++ struct cvmx_pip_stat5_prtx_s cn52xxp1; ++ struct cvmx_pip_stat5_prtx_s cn56xx; ++ struct cvmx_pip_stat5_prtx_s cn56xxp1; ++ struct cvmx_pip_stat5_prtx_s cn58xx; ++ struct cvmx_pip_stat5_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat6_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat6_prtx_s { ++ uint64_t h1024to1518:32; ++ uint64_t h512to1023:32; ++ } s; ++ struct cvmx_pip_stat6_prtx_s cn30xx; ++ struct cvmx_pip_stat6_prtx_s cn31xx; ++ struct cvmx_pip_stat6_prtx_s cn38xx; ++ struct cvmx_pip_stat6_prtx_s cn38xxp2; ++ struct cvmx_pip_stat6_prtx_s cn50xx; ++ struct cvmx_pip_stat6_prtx_s cn52xx; ++ struct cvmx_pip_stat6_prtx_s cn52xxp1; ++ struct cvmx_pip_stat6_prtx_s cn56xx; ++ struct cvmx_pip_stat6_prtx_s cn56xxp1; ++ struct cvmx_pip_stat6_prtx_s cn58xx; ++ struct cvmx_pip_stat6_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat7_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat7_prtx_s { ++ uint64_t fcs:32; ++ uint64_t h1519:32; ++ } s; ++ struct cvmx_pip_stat7_prtx_s cn30xx; ++ struct cvmx_pip_stat7_prtx_s cn31xx; ++ struct cvmx_pip_stat7_prtx_s cn38xx; ++ struct cvmx_pip_stat7_prtx_s cn38xxp2; ++ struct cvmx_pip_stat7_prtx_s cn50xx; ++ struct cvmx_pip_stat7_prtx_s cn52xx; ++ struct cvmx_pip_stat7_prtx_s cn52xxp1; ++ struct cvmx_pip_stat7_prtx_s cn56xx; ++ struct cvmx_pip_stat7_prtx_s cn56xxp1; ++ struct cvmx_pip_stat7_prtx_s cn58xx; ++ struct cvmx_pip_stat7_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat8_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat8_prtx_s { ++ uint64_t frag:32; ++ uint64_t undersz:32; ++ } s; ++ struct cvmx_pip_stat8_prtx_s cn30xx; ++ struct cvmx_pip_stat8_prtx_s cn31xx; ++ struct cvmx_pip_stat8_prtx_s cn38xx; ++ struct cvmx_pip_stat8_prtx_s cn38xxp2; ++ struct cvmx_pip_stat8_prtx_s cn50xx; ++ struct cvmx_pip_stat8_prtx_s cn52xx; ++ struct cvmx_pip_stat8_prtx_s cn52xxp1; ++ struct cvmx_pip_stat8_prtx_s cn56xx; ++ struct cvmx_pip_stat8_prtx_s cn56xxp1; ++ struct cvmx_pip_stat8_prtx_s cn58xx; ++ struct cvmx_pip_stat8_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat9_prtx { ++ uint64_t u64; ++ struct cvmx_pip_stat9_prtx_s { ++ uint64_t jabber:32; ++ uint64_t oversz:32; ++ } s; ++ struct cvmx_pip_stat9_prtx_s cn30xx; ++ struct cvmx_pip_stat9_prtx_s cn31xx; ++ struct cvmx_pip_stat9_prtx_s cn38xx; ++ struct cvmx_pip_stat9_prtx_s cn38xxp2; ++ struct cvmx_pip_stat9_prtx_s cn50xx; ++ struct cvmx_pip_stat9_prtx_s cn52xx; ++ struct cvmx_pip_stat9_prtx_s cn52xxp1; ++ struct cvmx_pip_stat9_prtx_s cn56xx; ++ struct cvmx_pip_stat9_prtx_s cn56xxp1; ++ struct cvmx_pip_stat9_prtx_s cn58xx; ++ struct cvmx_pip_stat9_prtx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat_ctl { ++ uint64_t u64; ++ struct cvmx_pip_stat_ctl_s { ++ uint64_t reserved_1_63:63; ++ uint64_t rdclr:1; ++ } s; ++ struct cvmx_pip_stat_ctl_s cn30xx; ++ struct cvmx_pip_stat_ctl_s cn31xx; ++ struct cvmx_pip_stat_ctl_s cn38xx; ++ struct cvmx_pip_stat_ctl_s cn38xxp2; ++ struct cvmx_pip_stat_ctl_s cn50xx; ++ struct cvmx_pip_stat_ctl_s cn52xx; ++ struct cvmx_pip_stat_ctl_s cn52xxp1; ++ struct cvmx_pip_stat_ctl_s cn56xx; ++ struct cvmx_pip_stat_ctl_s cn56xxp1; ++ struct cvmx_pip_stat_ctl_s cn58xx; ++ struct cvmx_pip_stat_ctl_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat_inb_errsx { ++ uint64_t u64; ++ struct cvmx_pip_stat_inb_errsx_s { ++ uint64_t reserved_16_63:48; ++ uint64_t errs:16; ++ } s; ++ struct cvmx_pip_stat_inb_errsx_s cn30xx; ++ struct cvmx_pip_stat_inb_errsx_s cn31xx; ++ struct cvmx_pip_stat_inb_errsx_s cn38xx; ++ struct cvmx_pip_stat_inb_errsx_s cn38xxp2; ++ struct cvmx_pip_stat_inb_errsx_s cn50xx; ++ struct cvmx_pip_stat_inb_errsx_s cn52xx; ++ struct cvmx_pip_stat_inb_errsx_s cn52xxp1; ++ struct cvmx_pip_stat_inb_errsx_s cn56xx; ++ struct cvmx_pip_stat_inb_errsx_s cn56xxp1; ++ struct cvmx_pip_stat_inb_errsx_s cn58xx; ++ struct cvmx_pip_stat_inb_errsx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat_inb_octsx { ++ uint64_t u64; ++ struct cvmx_pip_stat_inb_octsx_s { ++ uint64_t reserved_48_63:16; ++ uint64_t octs:48; ++ } s; ++ struct cvmx_pip_stat_inb_octsx_s cn30xx; ++ struct cvmx_pip_stat_inb_octsx_s cn31xx; ++ struct cvmx_pip_stat_inb_octsx_s cn38xx; ++ struct cvmx_pip_stat_inb_octsx_s cn38xxp2; ++ struct cvmx_pip_stat_inb_octsx_s cn50xx; ++ struct cvmx_pip_stat_inb_octsx_s cn52xx; ++ struct cvmx_pip_stat_inb_octsx_s cn52xxp1; ++ struct cvmx_pip_stat_inb_octsx_s cn56xx; ++ struct cvmx_pip_stat_inb_octsx_s cn56xxp1; ++ struct cvmx_pip_stat_inb_octsx_s cn58xx; ++ struct cvmx_pip_stat_inb_octsx_s cn58xxp1; ++}; ++ ++union cvmx_pip_stat_inb_pktsx { ++ uint64_t u64; ++ struct cvmx_pip_stat_inb_pktsx_s { ++ uint64_t reserved_32_63:32; ++ uint64_t pkts:32; ++ } s; ++ struct cvmx_pip_stat_inb_pktsx_s cn30xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn31xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn38xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn38xxp2; ++ struct cvmx_pip_stat_inb_pktsx_s cn50xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn52xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn52xxp1; ++ struct cvmx_pip_stat_inb_pktsx_s cn56xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn56xxp1; ++ struct cvmx_pip_stat_inb_pktsx_s cn58xx; ++ struct cvmx_pip_stat_inb_pktsx_s cn58xxp1; ++}; ++ ++union cvmx_pip_tag_incx { ++ uint64_t u64; ++ struct cvmx_pip_tag_incx_s { ++ uint64_t reserved_8_63:56; ++ uint64_t en:8; ++ } s; ++ struct cvmx_pip_tag_incx_s cn30xx; ++ struct cvmx_pip_tag_incx_s cn31xx; ++ struct cvmx_pip_tag_incx_s cn38xx; ++ struct cvmx_pip_tag_incx_s cn38xxp2; ++ struct cvmx_pip_tag_incx_s cn50xx; ++ struct cvmx_pip_tag_incx_s cn52xx; ++ struct cvmx_pip_tag_incx_s cn52xxp1; ++ struct cvmx_pip_tag_incx_s cn56xx; ++ struct cvmx_pip_tag_incx_s cn56xxp1; ++ struct cvmx_pip_tag_incx_s cn58xx; ++ struct cvmx_pip_tag_incx_s cn58xxp1; ++}; ++ ++union cvmx_pip_tag_mask { ++ uint64_t u64; ++ struct cvmx_pip_tag_mask_s { ++ uint64_t reserved_16_63:48; ++ uint64_t mask:16; ++ } s; ++ struct cvmx_pip_tag_mask_s cn30xx; ++ struct cvmx_pip_tag_mask_s cn31xx; ++ struct cvmx_pip_tag_mask_s cn38xx; ++ struct cvmx_pip_tag_mask_s cn38xxp2; ++ struct cvmx_pip_tag_mask_s cn50xx; ++ struct cvmx_pip_tag_mask_s cn52xx; ++ struct cvmx_pip_tag_mask_s cn52xxp1; ++ struct cvmx_pip_tag_mask_s cn56xx; ++ struct cvmx_pip_tag_mask_s cn56xxp1; ++ struct cvmx_pip_tag_mask_s cn58xx; ++ struct cvmx_pip_tag_mask_s cn58xxp1; ++}; ++ ++union cvmx_pip_tag_secret { ++ uint64_t u64; ++ struct cvmx_pip_tag_secret_s { ++ uint64_t reserved_32_63:32; ++ uint64_t dst:16; ++ uint64_t src:16; ++ } s; ++ struct cvmx_pip_tag_secret_s cn30xx; ++ struct cvmx_pip_tag_secret_s cn31xx; ++ struct cvmx_pip_tag_secret_s cn38xx; ++ struct cvmx_pip_tag_secret_s cn38xxp2; ++ struct cvmx_pip_tag_secret_s cn50xx; ++ struct cvmx_pip_tag_secret_s cn52xx; ++ struct cvmx_pip_tag_secret_s cn52xxp1; ++ struct cvmx_pip_tag_secret_s cn56xx; ++ struct cvmx_pip_tag_secret_s cn56xxp1; ++ struct cvmx_pip_tag_secret_s cn58xx; ++ struct cvmx_pip_tag_secret_s cn58xxp1; ++}; ++ ++union cvmx_pip_todo_entry { ++ uint64_t u64; ++ struct cvmx_pip_todo_entry_s { ++ uint64_t val:1; ++ uint64_t reserved_62_62:1; ++ uint64_t entry:62; ++ } s; ++ struct cvmx_pip_todo_entry_s cn30xx; ++ struct cvmx_pip_todo_entry_s cn31xx; ++ struct cvmx_pip_todo_entry_s cn38xx; ++ struct cvmx_pip_todo_entry_s cn38xxp2; ++ struct cvmx_pip_todo_entry_s cn50xx; ++ struct cvmx_pip_todo_entry_s cn52xx; ++ struct cvmx_pip_todo_entry_s cn52xxp1; ++ struct cvmx_pip_todo_entry_s cn56xx; ++ struct cvmx_pip_todo_entry_s cn56xxp1; ++ struct cvmx_pip_todo_entry_s cn58xx; ++ struct cvmx_pip_todo_entry_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pip.h +@@ -0,0 +1,524 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Interface to the hardware Packet Input Processing unit. ++ * ++ */ ++ ++#ifndef __CVMX_PIP_H__ ++#define __CVMX_PIP_H__ ++ ++#include "cvmx-wqe.h" ++#include "cvmx-fpa.h" ++#include "cvmx-pip-defs.h" ++ ++#define CVMX_PIP_NUM_INPUT_PORTS 40 ++#define CVMX_PIP_NUM_WATCHERS 4 ++ ++/* ++ * Encodes the different error and exception codes ++ */ ++typedef enum { ++ CVMX_PIP_L4_NO_ERR = 0ull, ++ /* ++ * 1 = TCP (UDP) packet not long enough to cover TCP (UDP) ++ * header ++ */ ++ CVMX_PIP_L4_MAL_ERR = 1ull, ++ /* 2 = TCP/UDP checksum failure */ ++ CVMX_PIP_CHK_ERR = 2ull, ++ /* ++ * 3 = TCP/UDP length check (TCP/UDP length does not match IP ++ * length). ++ */ ++ CVMX_PIP_L4_LENGTH_ERR = 3ull, ++ /* 4 = illegal TCP/UDP port (either source or dest port is zero) */ ++ CVMX_PIP_BAD_PRT_ERR = 4ull, ++ /* 8 = TCP flags = FIN only */ ++ CVMX_PIP_TCP_FLG8_ERR = 8ull, ++ /* 9 = TCP flags = 0 */ ++ CVMX_PIP_TCP_FLG9_ERR = 9ull, ++ /* 10 = TCP flags = FIN+RST+* */ ++ CVMX_PIP_TCP_FLG10_ERR = 10ull, ++ /* 11 = TCP flags = SYN+URG+* */ ++ CVMX_PIP_TCP_FLG11_ERR = 11ull, ++ /* 12 = TCP flags = SYN+RST+* */ ++ CVMX_PIP_TCP_FLG12_ERR = 12ull, ++ /* 13 = TCP flags = SYN+FIN+* */ ++ CVMX_PIP_TCP_FLG13_ERR = 13ull ++} cvmx_pip_l4_err_t; ++ ++typedef enum { ++ ++ CVMX_PIP_IP_NO_ERR = 0ull, ++ /* 1 = not IPv4 or IPv6 */ ++ CVMX_PIP_NOT_IP = 1ull, ++ /* 2 = IPv4 header checksum violation */ ++ CVMX_PIP_IPV4_HDR_CHK = 2ull, ++ /* 3 = malformed (packet not long enough to cover IP hdr) */ ++ CVMX_PIP_IP_MAL_HDR = 3ull, ++ /* 4 = malformed (packet not long enough to cover len in IP hdr) */ ++ CVMX_PIP_IP_MAL_PKT = 4ull, ++ /* 5 = TTL / hop count equal zero */ ++ CVMX_PIP_TTL_HOP = 5ull, ++ /* 6 = IPv4 options / IPv6 early extension headers */ ++ CVMX_PIP_OPTS = 6ull ++} cvmx_pip_ip_exc_t; ++ ++/** ++ * NOTES ++ * late collision (data received before collision) ++ * late collisions cannot be detected by the receiver ++ * they would appear as JAM bits which would appear as bad FCS ++ * or carrier extend error which is CVMX_PIP_EXTEND_ERR ++ */ ++typedef enum { ++ /* No error */ ++ CVMX_PIP_RX_NO_ERR = 0ull, ++ /* RGM+SPI 1 = partially received packet (buffering/bandwidth ++ * not adequate) */ ++ CVMX_PIP_PARTIAL_ERR = 1ull, ++ /* RGM+SPI 2 = receive packet too large and truncated */ ++ CVMX_PIP_JABBER_ERR = 2ull, ++ /* ++ * RGM 3 = max frame error (pkt len > max frame len) (with FCS ++ * error) ++ */ ++ CVMX_PIP_OVER_FCS_ERR = 3ull, ++ /* RGM+SPI 4 = max frame error (pkt len > max frame len) */ ++ CVMX_PIP_OVER_ERR = 4ull, ++ /* ++ * RGM 5 = nibble error (data not byte multiple - 100M and 10M ++ * only) ++ */ ++ CVMX_PIP_ALIGN_ERR = 5ull, ++ /* ++ * RGM 6 = min frame error (pkt len < min frame len) (with FCS ++ * error) ++ */ ++ CVMX_PIP_UNDER_FCS_ERR = 6ull, ++ /* RGM 7 = FCS error */ ++ CVMX_PIP_GMX_FCS_ERR = 7ull, ++ /* RGM+SPI 8 = min frame error (pkt len < min frame len) */ ++ CVMX_PIP_UNDER_ERR = 8ull, ++ /* RGM 9 = Frame carrier extend error */ ++ CVMX_PIP_EXTEND_ERR = 9ull, ++ /* ++ * RGM 10 = length mismatch (len did not match len in L2 ++ * length/type) ++ */ ++ CVMX_PIP_LENGTH_ERR = 10ull, ++ /* RGM 11 = Frame error (some or all data bits marked err) */ ++ CVMX_PIP_DAT_ERR = 11ull, ++ /* SPI 11 = DIP4 error */ ++ CVMX_PIP_DIP_ERR = 11ull, ++ /* ++ * RGM 12 = packet was not large enough to pass the skipper - ++ * no inspection could occur. ++ */ ++ CVMX_PIP_SKIP_ERR = 12ull, ++ /* ++ * RGM 13 = studder error (data not repeated - 100M and 10M ++ * only) ++ */ ++ CVMX_PIP_NIBBLE_ERR = 13ull, ++ /* RGM+SPI 16 = FCS error */ ++ CVMX_PIP_PIP_FCS = 16L, ++ /* ++ * RGM+SPI+PCI 17 = packet was not large enough to pass the ++ * skipper - no inspection could occur. ++ */ ++ CVMX_PIP_PIP_SKIP_ERR = 17L, ++ /* ++ * RGM+SPI+PCI 18 = malformed l2 (packet not long enough to ++ * cover L2 hdr). ++ */ ++ CVMX_PIP_PIP_L2_MAL_HDR = 18L ++ /* ++ * NOTES: xx = late collision (data received before collision) ++ * late collisions cannot be detected by the receiver ++ * they would appear as JAM bits which would appear as ++ * bad FCS or carrier extend error which is ++ * CVMX_PIP_EXTEND_ERR ++ */ ++} cvmx_pip_rcv_err_t; ++ ++/** ++ * This defines the err_code field errors in the work Q entry ++ */ ++typedef union { ++ cvmx_pip_l4_err_t l4_err; ++ cvmx_pip_ip_exc_t ip_exc; ++ cvmx_pip_rcv_err_t rcv_err; ++} cvmx_pip_err_t; ++ ++/** ++ * Status statistics for a port ++ */ ++typedef struct { ++ /* Inbound octets marked to be dropped by the IPD */ ++ uint32_t dropped_octets; ++ /* Inbound packets marked to be dropped by the IPD */ ++ uint32_t dropped_packets; ++ /* RAW PCI Packets received by PIP per port */ ++ uint32_t pci_raw_packets; ++ /* Number of octets processed by PIP */ ++ uint32_t octets; ++ /* Number of packets processed by PIP */ ++ uint32_t packets; ++ /* ++ * Number of indentified L2 multicast packets. Does not ++ * include broadcast packets. Only includes packets whose ++ * parse mode is SKIP_TO_L2 ++ */ ++ uint32_t multicast_packets; ++ /* ++ * Number of indentified L2 broadcast packets. Does not ++ * include multicast packets. Only includes packets whose ++ * parse mode is SKIP_TO_L2 ++ */ ++ uint32_t broadcast_packets; ++ /* Number of 64B packets */ ++ uint32_t len_64_packets; ++ /* Number of 65-127B packets */ ++ uint32_t len_65_127_packets; ++ /* Number of 128-255B packets */ ++ uint32_t len_128_255_packets; ++ /* Number of 256-511B packets */ ++ uint32_t len_256_511_packets; ++ /* Number of 512-1023B packets */ ++ uint32_t len_512_1023_packets; ++ /* Number of 1024-1518B packets */ ++ uint32_t len_1024_1518_packets; ++ /* Number of 1519-max packets */ ++ uint32_t len_1519_max_packets; ++ /* Number of packets with FCS or Align opcode errors */ ++ uint32_t fcs_align_err_packets; ++ /* Number of packets with length < min */ ++ uint32_t runt_packets; ++ /* Number of packets with length < min and FCS error */ ++ uint32_t runt_crc_packets; ++ /* Number of packets with length > max */ ++ uint32_t oversize_packets; ++ /* Number of packets with length > max and FCS error */ ++ uint32_t oversize_crc_packets; ++ /* Number of packets without GMX/SPX/PCI errors received by PIP */ ++ uint32_t inb_packets; ++ /* ++ * Total number of octets from all packets received by PIP, ++ * including CRC ++ */ ++ uint64_t inb_octets; ++ /* Number of packets with GMX/SPX/PCI errors received by PIP */ ++ uint16_t inb_errors; ++} cvmx_pip_port_status_t; ++ ++/** ++ * Definition of the PIP custom header that can be prepended ++ * to a packet by external hardware. ++ */ ++typedef union { ++ uint64_t u64; ++ struct { ++ /* ++ * Documented as R - Set if the Packet is RAWFULL. If ++ * set, this header must be the full 8 bytes. ++ */ ++ uint64_t rawfull:1; ++ /* Must be zero */ ++ uint64_t reserved0:5; ++ /* PIP parse mode for this packet */ ++ uint64_t parse_mode:2; ++ /* Must be zero */ ++ uint64_t reserved1:1; ++ /* ++ * Skip amount, including this header, to the ++ * beginning of the packet ++ */ ++ uint64_t skip_len:7; ++ /* Must be zero */ ++ uint64_t reserved2:6; ++ /* POW input queue for this packet */ ++ uint64_t qos:3; ++ /* POW input group for this packet */ ++ uint64_t grp:4; ++ /* ++ * Flag to store this packet in the work queue entry, ++ * if possible ++ */ ++ uint64_t rs:1; ++ /* POW input tag type */ ++ uint64_t tag_type:2; ++ /* POW input tag */ ++ uint64_t tag:32; ++ } s; ++} cvmx_pip_pkt_inst_hdr_t; ++ ++/* CSR typedefs have been moved to cvmx-csr-*.h */ ++ ++/** ++ * Configure an ethernet input port ++ * ++ * @port_num: Port number to configure ++ * @port_cfg: Port hardware configuration ++ * @port_tag_cfg: ++ * Port POW tagging configuration ++ */ ++static inline void cvmx_pip_config_port(uint64_t port_num, ++ union cvmx_pip_prt_cfgx port_cfg, ++ union cvmx_pip_prt_tagx port_tag_cfg) ++{ ++ cvmx_write_csr(CVMX_PIP_PRT_CFGX(port_num), port_cfg.u64); ++ cvmx_write_csr(CVMX_PIP_PRT_TAGX(port_num), port_tag_cfg.u64); ++} ++#if 0 ++/** ++ * @deprecated This function is a thin wrapper around the Pass1 version ++ * of the CVMX_PIP_QOS_WATCHX CSR; Pass2 has added a field for ++ * setting the group that is incompatible with this function, ++ * the preferred upgrade path is to use the CSR directly. ++ * ++ * Configure the global QoS packet watchers. Each watcher is ++ * capable of matching a field in a packet to determine the ++ * QoS queue for scheduling. ++ * ++ * @watcher: Watcher number to configure (0 - 3). ++ * @match_type: Watcher match type ++ * @match_value: ++ * Value the watcher will match against ++ * @qos: QoS queue for packets matching this watcher ++ */ ++static inline void cvmx_pip_config_watcher(uint64_t watcher, ++ cvmx_pip_qos_watch_types match_type, ++ uint64_t match_value, uint64_t qos) ++{ ++ cvmx_pip_port_watcher_cfg_t watcher_config; ++ ++ watcher_config.u64 = 0; ++ watcher_config.s.match_type = match_type; ++ watcher_config.s.match_value = match_value; ++ watcher_config.s.qos = qos; ++ ++ cvmx_write_csr(CVMX_PIP_QOS_WATCHX(watcher), watcher_config.u64); ++} ++#endif ++/** ++ * Configure the VLAN priority to QoS queue mapping. ++ * ++ * @vlan_priority: ++ * VLAN priority (0-7) ++ * @qos: QoS queue for packets matching this watcher ++ */ ++static inline void cvmx_pip_config_vlan_qos(uint64_t vlan_priority, ++ uint64_t qos) ++{ ++ union cvmx_pip_qos_vlanx pip_qos_vlanx; ++ pip_qos_vlanx.u64 = 0; ++ pip_qos_vlanx.s.qos = qos; ++ cvmx_write_csr(CVMX_PIP_QOS_VLANX(vlan_priority), pip_qos_vlanx.u64); ++} ++ ++/** ++ * Configure the Diffserv to QoS queue mapping. ++ * ++ * @diffserv: Diffserv field value (0-63) ++ * @qos: QoS queue for packets matching this watcher ++ */ ++static inline void cvmx_pip_config_diffserv_qos(uint64_t diffserv, uint64_t qos) ++{ ++ union cvmx_pip_qos_diffx pip_qos_diffx; ++ pip_qos_diffx.u64 = 0; ++ pip_qos_diffx.s.qos = qos; ++ cvmx_write_csr(CVMX_PIP_QOS_DIFFX(diffserv), pip_qos_diffx.u64); ++} ++ ++/** ++ * Get the status counters for a port. ++ * ++ * @port_num: Port number to get statistics for. ++ * @clear: Set to 1 to clear the counters after they are read ++ * @status: Where to put the results. ++ */ ++static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear, ++ cvmx_pip_port_status_t *status) ++{ ++ union cvmx_pip_stat_ctl pip_stat_ctl; ++ union cvmx_pip_stat0_prtx stat0; ++ union cvmx_pip_stat1_prtx stat1; ++ union cvmx_pip_stat2_prtx stat2; ++ union cvmx_pip_stat3_prtx stat3; ++ union cvmx_pip_stat4_prtx stat4; ++ union cvmx_pip_stat5_prtx stat5; ++ union cvmx_pip_stat6_prtx stat6; ++ union cvmx_pip_stat7_prtx stat7; ++ union cvmx_pip_stat8_prtx stat8; ++ union cvmx_pip_stat9_prtx stat9; ++ union cvmx_pip_stat_inb_pktsx pip_stat_inb_pktsx; ++ union cvmx_pip_stat_inb_octsx pip_stat_inb_octsx; ++ union cvmx_pip_stat_inb_errsx pip_stat_inb_errsx; ++ ++ pip_stat_ctl.u64 = 0; ++ pip_stat_ctl.s.rdclr = clear; ++ cvmx_write_csr(CVMX_PIP_STAT_CTL, pip_stat_ctl.u64); ++ ++ stat0.u64 = cvmx_read_csr(CVMX_PIP_STAT0_PRTX(port_num)); ++ stat1.u64 = cvmx_read_csr(CVMX_PIP_STAT1_PRTX(port_num)); ++ stat2.u64 = cvmx_read_csr(CVMX_PIP_STAT2_PRTX(port_num)); ++ stat3.u64 = cvmx_read_csr(CVMX_PIP_STAT3_PRTX(port_num)); ++ stat4.u64 = cvmx_read_csr(CVMX_PIP_STAT4_PRTX(port_num)); ++ stat5.u64 = cvmx_read_csr(CVMX_PIP_STAT5_PRTX(port_num)); ++ stat6.u64 = cvmx_read_csr(CVMX_PIP_STAT6_PRTX(port_num)); ++ stat7.u64 = cvmx_read_csr(CVMX_PIP_STAT7_PRTX(port_num)); ++ stat8.u64 = cvmx_read_csr(CVMX_PIP_STAT8_PRTX(port_num)); ++ stat9.u64 = cvmx_read_csr(CVMX_PIP_STAT9_PRTX(port_num)); ++ pip_stat_inb_pktsx.u64 = ++ cvmx_read_csr(CVMX_PIP_STAT_INB_PKTSX(port_num)); ++ pip_stat_inb_octsx.u64 = ++ cvmx_read_csr(CVMX_PIP_STAT_INB_OCTSX(port_num)); ++ pip_stat_inb_errsx.u64 = ++ cvmx_read_csr(CVMX_PIP_STAT_INB_ERRSX(port_num)); ++ ++ status->dropped_octets = stat0.s.drp_octs; ++ status->dropped_packets = stat0.s.drp_pkts; ++ status->octets = stat1.s.octs; ++ status->pci_raw_packets = stat2.s.raw; ++ status->packets = stat2.s.pkts; ++ status->multicast_packets = stat3.s.mcst; ++ status->broadcast_packets = stat3.s.bcst; ++ status->len_64_packets = stat4.s.h64; ++ status->len_65_127_packets = stat4.s.h65to127; ++ status->len_128_255_packets = stat5.s.h128to255; ++ status->len_256_511_packets = stat5.s.h256to511; ++ status->len_512_1023_packets = stat6.s.h512to1023; ++ status->len_1024_1518_packets = stat6.s.h1024to1518; ++ status->len_1519_max_packets = stat7.s.h1519; ++ status->fcs_align_err_packets = stat7.s.fcs; ++ status->runt_packets = stat8.s.undersz; ++ status->runt_crc_packets = stat8.s.frag; ++ status->oversize_packets = stat9.s.oversz; ++ status->oversize_crc_packets = stat9.s.jabber; ++ status->inb_packets = pip_stat_inb_pktsx.s.pkts; ++ status->inb_octets = pip_stat_inb_octsx.s.octs; ++ status->inb_errors = pip_stat_inb_errsx.s.errs; ++ ++ if (cvmx_octeon_is_pass1()) { ++ /* ++ * Kludge to fix Octeon Pass 1 errata - Drop counts ++ * don't work. ++ */ ++ if (status->inb_packets > status->packets) ++ status->dropped_packets = ++ status->inb_packets - status->packets; ++ else ++ status->dropped_packets = 0; ++ if (status->inb_octets - status->inb_packets * 4 > ++ status->octets) ++ status->dropped_octets = ++ status->inb_octets - status->inb_packets * 4 - ++ status->octets; ++ else ++ status->dropped_octets = 0; ++ } ++} ++ ++/** ++ * Configure the hardware CRC engine ++ * ++ * @interface: Interface to configure (0 or 1) ++ * @invert_result: ++ * Invert the result of the CRC ++ * @reflect: Reflect ++ * @initialization_vector: ++ * CRC initialization vector ++ */ ++static inline void cvmx_pip_config_crc(uint64_t interface, ++ uint64_t invert_result, uint64_t reflect, ++ uint32_t initialization_vector) ++{ ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ union cvmx_pip_crc_ctlx config; ++ union cvmx_pip_crc_ivx pip_crc_ivx; ++ ++ config.u64 = 0; ++ config.s.invres = invert_result; ++ config.s.reflect = reflect; ++ cvmx_write_csr(CVMX_PIP_CRC_CTLX(interface), config.u64); ++ ++ pip_crc_ivx.u64 = 0; ++ pip_crc_ivx.s.iv = initialization_vector; ++ cvmx_write_csr(CVMX_PIP_CRC_IVX(interface), pip_crc_ivx.u64); ++ } ++} ++ ++/** ++ * Clear all bits in a tag mask. This should be called on ++ * startup before any calls to cvmx_pip_tag_mask_set. Each bit ++ * set in the final mask represent a byte used in the packet for ++ * tag generation. ++ * ++ * @mask_index: Which tag mask to clear (0..3) ++ */ ++static inline void cvmx_pip_tag_mask_clear(uint64_t mask_index) ++{ ++ uint64_t index; ++ union cvmx_pip_tag_incx pip_tag_incx; ++ pip_tag_incx.u64 = 0; ++ pip_tag_incx.s.en = 0; ++ for (index = mask_index * 16; index < (mask_index + 1) * 16; index++) ++ cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64); ++} ++ ++/** ++ * Sets a range of bits in the tag mask. The tag mask is used ++ * when the cvmx_pip_port_tag_cfg_t tag_mode is non zero. ++ * There are four separate masks that can be configured. ++ * ++ * @mask_index: Which tag mask to modify (0..3) ++ * @offset: Offset into the bitmask to set bits at. Use the GCC macro ++ * offsetof() to determine the offsets into packet headers. ++ * For example, offsetof(ethhdr, protocol) returns the offset ++ * of the ethernet protocol field. The bitmask selects which ++ * bytes to include the the tag, with bit offset X selecting ++ * byte at offset X from the beginning of the packet data. ++ * @len: Number of bytes to include. Usually this is the sizeof() ++ * the field. ++ */ ++static inline void cvmx_pip_tag_mask_set(uint64_t mask_index, uint64_t offset, ++ uint64_t len) ++{ ++ while (len--) { ++ union cvmx_pip_tag_incx pip_tag_incx; ++ uint64_t index = mask_index * 16 + offset / 8; ++ pip_tag_incx.u64 = cvmx_read_csr(CVMX_PIP_TAG_INCX(index)); ++ pip_tag_incx.s.en |= 0x80 >> (offset & 0x7); ++ cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64); ++ offset++; ++ } ++} ++ ++#endif /* __CVMX_PIP_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pko-defs.h +@@ -0,0 +1,1133 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_PKO_DEFS_H__ ++#define __CVMX_PKO_DEFS_H__ ++ ++#define CVMX_PKO_MEM_COUNT0 \ ++ CVMX_ADD_IO_SEG(0x0001180050001080ull) ++#define CVMX_PKO_MEM_COUNT1 \ ++ CVMX_ADD_IO_SEG(0x0001180050001088ull) ++#define CVMX_PKO_MEM_DEBUG0 \ ++ CVMX_ADD_IO_SEG(0x0001180050001100ull) ++#define CVMX_PKO_MEM_DEBUG1 \ ++ CVMX_ADD_IO_SEG(0x0001180050001108ull) ++#define CVMX_PKO_MEM_DEBUG10 \ ++ CVMX_ADD_IO_SEG(0x0001180050001150ull) ++#define CVMX_PKO_MEM_DEBUG11 \ ++ CVMX_ADD_IO_SEG(0x0001180050001158ull) ++#define CVMX_PKO_MEM_DEBUG12 \ ++ CVMX_ADD_IO_SEG(0x0001180050001160ull) ++#define CVMX_PKO_MEM_DEBUG13 \ ++ CVMX_ADD_IO_SEG(0x0001180050001168ull) ++#define CVMX_PKO_MEM_DEBUG14 \ ++ CVMX_ADD_IO_SEG(0x0001180050001170ull) ++#define CVMX_PKO_MEM_DEBUG2 \ ++ CVMX_ADD_IO_SEG(0x0001180050001110ull) ++#define CVMX_PKO_MEM_DEBUG3 \ ++ CVMX_ADD_IO_SEG(0x0001180050001118ull) ++#define CVMX_PKO_MEM_DEBUG4 \ ++ CVMX_ADD_IO_SEG(0x0001180050001120ull) ++#define CVMX_PKO_MEM_DEBUG5 \ ++ CVMX_ADD_IO_SEG(0x0001180050001128ull) ++#define CVMX_PKO_MEM_DEBUG6 \ ++ CVMX_ADD_IO_SEG(0x0001180050001130ull) ++#define CVMX_PKO_MEM_DEBUG7 \ ++ CVMX_ADD_IO_SEG(0x0001180050001138ull) ++#define CVMX_PKO_MEM_DEBUG8 \ ++ CVMX_ADD_IO_SEG(0x0001180050001140ull) ++#define CVMX_PKO_MEM_DEBUG9 \ ++ CVMX_ADD_IO_SEG(0x0001180050001148ull) ++#define CVMX_PKO_MEM_PORT_PTRS \ ++ CVMX_ADD_IO_SEG(0x0001180050001010ull) ++#define CVMX_PKO_MEM_PORT_QOS \ ++ CVMX_ADD_IO_SEG(0x0001180050001018ull) ++#define CVMX_PKO_MEM_PORT_RATE0 \ ++ CVMX_ADD_IO_SEG(0x0001180050001020ull) ++#define CVMX_PKO_MEM_PORT_RATE1 \ ++ CVMX_ADD_IO_SEG(0x0001180050001028ull) ++#define CVMX_PKO_MEM_QUEUE_PTRS \ ++ CVMX_ADD_IO_SEG(0x0001180050001000ull) ++#define CVMX_PKO_MEM_QUEUE_QOS \ ++ CVMX_ADD_IO_SEG(0x0001180050001008ull) ++#define CVMX_PKO_REG_BIST_RESULT \ ++ CVMX_ADD_IO_SEG(0x0001180050000080ull) ++#define CVMX_PKO_REG_CMD_BUF \ ++ CVMX_ADD_IO_SEG(0x0001180050000010ull) ++#define CVMX_PKO_REG_CRC_CTLX(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180050000028ull + (((offset) & 1) * 8)) ++#define CVMX_PKO_REG_CRC_ENABLE \ ++ CVMX_ADD_IO_SEG(0x0001180050000020ull) ++#define CVMX_PKO_REG_CRC_IVX(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180050000038ull + (((offset) & 1) * 8)) ++#define CVMX_PKO_REG_DEBUG0 \ ++ CVMX_ADD_IO_SEG(0x0001180050000098ull) ++#define CVMX_PKO_REG_DEBUG1 \ ++ CVMX_ADD_IO_SEG(0x00011800500000A0ull) ++#define CVMX_PKO_REG_DEBUG2 \ ++ CVMX_ADD_IO_SEG(0x00011800500000A8ull) ++#define CVMX_PKO_REG_DEBUG3 \ ++ CVMX_ADD_IO_SEG(0x00011800500000B0ull) ++#define CVMX_PKO_REG_ENGINE_INFLIGHT \ ++ CVMX_ADD_IO_SEG(0x0001180050000050ull) ++#define CVMX_PKO_REG_ENGINE_THRESH \ ++ CVMX_ADD_IO_SEG(0x0001180050000058ull) ++#define CVMX_PKO_REG_ERROR \ ++ CVMX_ADD_IO_SEG(0x0001180050000088ull) ++#define CVMX_PKO_REG_FLAGS \ ++ CVMX_ADD_IO_SEG(0x0001180050000000ull) ++#define CVMX_PKO_REG_GMX_PORT_MODE \ ++ CVMX_ADD_IO_SEG(0x0001180050000018ull) ++#define CVMX_PKO_REG_INT_MASK \ ++ CVMX_ADD_IO_SEG(0x0001180050000090ull) ++#define CVMX_PKO_REG_QUEUE_MODE \ ++ CVMX_ADD_IO_SEG(0x0001180050000048ull) ++#define CVMX_PKO_REG_QUEUE_PTRS1 \ ++ CVMX_ADD_IO_SEG(0x0001180050000100ull) ++#define CVMX_PKO_REG_READ_IDX \ ++ CVMX_ADD_IO_SEG(0x0001180050000008ull) ++ ++union cvmx_pko_mem_count0 { ++ uint64_t u64; ++ struct cvmx_pko_mem_count0_s { ++ uint64_t reserved_32_63:32; ++ uint64_t count:32; ++ } s; ++ struct cvmx_pko_mem_count0_s cn30xx; ++ struct cvmx_pko_mem_count0_s cn31xx; ++ struct cvmx_pko_mem_count0_s cn38xx; ++ struct cvmx_pko_mem_count0_s cn38xxp2; ++ struct cvmx_pko_mem_count0_s cn50xx; ++ struct cvmx_pko_mem_count0_s cn52xx; ++ struct cvmx_pko_mem_count0_s cn52xxp1; ++ struct cvmx_pko_mem_count0_s cn56xx; ++ struct cvmx_pko_mem_count0_s cn56xxp1; ++ struct cvmx_pko_mem_count0_s cn58xx; ++ struct cvmx_pko_mem_count0_s cn58xxp1; ++}; ++ ++union cvmx_pko_mem_count1 { ++ uint64_t u64; ++ struct cvmx_pko_mem_count1_s { ++ uint64_t reserved_48_63:16; ++ uint64_t count:48; ++ } s; ++ struct cvmx_pko_mem_count1_s cn30xx; ++ struct cvmx_pko_mem_count1_s cn31xx; ++ struct cvmx_pko_mem_count1_s cn38xx; ++ struct cvmx_pko_mem_count1_s cn38xxp2; ++ struct cvmx_pko_mem_count1_s cn50xx; ++ struct cvmx_pko_mem_count1_s cn52xx; ++ struct cvmx_pko_mem_count1_s cn52xxp1; ++ struct cvmx_pko_mem_count1_s cn56xx; ++ struct cvmx_pko_mem_count1_s cn56xxp1; ++ struct cvmx_pko_mem_count1_s cn58xx; ++ struct cvmx_pko_mem_count1_s cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug0 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug0_s { ++ uint64_t fau:28; ++ uint64_t cmd:14; ++ uint64_t segs:6; ++ uint64_t size:16; ++ } s; ++ struct cvmx_pko_mem_debug0_s cn30xx; ++ struct cvmx_pko_mem_debug0_s cn31xx; ++ struct cvmx_pko_mem_debug0_s cn38xx; ++ struct cvmx_pko_mem_debug0_s cn38xxp2; ++ struct cvmx_pko_mem_debug0_s cn50xx; ++ struct cvmx_pko_mem_debug0_s cn52xx; ++ struct cvmx_pko_mem_debug0_s cn52xxp1; ++ struct cvmx_pko_mem_debug0_s cn56xx; ++ struct cvmx_pko_mem_debug0_s cn56xxp1; ++ struct cvmx_pko_mem_debug0_s cn58xx; ++ struct cvmx_pko_mem_debug0_s cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug1 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug1_s { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t size:16; ++ uint64_t ptr:40; ++ } s; ++ struct cvmx_pko_mem_debug1_s cn30xx; ++ struct cvmx_pko_mem_debug1_s cn31xx; ++ struct cvmx_pko_mem_debug1_s cn38xx; ++ struct cvmx_pko_mem_debug1_s cn38xxp2; ++ struct cvmx_pko_mem_debug1_s cn50xx; ++ struct cvmx_pko_mem_debug1_s cn52xx; ++ struct cvmx_pko_mem_debug1_s cn52xxp1; ++ struct cvmx_pko_mem_debug1_s cn56xx; ++ struct cvmx_pko_mem_debug1_s cn56xxp1; ++ struct cvmx_pko_mem_debug1_s cn58xx; ++ struct cvmx_pko_mem_debug1_s cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug10 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug10_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_mem_debug10_cn30xx { ++ uint64_t fau:28; ++ uint64_t cmd:14; ++ uint64_t segs:6; ++ uint64_t size:16; ++ } cn30xx; ++ struct cvmx_pko_mem_debug10_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug10_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug10_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug10_cn50xx { ++ uint64_t reserved_49_63:15; ++ uint64_t ptrs1:17; ++ uint64_t reserved_17_31:15; ++ uint64_t ptrs2:17; ++ } cn50xx; ++ struct cvmx_pko_mem_debug10_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug10_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug10_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug10_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug10_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug10_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug11 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug11_s { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t size:16; ++ uint64_t reserved_0_39:40; ++ } s; ++ struct cvmx_pko_mem_debug11_cn30xx { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t size:16; ++ uint64_t ptr:40; ++ } cn30xx; ++ struct cvmx_pko_mem_debug11_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug11_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug11_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug11_cn50xx { ++ uint64_t reserved_23_63:41; ++ uint64_t maj:1; ++ uint64_t uid:3; ++ uint64_t sop:1; ++ uint64_t len:1; ++ uint64_t chk:1; ++ uint64_t cnt:13; ++ uint64_t mod:3; ++ } cn50xx; ++ struct cvmx_pko_mem_debug11_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug11_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug11_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug11_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug11_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug11_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug12 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug12_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_mem_debug12_cn30xx { ++ uint64_t data:64; ++ } cn30xx; ++ struct cvmx_pko_mem_debug12_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug12_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug12_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug12_cn50xx { ++ uint64_t fau:28; ++ uint64_t cmd:14; ++ uint64_t segs:6; ++ uint64_t size:16; ++ } cn50xx; ++ struct cvmx_pko_mem_debug12_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug12_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug12_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug12_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug12_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug12_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug13 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug13_s { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t reserved_0_55:56; ++ } s; ++ struct cvmx_pko_mem_debug13_cn30xx { ++ uint64_t reserved_51_63:13; ++ uint64_t widx:17; ++ uint64_t ridx2:17; ++ uint64_t widx2:17; ++ } cn30xx; ++ struct cvmx_pko_mem_debug13_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug13_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug13_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug13_cn50xx { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t size:16; ++ uint64_t ptr:40; ++ } cn50xx; ++ struct cvmx_pko_mem_debug13_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug13_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug13_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug13_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug13_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug13_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug14 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug14_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_mem_debug14_cn30xx { ++ uint64_t reserved_17_63:47; ++ uint64_t ridx:17; ++ } cn30xx; ++ struct cvmx_pko_mem_debug14_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug14_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug14_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug14_cn52xx { ++ uint64_t data:64; ++ } cn52xx; ++ struct cvmx_pko_mem_debug14_cn52xx cn52xxp1; ++ struct cvmx_pko_mem_debug14_cn52xx cn56xx; ++ struct cvmx_pko_mem_debug14_cn52xx cn56xxp1; ++}; ++ ++union cvmx_pko_mem_debug2 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug2_s { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t size:16; ++ uint64_t ptr:40; ++ } s; ++ struct cvmx_pko_mem_debug2_s cn30xx; ++ struct cvmx_pko_mem_debug2_s cn31xx; ++ struct cvmx_pko_mem_debug2_s cn38xx; ++ struct cvmx_pko_mem_debug2_s cn38xxp2; ++ struct cvmx_pko_mem_debug2_s cn50xx; ++ struct cvmx_pko_mem_debug2_s cn52xx; ++ struct cvmx_pko_mem_debug2_s cn52xxp1; ++ struct cvmx_pko_mem_debug2_s cn56xx; ++ struct cvmx_pko_mem_debug2_s cn56xxp1; ++ struct cvmx_pko_mem_debug2_s cn58xx; ++ struct cvmx_pko_mem_debug2_s cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug3 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug3_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_mem_debug3_cn30xx { ++ uint64_t i:1; ++ uint64_t back:4; ++ uint64_t pool:3; ++ uint64_t size:16; ++ uint64_t ptr:40; ++ } cn30xx; ++ struct cvmx_pko_mem_debug3_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug3_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug3_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug3_cn50xx { ++ uint64_t data:64; ++ } cn50xx; ++ struct cvmx_pko_mem_debug3_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug3_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug3_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug3_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug3_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug3_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug4 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug4_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_mem_debug4_cn30xx { ++ uint64_t data:64; ++ } cn30xx; ++ struct cvmx_pko_mem_debug4_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug4_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug4_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug4_cn50xx { ++ uint64_t cmnd_segs:3; ++ uint64_t cmnd_siz:16; ++ uint64_t cmnd_off:6; ++ uint64_t uid:3; ++ uint64_t dread_sop:1; ++ uint64_t init_dwrite:1; ++ uint64_t chk_once:1; ++ uint64_t chk_mode:1; ++ uint64_t active:1; ++ uint64_t static_p:1; ++ uint64_t qos:3; ++ uint64_t qcb_ridx:5; ++ uint64_t qid_off_max:4; ++ uint64_t qid_off:4; ++ uint64_t qid_base:8; ++ uint64_t wait:1; ++ uint64_t minor:2; ++ uint64_t major:3; ++ } cn50xx; ++ struct cvmx_pko_mem_debug4_cn52xx { ++ uint64_t curr_siz:8; ++ uint64_t curr_off:16; ++ uint64_t cmnd_segs:6; ++ uint64_t cmnd_siz:16; ++ uint64_t cmnd_off:6; ++ uint64_t uid:2; ++ uint64_t dread_sop:1; ++ uint64_t init_dwrite:1; ++ uint64_t chk_once:1; ++ uint64_t chk_mode:1; ++ uint64_t wait:1; ++ uint64_t minor:2; ++ uint64_t major:3; ++ } cn52xx; ++ struct cvmx_pko_mem_debug4_cn52xx cn52xxp1; ++ struct cvmx_pko_mem_debug4_cn52xx cn56xx; ++ struct cvmx_pko_mem_debug4_cn52xx cn56xxp1; ++ struct cvmx_pko_mem_debug4_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug4_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug5 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug5_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_mem_debug5_cn30xx { ++ uint64_t dwri_mod:1; ++ uint64_t dwri_sop:1; ++ uint64_t dwri_len:1; ++ uint64_t dwri_cnt:13; ++ uint64_t cmnd_siz:16; ++ uint64_t uid:1; ++ uint64_t xfer_wor:1; ++ uint64_t xfer_dwr:1; ++ uint64_t cbuf_fre:1; ++ uint64_t reserved_27_27:1; ++ uint64_t chk_mode:1; ++ uint64_t active:1; ++ uint64_t qos:3; ++ uint64_t qcb_ridx:5; ++ uint64_t qid_off:3; ++ uint64_t qid_base:7; ++ uint64_t wait:1; ++ uint64_t minor:2; ++ uint64_t major:4; ++ } cn30xx; ++ struct cvmx_pko_mem_debug5_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug5_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug5_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug5_cn50xx { ++ uint64_t curr_ptr:29; ++ uint64_t curr_siz:16; ++ uint64_t curr_off:16; ++ uint64_t cmnd_segs:3; ++ } cn50xx; ++ struct cvmx_pko_mem_debug5_cn52xx { ++ uint64_t reserved_54_63:10; ++ uint64_t nxt_inflt:6; ++ uint64_t curr_ptr:40; ++ uint64_t curr_siz:8; ++ } cn52xx; ++ struct cvmx_pko_mem_debug5_cn52xx cn52xxp1; ++ struct cvmx_pko_mem_debug5_cn52xx cn56xx; ++ struct cvmx_pko_mem_debug5_cn52xx cn56xxp1; ++ struct cvmx_pko_mem_debug5_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug5_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug6 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug6_s { ++ uint64_t reserved_37_63:27; ++ uint64_t qid_offres:4; ++ uint64_t qid_offths:4; ++ uint64_t preempter:1; ++ uint64_t preemptee:1; ++ uint64_t preempted:1; ++ uint64_t active:1; ++ uint64_t statc:1; ++ uint64_t qos:3; ++ uint64_t qcb_ridx:5; ++ uint64_t qid_offmax:4; ++ uint64_t reserved_0_11:12; ++ } s; ++ struct cvmx_pko_mem_debug6_cn30xx { ++ uint64_t reserved_11_63:53; ++ uint64_t qid_offm:3; ++ uint64_t static_p:1; ++ uint64_t work_min:3; ++ uint64_t dwri_chk:1; ++ uint64_t dwri_uid:1; ++ uint64_t dwri_mod:2; ++ } cn30xx; ++ struct cvmx_pko_mem_debug6_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug6_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug6_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug6_cn50xx { ++ uint64_t reserved_11_63:53; ++ uint64_t curr_ptr:11; ++ } cn50xx; ++ struct cvmx_pko_mem_debug6_cn52xx { ++ uint64_t reserved_37_63:27; ++ uint64_t qid_offres:4; ++ uint64_t qid_offths:4; ++ uint64_t preempter:1; ++ uint64_t preemptee:1; ++ uint64_t preempted:1; ++ uint64_t active:1; ++ uint64_t statc:1; ++ uint64_t qos:3; ++ uint64_t qcb_ridx:5; ++ uint64_t qid_offmax:4; ++ uint64_t qid_off:4; ++ uint64_t qid_base:8; ++ } cn52xx; ++ struct cvmx_pko_mem_debug6_cn52xx cn52xxp1; ++ struct cvmx_pko_mem_debug6_cn52xx cn56xx; ++ struct cvmx_pko_mem_debug6_cn52xx cn56xxp1; ++ struct cvmx_pko_mem_debug6_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug6_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug7 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug7_s { ++ uint64_t qos:5; ++ uint64_t tail:1; ++ uint64_t reserved_0_57:58; ++ } s; ++ struct cvmx_pko_mem_debug7_cn30xx { ++ uint64_t reserved_58_63:6; ++ uint64_t dwb:9; ++ uint64_t start:33; ++ uint64_t size:16; ++ } cn30xx; ++ struct cvmx_pko_mem_debug7_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug7_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug7_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug7_cn50xx { ++ uint64_t qos:5; ++ uint64_t tail:1; ++ uint64_t buf_siz:13; ++ uint64_t buf_ptr:33; ++ uint64_t qcb_widx:6; ++ uint64_t qcb_ridx:6; ++ } cn50xx; ++ struct cvmx_pko_mem_debug7_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug7_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug7_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug7_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug7_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug7_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug8 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug8_s { ++ uint64_t reserved_59_63:5; ++ uint64_t tail:1; ++ uint64_t buf_siz:13; ++ uint64_t reserved_0_44:45; ++ } s; ++ struct cvmx_pko_mem_debug8_cn30xx { ++ uint64_t qos:5; ++ uint64_t tail:1; ++ uint64_t buf_siz:13; ++ uint64_t buf_ptr:33; ++ uint64_t qcb_widx:6; ++ uint64_t qcb_ridx:6; ++ } cn30xx; ++ struct cvmx_pko_mem_debug8_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug8_cn30xx cn38xx; ++ struct cvmx_pko_mem_debug8_cn30xx cn38xxp2; ++ struct cvmx_pko_mem_debug8_cn50xx { ++ uint64_t reserved_28_63:36; ++ uint64_t doorbell:20; ++ uint64_t reserved_6_7:2; ++ uint64_t static_p:1; ++ uint64_t s_tail:1; ++ uint64_t static_q:1; ++ uint64_t qos:3; ++ } cn50xx; ++ struct cvmx_pko_mem_debug8_cn52xx { ++ uint64_t reserved_29_63:35; ++ uint64_t preempter:1; ++ uint64_t doorbell:20; ++ uint64_t reserved_7_7:1; ++ uint64_t preemptee:1; ++ uint64_t static_p:1; ++ uint64_t s_tail:1; ++ uint64_t static_q:1; ++ uint64_t qos:3; ++ } cn52xx; ++ struct cvmx_pko_mem_debug8_cn52xx cn52xxp1; ++ struct cvmx_pko_mem_debug8_cn52xx cn56xx; ++ struct cvmx_pko_mem_debug8_cn52xx cn56xxp1; ++ struct cvmx_pko_mem_debug8_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug8_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_debug9 { ++ uint64_t u64; ++ struct cvmx_pko_mem_debug9_s { ++ uint64_t reserved_49_63:15; ++ uint64_t ptrs0:17; ++ uint64_t reserved_0_31:32; ++ } s; ++ struct cvmx_pko_mem_debug9_cn30xx { ++ uint64_t reserved_28_63:36; ++ uint64_t doorbell:20; ++ uint64_t reserved_5_7:3; ++ uint64_t s_tail:1; ++ uint64_t static_q:1; ++ uint64_t qos:3; ++ } cn30xx; ++ struct cvmx_pko_mem_debug9_cn30xx cn31xx; ++ struct cvmx_pko_mem_debug9_cn38xx { ++ uint64_t reserved_28_63:36; ++ uint64_t doorbell:20; ++ uint64_t reserved_6_7:2; ++ uint64_t static_p:1; ++ uint64_t s_tail:1; ++ uint64_t static_q:1; ++ uint64_t qos:3; ++ } cn38xx; ++ struct cvmx_pko_mem_debug9_cn38xx cn38xxp2; ++ struct cvmx_pko_mem_debug9_cn50xx { ++ uint64_t reserved_49_63:15; ++ uint64_t ptrs0:17; ++ uint64_t reserved_17_31:15; ++ uint64_t ptrs3:17; ++ } cn50xx; ++ struct cvmx_pko_mem_debug9_cn50xx cn52xx; ++ struct cvmx_pko_mem_debug9_cn50xx cn52xxp1; ++ struct cvmx_pko_mem_debug9_cn50xx cn56xx; ++ struct cvmx_pko_mem_debug9_cn50xx cn56xxp1; ++ struct cvmx_pko_mem_debug9_cn50xx cn58xx; ++ struct cvmx_pko_mem_debug9_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_mem_port_ptrs { ++ uint64_t u64; ++ struct cvmx_pko_mem_port_ptrs_s { ++ uint64_t reserved_62_63:2; ++ uint64_t static_p:1; ++ uint64_t qos_mask:8; ++ uint64_t reserved_16_52:37; ++ uint64_t bp_port:6; ++ uint64_t eid:4; ++ uint64_t pid:6; ++ } s; ++ struct cvmx_pko_mem_port_ptrs_s cn52xx; ++ struct cvmx_pko_mem_port_ptrs_s cn52xxp1; ++ struct cvmx_pko_mem_port_ptrs_s cn56xx; ++ struct cvmx_pko_mem_port_ptrs_s cn56xxp1; ++}; ++ ++union cvmx_pko_mem_port_qos { ++ uint64_t u64; ++ struct cvmx_pko_mem_port_qos_s { ++ uint64_t reserved_61_63:3; ++ uint64_t qos_mask:8; ++ uint64_t reserved_10_52:43; ++ uint64_t eid:4; ++ uint64_t pid:6; ++ } s; ++ struct cvmx_pko_mem_port_qos_s cn52xx; ++ struct cvmx_pko_mem_port_qos_s cn52xxp1; ++ struct cvmx_pko_mem_port_qos_s cn56xx; ++ struct cvmx_pko_mem_port_qos_s cn56xxp1; ++}; ++ ++union cvmx_pko_mem_port_rate0 { ++ uint64_t u64; ++ struct cvmx_pko_mem_port_rate0_s { ++ uint64_t reserved_51_63:13; ++ uint64_t rate_word:19; ++ uint64_t rate_pkt:24; ++ uint64_t reserved_6_7:2; ++ uint64_t pid:6; ++ } s; ++ struct cvmx_pko_mem_port_rate0_s cn52xx; ++ struct cvmx_pko_mem_port_rate0_s cn52xxp1; ++ struct cvmx_pko_mem_port_rate0_s cn56xx; ++ struct cvmx_pko_mem_port_rate0_s cn56xxp1; ++}; ++ ++union cvmx_pko_mem_port_rate1 { ++ uint64_t u64; ++ struct cvmx_pko_mem_port_rate1_s { ++ uint64_t reserved_32_63:32; ++ uint64_t rate_lim:24; ++ uint64_t reserved_6_7:2; ++ uint64_t pid:6; ++ } s; ++ struct cvmx_pko_mem_port_rate1_s cn52xx; ++ struct cvmx_pko_mem_port_rate1_s cn52xxp1; ++ struct cvmx_pko_mem_port_rate1_s cn56xx; ++ struct cvmx_pko_mem_port_rate1_s cn56xxp1; ++}; ++ ++union cvmx_pko_mem_queue_ptrs { ++ uint64_t u64; ++ struct cvmx_pko_mem_queue_ptrs_s { ++ uint64_t s_tail:1; ++ uint64_t static_p:1; ++ uint64_t static_q:1; ++ uint64_t qos_mask:8; ++ uint64_t buf_ptr:36; ++ uint64_t tail:1; ++ uint64_t index:3; ++ uint64_t port:6; ++ uint64_t queue:7; ++ } s; ++ struct cvmx_pko_mem_queue_ptrs_s cn30xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn31xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn38xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn38xxp2; ++ struct cvmx_pko_mem_queue_ptrs_s cn50xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn52xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn52xxp1; ++ struct cvmx_pko_mem_queue_ptrs_s cn56xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn56xxp1; ++ struct cvmx_pko_mem_queue_ptrs_s cn58xx; ++ struct cvmx_pko_mem_queue_ptrs_s cn58xxp1; ++}; ++ ++union cvmx_pko_mem_queue_qos { ++ uint64_t u64; ++ struct cvmx_pko_mem_queue_qos_s { ++ uint64_t reserved_61_63:3; ++ uint64_t qos_mask:8; ++ uint64_t reserved_13_52:40; ++ uint64_t pid:6; ++ uint64_t qid:7; ++ } s; ++ struct cvmx_pko_mem_queue_qos_s cn30xx; ++ struct cvmx_pko_mem_queue_qos_s cn31xx; ++ struct cvmx_pko_mem_queue_qos_s cn38xx; ++ struct cvmx_pko_mem_queue_qos_s cn38xxp2; ++ struct cvmx_pko_mem_queue_qos_s cn50xx; ++ struct cvmx_pko_mem_queue_qos_s cn52xx; ++ struct cvmx_pko_mem_queue_qos_s cn52xxp1; ++ struct cvmx_pko_mem_queue_qos_s cn56xx; ++ struct cvmx_pko_mem_queue_qos_s cn56xxp1; ++ struct cvmx_pko_mem_queue_qos_s cn58xx; ++ struct cvmx_pko_mem_queue_qos_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_bist_result { ++ uint64_t u64; ++ struct cvmx_pko_reg_bist_result_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_pko_reg_bist_result_cn30xx { ++ uint64_t reserved_27_63:37; ++ uint64_t psb2:5; ++ uint64_t count:1; ++ uint64_t rif:1; ++ uint64_t wif:1; ++ uint64_t ncb:1; ++ uint64_t out:1; ++ uint64_t crc:1; ++ uint64_t chk:1; ++ uint64_t qsb:2; ++ uint64_t qcb:2; ++ uint64_t pdb:4; ++ uint64_t psb:7; ++ } cn30xx; ++ struct cvmx_pko_reg_bist_result_cn30xx cn31xx; ++ struct cvmx_pko_reg_bist_result_cn30xx cn38xx; ++ struct cvmx_pko_reg_bist_result_cn30xx cn38xxp2; ++ struct cvmx_pko_reg_bist_result_cn50xx { ++ uint64_t reserved_33_63:31; ++ uint64_t csr:1; ++ uint64_t iob:1; ++ uint64_t out_crc:1; ++ uint64_t out_ctl:3; ++ uint64_t out_sta:1; ++ uint64_t out_wif:1; ++ uint64_t prt_chk:3; ++ uint64_t prt_nxt:1; ++ uint64_t prt_psb:6; ++ uint64_t ncb_inb:2; ++ uint64_t prt_qcb:2; ++ uint64_t prt_qsb:3; ++ uint64_t dat_dat:4; ++ uint64_t dat_ptr:4; ++ } cn50xx; ++ struct cvmx_pko_reg_bist_result_cn52xx { ++ uint64_t reserved_35_63:29; ++ uint64_t csr:1; ++ uint64_t iob:1; ++ uint64_t out_dat:1; ++ uint64_t out_ctl:3; ++ uint64_t out_sta:1; ++ uint64_t out_wif:1; ++ uint64_t prt_chk:3; ++ uint64_t prt_nxt:1; ++ uint64_t prt_psb:8; ++ uint64_t ncb_inb:2; ++ uint64_t prt_qcb:2; ++ uint64_t prt_qsb:3; ++ uint64_t prt_ctl:2; ++ uint64_t dat_dat:2; ++ uint64_t dat_ptr:4; ++ } cn52xx; ++ struct cvmx_pko_reg_bist_result_cn52xx cn52xxp1; ++ struct cvmx_pko_reg_bist_result_cn52xx cn56xx; ++ struct cvmx_pko_reg_bist_result_cn52xx cn56xxp1; ++ struct cvmx_pko_reg_bist_result_cn50xx cn58xx; ++ struct cvmx_pko_reg_bist_result_cn50xx cn58xxp1; ++}; ++ ++union cvmx_pko_reg_cmd_buf { ++ uint64_t u64; ++ struct cvmx_pko_reg_cmd_buf_s { ++ uint64_t reserved_23_63:41; ++ uint64_t pool:3; ++ uint64_t reserved_13_19:7; ++ uint64_t size:13; ++ } s; ++ struct cvmx_pko_reg_cmd_buf_s cn30xx; ++ struct cvmx_pko_reg_cmd_buf_s cn31xx; ++ struct cvmx_pko_reg_cmd_buf_s cn38xx; ++ struct cvmx_pko_reg_cmd_buf_s cn38xxp2; ++ struct cvmx_pko_reg_cmd_buf_s cn50xx; ++ struct cvmx_pko_reg_cmd_buf_s cn52xx; ++ struct cvmx_pko_reg_cmd_buf_s cn52xxp1; ++ struct cvmx_pko_reg_cmd_buf_s cn56xx; ++ struct cvmx_pko_reg_cmd_buf_s cn56xxp1; ++ struct cvmx_pko_reg_cmd_buf_s cn58xx; ++ struct cvmx_pko_reg_cmd_buf_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_crc_ctlx { ++ uint64_t u64; ++ struct cvmx_pko_reg_crc_ctlx_s { ++ uint64_t reserved_2_63:62; ++ uint64_t invres:1; ++ uint64_t refin:1; ++ } s; ++ struct cvmx_pko_reg_crc_ctlx_s cn38xx; ++ struct cvmx_pko_reg_crc_ctlx_s cn38xxp2; ++ struct cvmx_pko_reg_crc_ctlx_s cn58xx; ++ struct cvmx_pko_reg_crc_ctlx_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_crc_enable { ++ uint64_t u64; ++ struct cvmx_pko_reg_crc_enable_s { ++ uint64_t reserved_32_63:32; ++ uint64_t enable:32; ++ } s; ++ struct cvmx_pko_reg_crc_enable_s cn38xx; ++ struct cvmx_pko_reg_crc_enable_s cn38xxp2; ++ struct cvmx_pko_reg_crc_enable_s cn58xx; ++ struct cvmx_pko_reg_crc_enable_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_crc_ivx { ++ uint64_t u64; ++ struct cvmx_pko_reg_crc_ivx_s { ++ uint64_t reserved_32_63:32; ++ uint64_t iv:32; ++ } s; ++ struct cvmx_pko_reg_crc_ivx_s cn38xx; ++ struct cvmx_pko_reg_crc_ivx_s cn38xxp2; ++ struct cvmx_pko_reg_crc_ivx_s cn58xx; ++ struct cvmx_pko_reg_crc_ivx_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_debug0 { ++ uint64_t u64; ++ struct cvmx_pko_reg_debug0_s { ++ uint64_t asserts:64; ++ } s; ++ struct cvmx_pko_reg_debug0_cn30xx { ++ uint64_t reserved_17_63:47; ++ uint64_t asserts:17; ++ } cn30xx; ++ struct cvmx_pko_reg_debug0_cn30xx cn31xx; ++ struct cvmx_pko_reg_debug0_cn30xx cn38xx; ++ struct cvmx_pko_reg_debug0_cn30xx cn38xxp2; ++ struct cvmx_pko_reg_debug0_s cn50xx; ++ struct cvmx_pko_reg_debug0_s cn52xx; ++ struct cvmx_pko_reg_debug0_s cn52xxp1; ++ struct cvmx_pko_reg_debug0_s cn56xx; ++ struct cvmx_pko_reg_debug0_s cn56xxp1; ++ struct cvmx_pko_reg_debug0_s cn58xx; ++ struct cvmx_pko_reg_debug0_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_debug1 { ++ uint64_t u64; ++ struct cvmx_pko_reg_debug1_s { ++ uint64_t asserts:64; ++ } s; ++ struct cvmx_pko_reg_debug1_s cn50xx; ++ struct cvmx_pko_reg_debug1_s cn52xx; ++ struct cvmx_pko_reg_debug1_s cn52xxp1; ++ struct cvmx_pko_reg_debug1_s cn56xx; ++ struct cvmx_pko_reg_debug1_s cn56xxp1; ++ struct cvmx_pko_reg_debug1_s cn58xx; ++ struct cvmx_pko_reg_debug1_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_debug2 { ++ uint64_t u64; ++ struct cvmx_pko_reg_debug2_s { ++ uint64_t asserts:64; ++ } s; ++ struct cvmx_pko_reg_debug2_s cn50xx; ++ struct cvmx_pko_reg_debug2_s cn52xx; ++ struct cvmx_pko_reg_debug2_s cn52xxp1; ++ struct cvmx_pko_reg_debug2_s cn56xx; ++ struct cvmx_pko_reg_debug2_s cn56xxp1; ++ struct cvmx_pko_reg_debug2_s cn58xx; ++ struct cvmx_pko_reg_debug2_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_debug3 { ++ uint64_t u64; ++ struct cvmx_pko_reg_debug3_s { ++ uint64_t asserts:64; ++ } s; ++ struct cvmx_pko_reg_debug3_s cn50xx; ++ struct cvmx_pko_reg_debug3_s cn52xx; ++ struct cvmx_pko_reg_debug3_s cn52xxp1; ++ struct cvmx_pko_reg_debug3_s cn56xx; ++ struct cvmx_pko_reg_debug3_s cn56xxp1; ++ struct cvmx_pko_reg_debug3_s cn58xx; ++ struct cvmx_pko_reg_debug3_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_engine_inflight { ++ uint64_t u64; ++ struct cvmx_pko_reg_engine_inflight_s { ++ uint64_t reserved_40_63:24; ++ uint64_t engine9:4; ++ uint64_t engine8:4; ++ uint64_t engine7:4; ++ uint64_t engine6:4; ++ uint64_t engine5:4; ++ uint64_t engine4:4; ++ uint64_t engine3:4; ++ uint64_t engine2:4; ++ uint64_t engine1:4; ++ uint64_t engine0:4; ++ } s; ++ struct cvmx_pko_reg_engine_inflight_s cn52xx; ++ struct cvmx_pko_reg_engine_inflight_s cn52xxp1; ++ struct cvmx_pko_reg_engine_inflight_s cn56xx; ++ struct cvmx_pko_reg_engine_inflight_s cn56xxp1; ++}; ++ ++union cvmx_pko_reg_engine_thresh { ++ uint64_t u64; ++ struct cvmx_pko_reg_engine_thresh_s { ++ uint64_t reserved_10_63:54; ++ uint64_t mask:10; ++ } s; ++ struct cvmx_pko_reg_engine_thresh_s cn52xx; ++ struct cvmx_pko_reg_engine_thresh_s cn52xxp1; ++ struct cvmx_pko_reg_engine_thresh_s cn56xx; ++ struct cvmx_pko_reg_engine_thresh_s cn56xxp1; ++}; ++ ++union cvmx_pko_reg_error { ++ uint64_t u64; ++ struct cvmx_pko_reg_error_s { ++ uint64_t reserved_3_63:61; ++ uint64_t currzero:1; ++ uint64_t doorbell:1; ++ uint64_t parity:1; ++ } s; ++ struct cvmx_pko_reg_error_cn30xx { ++ uint64_t reserved_2_63:62; ++ uint64_t doorbell:1; ++ uint64_t parity:1; ++ } cn30xx; ++ struct cvmx_pko_reg_error_cn30xx cn31xx; ++ struct cvmx_pko_reg_error_cn30xx cn38xx; ++ struct cvmx_pko_reg_error_cn30xx cn38xxp2; ++ struct cvmx_pko_reg_error_s cn50xx; ++ struct cvmx_pko_reg_error_s cn52xx; ++ struct cvmx_pko_reg_error_s cn52xxp1; ++ struct cvmx_pko_reg_error_s cn56xx; ++ struct cvmx_pko_reg_error_s cn56xxp1; ++ struct cvmx_pko_reg_error_s cn58xx; ++ struct cvmx_pko_reg_error_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_flags { ++ uint64_t u64; ++ struct cvmx_pko_reg_flags_s { ++ uint64_t reserved_4_63:60; ++ uint64_t reset:1; ++ uint64_t store_be:1; ++ uint64_t ena_dwb:1; ++ uint64_t ena_pko:1; ++ } s; ++ struct cvmx_pko_reg_flags_s cn30xx; ++ struct cvmx_pko_reg_flags_s cn31xx; ++ struct cvmx_pko_reg_flags_s cn38xx; ++ struct cvmx_pko_reg_flags_s cn38xxp2; ++ struct cvmx_pko_reg_flags_s cn50xx; ++ struct cvmx_pko_reg_flags_s cn52xx; ++ struct cvmx_pko_reg_flags_s cn52xxp1; ++ struct cvmx_pko_reg_flags_s cn56xx; ++ struct cvmx_pko_reg_flags_s cn56xxp1; ++ struct cvmx_pko_reg_flags_s cn58xx; ++ struct cvmx_pko_reg_flags_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_gmx_port_mode { ++ uint64_t u64; ++ struct cvmx_pko_reg_gmx_port_mode_s { ++ uint64_t reserved_6_63:58; ++ uint64_t mode1:3; ++ uint64_t mode0:3; ++ } s; ++ struct cvmx_pko_reg_gmx_port_mode_s cn30xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn31xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn38xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn38xxp2; ++ struct cvmx_pko_reg_gmx_port_mode_s cn50xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn52xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn52xxp1; ++ struct cvmx_pko_reg_gmx_port_mode_s cn56xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn56xxp1; ++ struct cvmx_pko_reg_gmx_port_mode_s cn58xx; ++ struct cvmx_pko_reg_gmx_port_mode_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_int_mask { ++ uint64_t u64; ++ struct cvmx_pko_reg_int_mask_s { ++ uint64_t reserved_3_63:61; ++ uint64_t currzero:1; ++ uint64_t doorbell:1; ++ uint64_t parity:1; ++ } s; ++ struct cvmx_pko_reg_int_mask_cn30xx { ++ uint64_t reserved_2_63:62; ++ uint64_t doorbell:1; ++ uint64_t parity:1; ++ } cn30xx; ++ struct cvmx_pko_reg_int_mask_cn30xx cn31xx; ++ struct cvmx_pko_reg_int_mask_cn30xx cn38xx; ++ struct cvmx_pko_reg_int_mask_cn30xx cn38xxp2; ++ struct cvmx_pko_reg_int_mask_s cn50xx; ++ struct cvmx_pko_reg_int_mask_s cn52xx; ++ struct cvmx_pko_reg_int_mask_s cn52xxp1; ++ struct cvmx_pko_reg_int_mask_s cn56xx; ++ struct cvmx_pko_reg_int_mask_s cn56xxp1; ++ struct cvmx_pko_reg_int_mask_s cn58xx; ++ struct cvmx_pko_reg_int_mask_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_queue_mode { ++ uint64_t u64; ++ struct cvmx_pko_reg_queue_mode_s { ++ uint64_t reserved_2_63:62; ++ uint64_t mode:2; ++ } s; ++ struct cvmx_pko_reg_queue_mode_s cn30xx; ++ struct cvmx_pko_reg_queue_mode_s cn31xx; ++ struct cvmx_pko_reg_queue_mode_s cn38xx; ++ struct cvmx_pko_reg_queue_mode_s cn38xxp2; ++ struct cvmx_pko_reg_queue_mode_s cn50xx; ++ struct cvmx_pko_reg_queue_mode_s cn52xx; ++ struct cvmx_pko_reg_queue_mode_s cn52xxp1; ++ struct cvmx_pko_reg_queue_mode_s cn56xx; ++ struct cvmx_pko_reg_queue_mode_s cn56xxp1; ++ struct cvmx_pko_reg_queue_mode_s cn58xx; ++ struct cvmx_pko_reg_queue_mode_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_queue_ptrs1 { ++ uint64_t u64; ++ struct cvmx_pko_reg_queue_ptrs1_s { ++ uint64_t reserved_2_63:62; ++ uint64_t idx3:1; ++ uint64_t qid7:1; ++ } s; ++ struct cvmx_pko_reg_queue_ptrs1_s cn50xx; ++ struct cvmx_pko_reg_queue_ptrs1_s cn52xx; ++ struct cvmx_pko_reg_queue_ptrs1_s cn52xxp1; ++ struct cvmx_pko_reg_queue_ptrs1_s cn56xx; ++ struct cvmx_pko_reg_queue_ptrs1_s cn56xxp1; ++ struct cvmx_pko_reg_queue_ptrs1_s cn58xx; ++ struct cvmx_pko_reg_queue_ptrs1_s cn58xxp1; ++}; ++ ++union cvmx_pko_reg_read_idx { ++ uint64_t u64; ++ struct cvmx_pko_reg_read_idx_s { ++ uint64_t reserved_16_63:48; ++ uint64_t inc:8; ++ uint64_t index:8; ++ } s; ++ struct cvmx_pko_reg_read_idx_s cn30xx; ++ struct cvmx_pko_reg_read_idx_s cn31xx; ++ struct cvmx_pko_reg_read_idx_s cn38xx; ++ struct cvmx_pko_reg_read_idx_s cn38xxp2; ++ struct cvmx_pko_reg_read_idx_s cn50xx; ++ struct cvmx_pko_reg_read_idx_s cn52xx; ++ struct cvmx_pko_reg_read_idx_s cn52xxp1; ++ struct cvmx_pko_reg_read_idx_s cn56xx; ++ struct cvmx_pko_reg_read_idx_s cn56xxp1; ++ struct cvmx_pko_reg_read_idx_s cn58xx; ++ struct cvmx_pko_reg_read_idx_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pko.c +@@ -0,0 +1,506 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * Support library for the hardware Packet Output unit. ++ */ ++ ++#include ++ ++#include "cvmx-config.h" ++#include "cvmx-pko.h" ++#include "cvmx-helper.h" ++ ++/** ++ * Internal state of packet output ++ */ ++ ++/** ++ * Call before any other calls to initialize the packet ++ * output system. This does chip global config, and should only be ++ * done by one core. ++ */ ++ ++void cvmx_pko_initialize_global(void) ++{ ++ int i; ++ uint64_t priority = 8; ++ union cvmx_pko_reg_cmd_buf config; ++ ++ /* ++ * Set the size of the PKO command buffers to an odd number of ++ * 64bit words. This allows the normal two word send to stay ++ * aligned and never span a comamnd word buffer. ++ */ ++ config.u64 = 0; ++ config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL; ++ config.s.size = CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE / 8 - 1; ++ ++ cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64); ++ ++ for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) ++ cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1, ++ &priority); ++ ++ /* ++ * If we aren't using all of the queues optimize PKO's ++ * internal memory. ++ */ ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX) ++ || OCTEON_IS_MODEL(OCTEON_CN56XX) ++ || OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ int num_interfaces = cvmx_helper_get_number_of_interfaces(); ++ int last_port = ++ cvmx_helper_get_last_ipd_port(num_interfaces - 1); ++ int max_queues = ++ cvmx_pko_get_base_queue(last_port) + ++ cvmx_pko_get_num_queues(last_port); ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { ++ if (max_queues <= 32) ++ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2); ++ else if (max_queues <= 64) ++ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1); ++ } else { ++ if (max_queues <= 64) ++ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2); ++ else if (max_queues <= 128) ++ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1); ++ } ++ } ++} ++ ++/** ++ * This function does per-core initialization required by the PKO routines. ++ * This must be called on all cores that will do packet output, and must ++ * be called after the FPA has been initialized and filled with pages. ++ * ++ * Returns 0 on success ++ * !0 on failure ++ */ ++int cvmx_pko_initialize_local(void) ++{ ++ /* Nothing to do */ ++ return 0; ++} ++ ++/** ++ * Enables the packet output hardware. It must already be ++ * configured. ++ */ ++void cvmx_pko_enable(void) ++{ ++ union cvmx_pko_reg_flags flags; ++ ++ flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); ++ if (flags.s.ena_pko) ++ cvmx_dprintf ++ ("Warning: Enabling PKO when PKO already enabled.\n"); ++ ++ flags.s.ena_dwb = 1; ++ flags.s.ena_pko = 1; ++ /* ++ * always enable big endian for 3-word command. Does nothing ++ * for 2-word. ++ */ ++ flags.s.store_be = 1; ++ cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64); ++} ++ ++/** ++ * Disables the packet output. Does not affect any configuration. ++ */ ++void cvmx_pko_disable(void) ++{ ++ union cvmx_pko_reg_flags pko_reg_flags; ++ pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); ++ pko_reg_flags.s.ena_pko = 0; ++ cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); ++} ++ ++ ++/** ++ * Reset the packet output. ++ */ ++static void __cvmx_pko_reset(void) ++{ ++ union cvmx_pko_reg_flags pko_reg_flags; ++ pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); ++ pko_reg_flags.s.reset = 1; ++ cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); ++} ++ ++/** ++ * Shutdown and free resources required by packet output. ++ */ ++void cvmx_pko_shutdown(void) ++{ ++ union cvmx_pko_mem_queue_ptrs config; ++ int queue; ++ ++ cvmx_pko_disable(); ++ ++ for (queue = 0; queue < CVMX_PKO_MAX_OUTPUT_QUEUES; queue++) { ++ config.u64 = 0; ++ config.s.tail = 1; ++ config.s.index = 0; ++ config.s.port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID; ++ config.s.queue = queue & 0x7f; ++ config.s.qos_mask = 0; ++ config.s.buf_ptr = 0; ++ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ union cvmx_pko_reg_queue_ptrs1 config1; ++ config1.u64 = 0; ++ config1.s.qid7 = queue >> 7; ++ cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); ++ } ++ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); ++ cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue)); ++ } ++ __cvmx_pko_reset(); ++} ++ ++/** ++ * Configure a output port and the associated queues for use. ++ * ++ * @port: Port to configure. ++ * @base_queue: First queue number to associate with this port. ++ * @num_queues: Number of queues to associate with this port ++ * @priority: Array of priority levels for each queue. Values are ++ * allowed to be 0-8. A value of 8 get 8 times the traffic ++ * of a value of 1. A value of 0 indicates that no rounds ++ * will be participated in. These priorities can be changed ++ * on the fly while the pko is enabled. A priority of 9 ++ * indicates that static priority should be used. If static ++ * priority is used all queues with static priority must be ++ * contiguous starting at the base_queue, and lower numbered ++ * queues have higher priority than higher numbered queues. ++ * There must be num_queues elements in the array. ++ */ ++cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, ++ uint64_t num_queues, ++ const uint64_t priority[]) ++{ ++ cvmx_pko_status_t result_code; ++ uint64_t queue; ++ union cvmx_pko_mem_queue_ptrs config; ++ union cvmx_pko_reg_queue_ptrs1 config1; ++ int static_priority_base = -1; ++ int static_priority_end = -1; ++ ++ if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS) ++ && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) { ++ cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n", ++ (unsigned long long)port); ++ return CVMX_PKO_INVALID_PORT; ++ } ++ ++ if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES) { ++ cvmx_dprintf ++ ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n", ++ (unsigned long long)(base_queue + num_queues)); ++ return CVMX_PKO_INVALID_QUEUE; ++ } ++ ++ if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { ++ /* ++ * Validate the static queue priority setup and set ++ * static_priority_base and static_priority_end ++ * accordingly. ++ */ ++ for (queue = 0; queue < num_queues; queue++) { ++ /* Find first queue of static priority */ ++ if (static_priority_base == -1 ++ && priority[queue] == ++ CVMX_PKO_QUEUE_STATIC_PRIORITY) ++ static_priority_base = queue; ++ /* Find last queue of static priority */ ++ if (static_priority_base != -1 ++ && static_priority_end == -1 ++ && priority[queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY ++ && queue) ++ static_priority_end = queue - 1; ++ else if (static_priority_base != -1 ++ && static_priority_end == -1 ++ && queue == num_queues - 1) ++ /* all queues are static priority */ ++ static_priority_end = queue; ++ /* ++ * Check to make sure all static priority ++ * queues are contiguous. Also catches some ++ * cases of static priorites not starting at ++ * queue 0. ++ */ ++ if (static_priority_end != -1 ++ && (int)queue > static_priority_end ++ && priority[queue] == ++ CVMX_PKO_QUEUE_STATIC_PRIORITY) { ++ cvmx_dprintf("ERROR: cvmx_pko_config_port: " ++ "Static priority queues aren't " ++ "contiguous or don't start at " ++ "base queue. q: %d, eq: %d\n", ++ (int)queue, static_priority_end); ++ return CVMX_PKO_INVALID_PRIORITY; ++ } ++ } ++ if (static_priority_base > 0) { ++ cvmx_dprintf("ERROR: cvmx_pko_config_port: Static " ++ "priority queues don't start at base " ++ "queue. sq: %d\n", ++ static_priority_base); ++ return CVMX_PKO_INVALID_PRIORITY; ++ } ++#if 0 ++ cvmx_dprintf("Port %d: Static priority queue base: %d, " ++ "end: %d\n", port, ++ static_priority_base, static_priority_end); ++#endif ++ } ++ /* ++ * At this point, static_priority_base and static_priority_end ++ * are either both -1, or are valid start/end queue ++ * numbers. ++ */ ++ ++ result_code = CVMX_PKO_SUCCESS; ++ ++#ifdef PKO_DEBUG ++ cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues, ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0, ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1); ++#endif ++ ++ for (queue = 0; queue < num_queues; queue++) { ++ uint64_t *buf_ptr = NULL; ++ ++ config1.u64 = 0; ++ config1.s.idx3 = queue >> 3; ++ config1.s.qid7 = (base_queue + queue) >> 7; ++ ++ config.u64 = 0; ++ config.s.tail = queue == (num_queues - 1); ++ config.s.index = queue; ++ config.s.port = port; ++ config.s.queue = base_queue + queue; ++ ++ if (!cvmx_octeon_is_pass1()) { ++ config.s.static_p = static_priority_base >= 0; ++ config.s.static_q = (int)queue <= static_priority_end; ++ config.s.s_tail = (int)queue == static_priority_end; ++ } ++ /* ++ * Convert the priority into an enable bit field. Try ++ * to space the bits out evenly so the packet don't ++ * get grouped up ++ */ ++ switch ((int)priority[queue]) { ++ case 0: ++ config.s.qos_mask = 0x00; ++ break; ++ case 1: ++ config.s.qos_mask = 0x01; ++ break; ++ case 2: ++ config.s.qos_mask = 0x11; ++ break; ++ case 3: ++ config.s.qos_mask = 0x49; ++ break; ++ case 4: ++ config.s.qos_mask = 0x55; ++ break; ++ case 5: ++ config.s.qos_mask = 0x57; ++ break; ++ case 6: ++ config.s.qos_mask = 0x77; ++ break; ++ case 7: ++ config.s.qos_mask = 0x7f; ++ break; ++ case 8: ++ config.s.qos_mask = 0xff; ++ break; ++ case CVMX_PKO_QUEUE_STATIC_PRIORITY: ++ /* Pass 1 will fall through to the error case */ ++ if (!cvmx_octeon_is_pass1()) { ++ config.s.qos_mask = 0xff; ++ break; ++ } ++ default: ++ cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid " ++ "priority %llu\n", ++ (unsigned long long)priority[queue]); ++ config.s.qos_mask = 0xff; ++ result_code = CVMX_PKO_INVALID_PRIORITY; ++ break; ++ } ++ ++ if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { ++ cvmx_cmd_queue_result_t cmd_res = ++ cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO ++ (base_queue + queue), ++ CVMX_PKO_MAX_QUEUE_DEPTH, ++ CVMX_FPA_OUTPUT_BUFFER_POOL, ++ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE ++ - ++ CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST ++ * 8); ++ if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) { ++ switch (cmd_res) { ++ case CVMX_CMD_QUEUE_NO_MEMORY: ++ cvmx_dprintf("ERROR: " ++ "cvmx_pko_config_port: " ++ "Unable to allocate " ++ "output buffer.\n"); ++ return CVMX_PKO_NO_MEMORY; ++ case CVMX_CMD_QUEUE_ALREADY_SETUP: ++ cvmx_dprintf ++ ("ERROR: cvmx_pko_config_port: Port already setup.\n"); ++ return CVMX_PKO_PORT_ALREADY_SETUP; ++ case CVMX_CMD_QUEUE_INVALID_PARAM: ++ default: ++ cvmx_dprintf ++ ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n"); ++ return CVMX_PKO_CMD_QUEUE_INIT_ERROR; ++ } ++ } ++ ++ buf_ptr = ++ (uint64_t *) ++ cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO ++ (base_queue + queue)); ++ config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr); ++ } else ++ config.s.buf_ptr = 0; ++ ++ CVMX_SYNCWS; ++ ++ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) ++ cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); ++ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); ++ } ++ ++ return result_code; ++} ++ ++#ifdef PKO_DEBUG ++/** ++ * Show map of ports -> queues for different cores. ++ */ ++void cvmx_pko_show_queue_map() ++{ ++ int core, port; ++ int pko_output_ports = 36; ++ ++ cvmx_dprintf("port"); ++ for (port = 0; port < pko_output_ports; port++) ++ cvmx_dprintf("%3d ", port); ++ cvmx_dprintf("\n"); ++ ++ for (core = 0; core < CVMX_MAX_CORES; core++) { ++ cvmx_dprintf("\n%2d: ", core); ++ for (port = 0; port < pko_output_ports; port++) { ++ cvmx_dprintf("%3d ", ++ cvmx_pko_get_base_queue_per_core(port, ++ core)); ++ } ++ } ++ cvmx_dprintf("\n"); ++} ++#endif ++ ++/** ++ * Rate limit a PKO port to a max packets/sec. This function is only ++ * supported on CN51XX and higher, excluding CN58XX. ++ * ++ * @port: Port to rate limit ++ * @packets_s: Maximum packet/sec ++ * @burst: Maximum number of packets to burst in a row before rate ++ * limiting cuts in. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst) ++{ ++ union cvmx_pko_mem_port_rate0 pko_mem_port_rate0; ++ union cvmx_pko_mem_port_rate1 pko_mem_port_rate1; ++ ++ pko_mem_port_rate0.u64 = 0; ++ pko_mem_port_rate0.s.pid = port; ++ pko_mem_port_rate0.s.rate_pkt = ++ cvmx_sysinfo_get()->cpu_clock_hz / packets_s / 16; ++ /* No cost per word since we are limited by packets/sec, not bits/sec */ ++ pko_mem_port_rate0.s.rate_word = 0; ++ ++ pko_mem_port_rate1.u64 = 0; ++ pko_mem_port_rate1.s.pid = port; ++ pko_mem_port_rate1.s.rate_lim = ++ ((uint64_t) pko_mem_port_rate0.s.rate_pkt * burst) >> 8; ++ ++ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64); ++ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64); ++ return 0; ++} ++ ++/** ++ * Rate limit a PKO port to a max bits/sec. This function is only ++ * supported on CN51XX and higher, excluding CN58XX. ++ * ++ * @port: Port to rate limit ++ * @bits_s: PKO rate limit in bits/sec ++ * @burst: Maximum number of bits to burst before rate ++ * limiting cuts in. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst) ++{ ++ union cvmx_pko_mem_port_rate0 pko_mem_port_rate0; ++ union cvmx_pko_mem_port_rate1 pko_mem_port_rate1; ++ uint64_t clock_rate = cvmx_sysinfo_get()->cpu_clock_hz; ++ uint64_t tokens_per_bit = clock_rate * 16 / bits_s; ++ ++ pko_mem_port_rate0.u64 = 0; ++ pko_mem_port_rate0.s.pid = port; ++ /* ++ * Each packet has a 12 bytes of interframe gap, an 8 byte ++ * preamble, and a 4 byte CRC. These are not included in the ++ * per word count. Multiply by 8 to covert to bits and divide ++ * by 256 for limit granularity. ++ */ ++ pko_mem_port_rate0.s.rate_pkt = (12 + 8 + 4) * 8 * tokens_per_bit / 256; ++ /* Each 8 byte word has 64bits */ ++ pko_mem_port_rate0.s.rate_word = 64 * tokens_per_bit; ++ ++ pko_mem_port_rate1.u64 = 0; ++ pko_mem_port_rate1.s.pid = port; ++ pko_mem_port_rate1.s.rate_lim = tokens_per_bit * burst / 256; ++ ++ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64); ++ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64); ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pko.h +@@ -0,0 +1,610 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * Interface to the hardware Packet Output unit. ++ * ++ * Starting with SDK 1.7.0, the PKO output functions now support ++ * two types of locking. CVMX_PKO_LOCK_ATOMIC_TAG continues to ++ * function similarly to previous SDKs by using POW atomic tags ++ * to preserve ordering and exclusivity. As a new option, you ++ * can now pass CVMX_PKO_LOCK_CMD_QUEUE which uses a ll/sc ++ * memory based locking instead. This locking has the advantage ++ * of not affecting the tag state but doesn't preserve packet ++ * ordering. CVMX_PKO_LOCK_CMD_QUEUE is appropriate in most ++ * generic code while CVMX_PKO_LOCK_CMD_QUEUE should be used ++ * with hand tuned fast path code. ++ * ++ * Some of other SDK differences visible to the command command ++ * queuing: ++ * - PKO indexes are no longer stored in the FAU. A large ++ * percentage of the FAU register block used to be tied up ++ * maintaining PKO queue pointers. These are now stored in a ++ * global named block. ++ * - The PKO use_locking parameter can now have a global ++ * effect. Since all application use the same named block, ++ * queue locking correctly applies across all operating ++ * systems when using CVMX_PKO_LOCK_CMD_QUEUE. ++ * - PKO 3 word commands are now supported. Use ++ * cvmx_pko_send_packet_finish3(). ++ * ++ */ ++ ++#ifndef __CVMX_PKO_H__ ++#define __CVMX_PKO_H__ ++ ++#include "cvmx-fpa.h" ++#include "cvmx-pow.h" ++#include "cvmx-cmd-queue.h" ++#include "cvmx-pko-defs.h" ++ ++/* Adjust the command buffer size by 1 word so that in the case of using only ++ * two word PKO commands no command words stradle buffers. The useful values ++ * for this are 0 and 1. */ ++#define CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST (1) ++ ++#define CVMX_PKO_MAX_OUTPUT_QUEUES_STATIC 256 ++#define CVMX_PKO_MAX_OUTPUT_QUEUES ((OCTEON_IS_MODEL(OCTEON_CN31XX) || \ ++ OCTEON_IS_MODEL(OCTEON_CN3010) || OCTEON_IS_MODEL(OCTEON_CN3005) || \ ++ OCTEON_IS_MODEL(OCTEON_CN50XX)) ? 32 : \ ++ (OCTEON_IS_MODEL(OCTEON_CN58XX) || \ ++ OCTEON_IS_MODEL(OCTEON_CN56XX)) ? 256 : 128) ++#define CVMX_PKO_NUM_OUTPUT_PORTS 40 ++/* use this for queues that are not used */ ++#define CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID 63 ++#define CVMX_PKO_QUEUE_STATIC_PRIORITY 9 ++#define CVMX_PKO_ILLEGAL_QUEUE 0xFFFF ++#define CVMX_PKO_MAX_QUEUE_DEPTH 0 ++ ++typedef enum { ++ CVMX_PKO_SUCCESS, ++ CVMX_PKO_INVALID_PORT, ++ CVMX_PKO_INVALID_QUEUE, ++ CVMX_PKO_INVALID_PRIORITY, ++ CVMX_PKO_NO_MEMORY, ++ CVMX_PKO_PORT_ALREADY_SETUP, ++ CVMX_PKO_CMD_QUEUE_INIT_ERROR ++} cvmx_pko_status_t; ++ ++/** ++ * This enumeration represents the differnet locking modes supported by PKO. ++ */ ++typedef enum { ++ /* ++ * PKO doesn't do any locking. It is the responsibility of the ++ * application to make sure that no other core is accessing ++ * the same queue at the smae time ++ */ ++ CVMX_PKO_LOCK_NONE = 0, ++ /* ++ * PKO performs an atomic tagswitch to insure exclusive access ++ * to the output queue. This will maintain packet ordering on ++ * output. ++ */ ++ CVMX_PKO_LOCK_ATOMIC_TAG = 1, ++ /* ++ * PKO uses the common command queue locks to insure exclusive ++ * access to the output queue. This is a memory based ++ * ll/sc. This is the most portable locking mechanism. ++ */ ++ CVMX_PKO_LOCK_CMD_QUEUE = 2, ++} cvmx_pko_lock_t; ++ ++typedef struct { ++ uint32_t packets; ++ uint64_t octets; ++ uint64_t doorbell; ++} cvmx_pko_port_status_t; ++ ++/** ++ * This structure defines the address to use on a packet enqueue ++ */ ++typedef union { ++ uint64_t u64; ++ struct { ++ /* Must CVMX_IO_SEG */ ++ uint64_t mem_space:2; ++ /* Must be zero */ ++ uint64_t reserved:13; ++ /* Must be one */ ++ uint64_t is_io:1; ++ /* The ID of the device on the non-coherent bus */ ++ uint64_t did:8; ++ /* Must be zero */ ++ uint64_t reserved2:4; ++ /* Must be zero */ ++ uint64_t reserved3:18; ++ /* ++ * The hardware likes to have the output port in ++ * addition to the output queue, ++ */ ++ uint64_t port:6; ++ /* ++ * The output queue to send the packet to (0-127 are ++ * legal) ++ */ ++ uint64_t queue:9; ++ /* Must be zero */ ++ uint64_t reserved4:3; ++ } s; ++} cvmx_pko_doorbell_address_t; ++ ++/** ++ * Structure of the first packet output command word. ++ */ ++typedef union { ++ uint64_t u64; ++ struct { ++ /* ++ * The size of the reg1 operation - could be 8, 16, ++ * 32, or 64 bits. ++ */ ++ uint64_t size1:2; ++ /* ++ * The size of the reg0 operation - could be 8, 16, ++ * 32, or 64 bits. ++ */ ++ uint64_t size0:2; ++ /* ++ * If set, subtract 1, if clear, subtract packet ++ * size. ++ */ ++ uint64_t subone1:1; ++ /* ++ * The register, subtract will be done if reg1 is ++ * non-zero. ++ */ ++ uint64_t reg1:11; ++ /* If set, subtract 1, if clear, subtract packet size */ ++ uint64_t subone0:1; ++ /* The register, subtract will be done if reg0 is non-zero */ ++ uint64_t reg0:11; ++ /* ++ * When set, interpret segment pointer and segment ++ * bytes in little endian order. ++ */ ++ uint64_t le:1; ++ /* ++ * When set, packet data not allocated in L2 cache by ++ * PKO. ++ */ ++ uint64_t n2:1; ++ /* ++ * If set and rsp is set, word3 contains a pointer to ++ * a work queue entry. ++ */ ++ uint64_t wqp:1; ++ /* If set, the hardware will send a response when done */ ++ uint64_t rsp:1; ++ /* ++ * If set, the supplied pkt_ptr is really a pointer to ++ * a list of pkt_ptr's. ++ */ ++ uint64_t gather:1; ++ /* ++ * If ipoffp1 is non zero, (ipoffp1-1) is the number ++ * of bytes to IP header, and the hardware will ++ * calculate and insert the UDP/TCP checksum. ++ */ ++ uint64_t ipoffp1:7; ++ /* ++ * If set, ignore the I bit (force to zero) from all ++ * pointer structures. ++ */ ++ uint64_t ignore_i:1; ++ /* ++ * If clear, the hardware will attempt to free the ++ * buffers containing the packet. ++ */ ++ uint64_t dontfree:1; ++ /* ++ * The total number of segs in the packet, if gather ++ * set, also gather list length. ++ */ ++ uint64_t segs:6; ++ /* Including L2, but no trailing CRC */ ++ uint64_t total_bytes:16; ++ } s; ++} cvmx_pko_command_word0_t; ++ ++/* CSR typedefs have been moved to cvmx-csr-*.h */ ++ ++/** ++ * Definition of internal state for Packet output processing ++ */ ++typedef struct { ++ /* ptr to start of buffer, offset kept in FAU reg */ ++ uint64_t *start_ptr; ++} cvmx_pko_state_elem_t; ++ ++/** ++ * Call before any other calls to initialize the packet ++ * output system. ++ */ ++extern void cvmx_pko_initialize_global(void); ++extern int cvmx_pko_initialize_local(void); ++ ++/** ++ * Enables the packet output hardware. It must already be ++ * configured. ++ */ ++extern void cvmx_pko_enable(void); ++ ++/** ++ * Disables the packet output. Does not affect any configuration. ++ */ ++extern void cvmx_pko_disable(void); ++ ++/** ++ * Shutdown and free resources required by packet output. ++ */ ++ ++extern void cvmx_pko_shutdown(void); ++ ++/** ++ * Configure a output port and the associated queues for use. ++ * ++ * @port: Port to configure. ++ * @base_queue: First queue number to associate with this port. ++ * @num_queues: Number of queues t oassociate with this port ++ * @priority: Array of priority levels for each queue. Values are ++ * allowed to be 1-8. A value of 8 get 8 times the traffic ++ * of a value of 1. There must be num_queues elements in the ++ * array. ++ */ ++extern cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, ++ uint64_t base_queue, ++ uint64_t num_queues, ++ const uint64_t priority[]); ++ ++/** ++ * Ring the packet output doorbell. This tells the packet ++ * output hardware that "len" command words have been added ++ * to its pending list. This command includes the required ++ * CVMX_SYNCWS before the doorbell ring. ++ * ++ * @port: Port the packet is for ++ * @queue: Queue the packet is for ++ * @len: Length of the command in 64 bit words ++ */ ++static inline void cvmx_pko_doorbell(uint64_t port, uint64_t queue, ++ uint64_t len) ++{ ++ cvmx_pko_doorbell_address_t ptr; ++ ++ ptr.u64 = 0; ++ ptr.s.mem_space = CVMX_IO_SEG; ++ ptr.s.did = CVMX_OCT_DID_PKT_SEND; ++ ptr.s.is_io = 1; ++ ptr.s.port = port; ++ ptr.s.queue = queue; ++ /* ++ * Need to make sure output queue data is in DRAM before ++ * doorbell write. ++ */ ++ CVMX_SYNCWS; ++ cvmx_write_io(ptr.u64, len); ++} ++ ++/** ++ * Prepare to send a packet. This may initiate a tag switch to ++ * get exclusive access to the output queue structure, and ++ * performs other prep work for the packet send operation. ++ * ++ * cvmx_pko_send_packet_finish() MUST be called after this function is called, ++ * and must be called with the same port/queue/use_locking arguments. ++ * ++ * The use_locking parameter allows the caller to use three ++ * possible locking modes. ++ * - CVMX_PKO_LOCK_NONE ++ * - PKO doesn't do any locking. It is the responsibility ++ * of the application to make sure that no other core ++ * is accessing the same queue at the smae time. ++ * - CVMX_PKO_LOCK_ATOMIC_TAG ++ * - PKO performs an atomic tagswitch to insure exclusive ++ * access to the output queue. This will maintain ++ * packet ordering on output. ++ * - CVMX_PKO_LOCK_CMD_QUEUE ++ * - PKO uses the common command queue locks to insure ++ * exclusive access to the output queue. This is a ++ * memory based ll/sc. This is the most portable ++ * locking mechanism. ++ * ++ * NOTE: If atomic locking is used, the POW entry CANNOT be ++ * descheduled, as it does not contain a valid WQE pointer. ++ * ++ * @port: Port to send it on ++ * @queue: Queue to use ++ * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or ++ * CVMX_PKO_LOCK_CMD_QUEUE ++ */ ++ ++static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, ++ cvmx_pko_lock_t use_locking) ++{ ++ if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) { ++ /* ++ * Must do a full switch here to handle all cases. We ++ * use a fake WQE pointer, as the POW does not access ++ * this memory. The WQE pointer and group are only ++ * used if this work is descheduled, which is not ++ * supported by the ++ * cvmx_pko_send_packet_prepare/cvmx_pko_send_packet_finish ++ * combination. Note that this is a special case in ++ * which these fake values can be used - this is not a ++ * general technique. ++ */ ++ uint32_t tag = ++ CVMX_TAG_SW_BITS_INTERNAL << CVMX_TAG_SW_SHIFT | ++ CVMX_TAG_SUBGROUP_PKO << CVMX_TAG_SUBGROUP_SHIFT | ++ (CVMX_TAG_SUBGROUP_MASK & queue); ++ cvmx_pow_tag_sw_full((cvmx_wqe_t *) cvmx_phys_to_ptr(0x80), tag, ++ CVMX_POW_TAG_TYPE_ATOMIC, 0); ++ } ++} ++ ++/** ++ * Complete packet output. cvmx_pko_send_packet_prepare() must be ++ * called exactly once before this, and the same parameters must be ++ * passed to both cvmx_pko_send_packet_prepare() and ++ * cvmx_pko_send_packet_finish(). ++ * ++ * @port: Port to send it on ++ * @queue: Queue to use ++ * @pko_command: ++ * PKO HW command word ++ * @packet: Packet to send ++ * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or ++ * CVMX_PKO_LOCK_CMD_QUEUE ++ * ++ * Returns returns CVMX_PKO_SUCCESS on success, or error code on ++ * failure of output ++ */ ++static inline cvmx_pko_status_t cvmx_pko_send_packet_finish( ++ uint64_t port, ++ uint64_t queue, ++ cvmx_pko_command_word0_t pko_command, ++ union cvmx_buf_ptr packet, ++ cvmx_pko_lock_t use_locking) ++{ ++ cvmx_cmd_queue_result_t result; ++ if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) ++ cvmx_pow_tag_sw_wait(); ++ result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), ++ (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), ++ pko_command.u64, packet.u64); ++ if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) { ++ cvmx_pko_doorbell(port, queue, 2); ++ return CVMX_PKO_SUCCESS; ++ } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) ++ || (result == CVMX_CMD_QUEUE_FULL)) { ++ return CVMX_PKO_NO_MEMORY; ++ } else { ++ return CVMX_PKO_INVALID_QUEUE; ++ } ++} ++ ++/** ++ * Complete packet output. cvmx_pko_send_packet_prepare() must be ++ * called exactly once before this, and the same parameters must be ++ * passed to both cvmx_pko_send_packet_prepare() and ++ * cvmx_pko_send_packet_finish(). ++ * ++ * @port: Port to send it on ++ * @queue: Queue to use ++ * @pko_command: ++ * PKO HW command word ++ * @packet: Packet to send ++ * @addr: Plysical address of a work queue entry or physical address ++ * to zero on complete. ++ * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or ++ * CVMX_PKO_LOCK_CMD_QUEUE ++ * ++ * Returns returns CVMX_PKO_SUCCESS on success, or error code on ++ * failure of output ++ */ ++static inline cvmx_pko_status_t cvmx_pko_send_packet_finish3( ++ uint64_t port, ++ uint64_t queue, ++ cvmx_pko_command_word0_t pko_command, ++ union cvmx_buf_ptr packet, ++ uint64_t addr, ++ cvmx_pko_lock_t use_locking) ++{ ++ cvmx_cmd_queue_result_t result; ++ if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) ++ cvmx_pow_tag_sw_wait(); ++ result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), ++ (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), ++ pko_command.u64, packet.u64, addr); ++ if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) { ++ cvmx_pko_doorbell(port, queue, 3); ++ return CVMX_PKO_SUCCESS; ++ } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) ++ || (result == CVMX_CMD_QUEUE_FULL)) { ++ return CVMX_PKO_NO_MEMORY; ++ } else { ++ return CVMX_PKO_INVALID_QUEUE; ++ } ++} ++ ++/** ++ * Return the pko output queue associated with a port and a specific core. ++ * In normal mode (PKO lockless operation is disabled), the value returned ++ * is the base queue. ++ * ++ * @port: Port number ++ * @core: Core to get queue for ++ * ++ * Returns Core-specific output queue ++ */ ++static inline int cvmx_pko_get_base_queue_per_core(int port, int core) ++{ ++#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 ++#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 16 ++#endif ++#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 ++#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 16 ++#endif ++ ++ if (port < CVMX_PKO_MAX_PORTS_INTERFACE0) ++ return port * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + core; ++ else if (port >= 16 && port < 16 + CVMX_PKO_MAX_PORTS_INTERFACE1) ++ return CVMX_PKO_MAX_PORTS_INTERFACE0 * ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + (port - ++ 16) * ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + core; ++ else if ((port >= 32) && (port < 36)) ++ return CVMX_PKO_MAX_PORTS_INTERFACE0 * ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + ++ CVMX_PKO_MAX_PORTS_INTERFACE1 * ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + (port - ++ 32) * ++ CVMX_PKO_QUEUES_PER_PORT_PCI; ++ else if ((port >= 36) && (port < 40)) ++ return CVMX_PKO_MAX_PORTS_INTERFACE0 * ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + ++ CVMX_PKO_MAX_PORTS_INTERFACE1 * ++ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + ++ 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + (port - ++ 36) * ++ CVMX_PKO_QUEUES_PER_PORT_LOOP; ++ else ++ /* Given the limit on the number of ports we can map to ++ * CVMX_MAX_OUTPUT_QUEUES_STATIC queues (currently 256, ++ * divided among all cores), the remaining unmapped ports ++ * are assigned an illegal queue number */ ++ return CVMX_PKO_ILLEGAL_QUEUE; ++} ++ ++/** ++ * For a given port number, return the base pko output queue ++ * for the port. ++ * ++ * @port: Port number ++ * Returns Base output queue ++ */ ++static inline int cvmx_pko_get_base_queue(int port) ++{ ++ return cvmx_pko_get_base_queue_per_core(port, 0); ++} ++ ++/** ++ * For a given port number, return the number of pko output queues. ++ * ++ * @port: Port number ++ * Returns Number of output queues ++ */ ++static inline int cvmx_pko_get_num_queues(int port) ++{ ++ if (port < 16) ++ return CVMX_PKO_QUEUES_PER_PORT_INTERFACE0; ++ else if (port < 32) ++ return CVMX_PKO_QUEUES_PER_PORT_INTERFACE1; ++ else if (port < 36) ++ return CVMX_PKO_QUEUES_PER_PORT_PCI; ++ else if (port < 40) ++ return CVMX_PKO_QUEUES_PER_PORT_LOOP; ++ else ++ return 0; ++} ++ ++/** ++ * Get the status counters for a port. ++ * ++ * @port_num: Port number to get statistics for. ++ * @clear: Set to 1 to clear the counters after they are read ++ * @status: Where to put the results. ++ */ ++static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, ++ cvmx_pko_port_status_t *status) ++{ ++ union cvmx_pko_reg_read_idx pko_reg_read_idx; ++ union cvmx_pko_mem_count0 pko_mem_count0; ++ union cvmx_pko_mem_count1 pko_mem_count1; ++ ++ pko_reg_read_idx.u64 = 0; ++ pko_reg_read_idx.s.index = port_num; ++ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); ++ ++ pko_mem_count0.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT0); ++ status->packets = pko_mem_count0.s.count; ++ if (clear) { ++ pko_mem_count0.s.count = port_num; ++ cvmx_write_csr(CVMX_PKO_MEM_COUNT0, pko_mem_count0.u64); ++ } ++ ++ pko_mem_count1.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT1); ++ status->octets = pko_mem_count1.s.count; ++ if (clear) { ++ pko_mem_count1.s.count = port_num; ++ cvmx_write_csr(CVMX_PKO_MEM_COUNT1, pko_mem_count1.u64); ++ } ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ union cvmx_pko_mem_debug9 debug9; ++ pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); ++ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); ++ debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9); ++ status->doorbell = debug9.cn38xx.doorbell; ++ } else { ++ union cvmx_pko_mem_debug8 debug8; ++ pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); ++ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); ++ debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); ++ status->doorbell = debug8.cn58xx.doorbell; ++ } ++} ++ ++/** ++ * Rate limit a PKO port to a max packets/sec. This function is only ++ * supported on CN57XX, CN56XX, CN55XX, and CN54XX. ++ * ++ * @port: Port to rate limit ++ * @packets_s: Maximum packet/sec ++ * @burst: Maximum number of packets to burst in a row before rate ++ * limiting cuts in. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst); ++ ++/** ++ * Rate limit a PKO port to a max bits/sec. This function is only ++ * supported on CN57XX, CN56XX, CN55XX, and CN54XX. ++ * ++ * @port: Port to rate limit ++ * @bits_s: PKO rate limit in bits/sec ++ * @burst: Maximum number of bits to burst before rate ++ * limiting cuts in. ++ * ++ * Returns Zero on success, negative on failure ++ */ ++extern int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst); ++ ++#endif /* __CVMX_PKO_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-pow.h +@@ -0,0 +1,1982 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * Interface to the hardware Packet Order / Work unit. ++ * ++ * New, starting with SDK 1.7.0, cvmx-pow supports a number of ++ * extended consistency checks. The define ++ * CVMX_ENABLE_POW_CHECKS controls the runtime insertion of POW ++ * internal state checks to find common programming errors. If ++ * CVMX_ENABLE_POW_CHECKS is not defined, checks are by default ++ * enabled. For example, cvmx-pow will check for the following ++ * program errors or POW state inconsistency. ++ * - Requesting a POW operation with an active tag switch in ++ * progress. ++ * - Waiting for a tag switch to complete for an excessively ++ * long period. This is normally a sign of an error in locking ++ * causing deadlock. ++ * - Illegal tag switches from NULL_NULL. ++ * - Illegal tag switches from NULL. ++ * - Illegal deschedule request. ++ * - WQE pointer not matching the one attached to the core by ++ * the POW. ++ * ++ */ ++ ++#ifndef __CVMX_POW_H__ ++#define __CVMX_POW_H__ ++ ++#include ++ ++#include "cvmx-scratch.h" ++#include "cvmx-wqe.h" ++ ++/* Default to having all POW constancy checks turned on */ ++#ifndef CVMX_ENABLE_POW_CHECKS ++#define CVMX_ENABLE_POW_CHECKS 1 ++#endif ++ ++enum cvmx_pow_tag_type { ++ /* Tag ordering is maintained */ ++ CVMX_POW_TAG_TYPE_ORDERED = 0L, ++ /* Tag ordering is maintained, and at most one PP has the tag */ ++ CVMX_POW_TAG_TYPE_ATOMIC = 1L, ++ /* ++ * The work queue entry from the order - NEVER tag switch from ++ * NULL to NULL ++ */ ++ CVMX_POW_TAG_TYPE_NULL = 2L, ++ /* A tag switch to NULL, and there is no space reserved in POW ++ * - NEVER tag switch to NULL_NULL ++ * - NEVER tag switch from NULL_NULL ++ * - NULL_NULL is entered at the beginning of time and on a deschedule. ++ * - NULL_NULL can be exited by a new work request. A NULL_SWITCH ++ * load can also switch the state to NULL ++ */ ++ CVMX_POW_TAG_TYPE_NULL_NULL = 3L ++}; ++ ++/** ++ * Wait flag values for pow functions. ++ */ ++typedef enum { ++ CVMX_POW_WAIT = 1, ++ CVMX_POW_NO_WAIT = 0, ++} cvmx_pow_wait_t; ++ ++/** ++ * POW tag operations. These are used in the data stored to the POW. ++ */ ++typedef enum { ++ /* ++ * switch the tag (only) for this PP ++ * - the previous tag should be non-NULL in this case ++ * - tag switch response required ++ * - fields used: op, type, tag ++ */ ++ CVMX_POW_TAG_OP_SWTAG = 0L, ++ /* ++ * switch the tag for this PP, with full information ++ * - this should be used when the previous tag is NULL ++ * - tag switch response required ++ * - fields used: address, op, grp, type, tag ++ */ ++ CVMX_POW_TAG_OP_SWTAG_FULL = 1L, ++ /* ++ * switch the tag (and/or group) for this PP and de-schedule ++ * - OK to keep the tag the same and only change the group ++ * - fields used: op, no_sched, grp, type, tag ++ */ ++ CVMX_POW_TAG_OP_SWTAG_DESCH = 2L, ++ /* ++ * just de-schedule ++ * - fields used: op, no_sched ++ */ ++ CVMX_POW_TAG_OP_DESCH = 3L, ++ /* ++ * create an entirely new work queue entry ++ * - fields used: address, op, qos, grp, type, tag ++ */ ++ CVMX_POW_TAG_OP_ADDWQ = 4L, ++ /* ++ * just update the work queue pointer and grp for this PP ++ * - fields used: address, op, grp ++ */ ++ CVMX_POW_TAG_OP_UPDATE_WQP_GRP = 5L, ++ /* ++ * set the no_sched bit on the de-schedule list ++ * ++ * - does nothing if the selected entry is not on the ++ * de-schedule list ++ * ++ * - does nothing if the stored work queue pointer does not ++ * match the address field ++ * ++ * - fields used: address, index, op ++ * ++ * Before issuing a *_NSCHED operation, SW must guarantee ++ * that all prior deschedules and set/clr NSCHED operations ++ * are complete and all prior switches are complete. The ++ * hardware provides the opsdone bit and swdone bit for SW ++ * polling. After issuing a *_NSCHED operation, SW must ++ * guarantee that the set/clr NSCHED is complete before any ++ * subsequent operations. ++ */ ++ CVMX_POW_TAG_OP_SET_NSCHED = 6L, ++ /* ++ * clears the no_sched bit on the de-schedule list ++ * ++ * - does nothing if the selected entry is not on the ++ * de-schedule list ++ * ++ * - does nothing if the stored work queue pointer does not ++ * match the address field ++ * ++ * - fields used: address, index, op ++ * ++ * Before issuing a *_NSCHED operation, SW must guarantee that ++ * all prior deschedules and set/clr NSCHED operations are ++ * complete and all prior switches are complete. The hardware ++ * provides the opsdone bit and swdone bit for SW ++ * polling. After issuing a *_NSCHED operation, SW must ++ * guarantee that the set/clr NSCHED is complete before any ++ * subsequent operations. ++ */ ++ CVMX_POW_TAG_OP_CLR_NSCHED = 7L, ++ /* do nothing */ ++ CVMX_POW_TAG_OP_NOP = 15L ++} cvmx_pow_tag_op_t; ++ ++/** ++ * This structure defines the store data on a store to POW ++ */ ++typedef union { ++ uint64_t u64; ++ struct { ++ /* ++ * Don't reschedule this entry. no_sched is used for ++ * CVMX_POW_TAG_OP_SWTAG_DESCH and ++ * CVMX_POW_TAG_OP_DESCH ++ */ ++ uint64_t no_sched:1; ++ uint64_t unused:2; ++ /* Tontains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */ ++ uint64_t index:13; ++ /* The operation to perform */ ++ cvmx_pow_tag_op_t op:4; ++ uint64_t unused2:2; ++ /* ++ * The QOS level for the packet. qos is only used for ++ * CVMX_POW_TAG_OP_ADDWQ ++ */ ++ uint64_t qos:3; ++ /* ++ * The group that the work queue entry will be ++ * scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ, ++ * CVMX_POW_TAG_OP_SWTAG_FULL, ++ * CVMX_POW_TAG_OP_SWTAG_DESCH, and ++ * CVMX_POW_TAG_OP_UPDATE_WQP_GRP ++ */ ++ uint64_t grp:4; ++ /* ++ * The type of the tag. type is used for everything ++ * except CVMX_POW_TAG_OP_DESCH, ++ * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and ++ * CVMX_POW_TAG_OP_*_NSCHED ++ */ ++ uint64_t type:3; ++ /* ++ * The actual tag. tag is used for everything except ++ * CVMX_POW_TAG_OP_DESCH, ++ * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and ++ * CVMX_POW_TAG_OP_*_NSCHED ++ */ ++ uint64_t tag:32; ++ } s; ++} cvmx_pow_tag_req_t; ++ ++/** ++ * This structure describes the address to load stuff from POW ++ */ ++typedef union { ++ uint64_t u64; ++ ++ /** ++ * Address for new work request loads (did<2:0> == 0) ++ */ ++ struct { ++ /* Mips64 address region. Should be CVMX_IO_SEG */ ++ uint64_t mem_region:2; ++ /* Must be zero */ ++ uint64_t reserved_49_61:13; ++ /* Must be one */ ++ uint64_t is_io:1; ++ /* the ID of POW -- did<2:0> == 0 in this case */ ++ uint64_t did:8; ++ /* Must be zero */ ++ uint64_t reserved_4_39:36; ++ /* ++ * If set, don't return load response until work is ++ * available. ++ */ ++ uint64_t wait:1; ++ /* Must be zero */ ++ uint64_t reserved_0_2:3; ++ } swork; ++ ++ /** ++ * Address for loads to get POW internal status ++ */ ++ struct { ++ /* Mips64 address region. Should be CVMX_IO_SEG */ ++ uint64_t mem_region:2; ++ /* Must be zero */ ++ uint64_t reserved_49_61:13; ++ /* Must be one */ ++ uint64_t is_io:1; ++ /* the ID of POW -- did<2:0> == 1 in this case */ ++ uint64_t did:8; ++ /* Must be zero */ ++ uint64_t reserved_10_39:30; ++ /* The core id to get status for */ ++ uint64_t coreid:4; ++ /* ++ * If set and get_cur is set, return reverse tag-list ++ * pointer rather than forward tag-list pointer. ++ */ ++ uint64_t get_rev:1; ++ /* ++ * If set, return current status rather than pending ++ * status. ++ */ ++ uint64_t get_cur:1; ++ /* ++ * If set, get the work-queue pointer rather than ++ * tag/type. ++ */ ++ uint64_t get_wqp:1; ++ /* Must be zero */ ++ uint64_t reserved_0_2:3; ++ } sstatus; ++ ++ /** ++ * Address for memory loads to get POW internal state ++ */ ++ struct { ++ /* Mips64 address region. Should be CVMX_IO_SEG */ ++ uint64_t mem_region:2; ++ /* Must be zero */ ++ uint64_t reserved_49_61:13; ++ /* Must be one */ ++ uint64_t is_io:1; ++ /* the ID of POW -- did<2:0> == 2 in this case */ ++ uint64_t did:8; ++ /* Must be zero */ ++ uint64_t reserved_16_39:24; ++ /* POW memory index */ ++ uint64_t index:11; ++ /* ++ * If set, return deschedule information rather than ++ * the standard response for work-queue index (invalid ++ * if the work-queue entry is not on the deschedule ++ * list). ++ */ ++ uint64_t get_des:1; ++ /* ++ * If set, get the work-queue pointer rather than ++ * tag/type (no effect when get_des set). ++ */ ++ uint64_t get_wqp:1; ++ /* Must be zero */ ++ uint64_t reserved_0_2:3; ++ } smemload; ++ ++ /** ++ * Address for index/pointer loads ++ */ ++ struct { ++ /* Mips64 address region. Should be CVMX_IO_SEG */ ++ uint64_t mem_region:2; ++ /* Must be zero */ ++ uint64_t reserved_49_61:13; ++ /* Must be one */ ++ uint64_t is_io:1; ++ /* the ID of POW -- did<2:0> == 3 in this case */ ++ uint64_t did:8; ++ /* Must be zero */ ++ uint64_t reserved_9_39:31; ++ /* ++ * when {get_rmt ==0 AND get_des_get_tail == 0}, this ++ * field selects one of eight POW internal-input ++ * queues (0-7), one per QOS level; values 8-15 are ++ * illegal in this case; when {get_rmt ==0 AND ++ * get_des_get_tail == 1}, this field selects one of ++ * 16 deschedule lists (per group); when get_rmt ==1, ++ * this field selects one of 16 memory-input queue ++ * lists. The two memory-input queue lists associated ++ * with each QOS level are: ++ * ++ * - qosgrp = 0, qosgrp = 8: QOS0 ++ * - qosgrp = 1, qosgrp = 9: QOS1 ++ * - qosgrp = 2, qosgrp = 10: QOS2 ++ * - qosgrp = 3, qosgrp = 11: QOS3 ++ * - qosgrp = 4, qosgrp = 12: QOS4 ++ * - qosgrp = 5, qosgrp = 13: QOS5 ++ * - qosgrp = 6, qosgrp = 14: QOS6 ++ * - qosgrp = 7, qosgrp = 15: QOS7 ++ */ ++ uint64_t qosgrp:4; ++ /* ++ * If set and get_rmt is clear, return deschedule list ++ * indexes rather than indexes for the specified qos ++ * level; if set and get_rmt is set, return the tail ++ * pointer rather than the head pointer for the ++ * specified qos level. ++ */ ++ uint64_t get_des_get_tail:1; ++ /* ++ * If set, return remote pointers rather than the ++ * local indexes for the specified qos level. ++ */ ++ uint64_t get_rmt:1; ++ /* Must be zero */ ++ uint64_t reserved_0_2:3; ++ } sindexload; ++ ++ /** ++ * address for NULL_RD request (did<2:0> == 4) when this is read, ++ * HW attempts to change the state to NULL if it is NULL_NULL (the ++ * hardware cannot switch from NULL_NULL to NULL if a POW entry is ++ * not available - software may need to recover by finishing ++ * another piece of work before a POW entry can ever become ++ * available.) ++ */ ++ struct { ++ /* Mips64 address region. Should be CVMX_IO_SEG */ ++ uint64_t mem_region:2; ++ /* Must be zero */ ++ uint64_t reserved_49_61:13; ++ /* Must be one */ ++ uint64_t is_io:1; ++ /* the ID of POW -- did<2:0> == 4 in this case */ ++ uint64_t did:8; ++ /* Must be zero */ ++ uint64_t reserved_0_39:40; ++ } snull_rd; ++} cvmx_pow_load_addr_t; ++ ++/** ++ * This structure defines the response to a load/SENDSINGLE to POW ++ * (except CSR reads) ++ */ ++typedef union { ++ uint64_t u64; ++ ++ /** ++ * Response to new work request loads ++ */ ++ struct { ++ /* ++ * Set when no new work queue entry was returned. * ++ * If there was de-scheduled work, the HW will ++ * definitely return it. When this bit is set, it ++ * could mean either mean: ++ * ++ * - There was no work, or ++ * ++ * - There was no work that the HW could find. This ++ * case can happen, regardless of the wait bit value ++ * in the original request, when there is work in ++ * the IQ's that is too deep down the list. ++ */ ++ uint64_t no_work:1; ++ /* Must be zero */ ++ uint64_t reserved_40_62:23; ++ /* 36 in O1 -- the work queue pointer */ ++ uint64_t addr:40; ++ } s_work; ++ ++ /** ++ * Result for a POW Status Load (when get_cur==0 and get_wqp==0) ++ */ ++ struct { ++ uint64_t reserved_62_63:2; ++ /* Set when there is a pending non-NULL SWTAG or ++ * SWTAG_FULL, and the POW entry has not left the list ++ * for the original tag. */ ++ uint64_t pend_switch:1; ++ /* Set when SWTAG_FULL and pend_switch is set. */ ++ uint64_t pend_switch_full:1; ++ /* ++ * Set when there is a pending NULL SWTAG, or an ++ * implicit switch to NULL. ++ */ ++ uint64_t pend_switch_null:1; ++ /* Set when there is a pending DESCHED or SWTAG_DESCHED. */ ++ uint64_t pend_desched:1; ++ /* ++ * Set when there is a pending SWTAG_DESCHED and ++ * pend_desched is set. ++ */ ++ uint64_t pend_desched_switch:1; ++ /* Set when nosched is desired and pend_desched is set. */ ++ uint64_t pend_nosched:1; ++ /* Set when there is a pending GET_WORK. */ ++ uint64_t pend_new_work:1; ++ /* ++ * When pend_new_work is set, this bit indicates that ++ * the wait bit was set. ++ */ ++ uint64_t pend_new_work_wait:1; ++ /* Set when there is a pending NULL_RD. */ ++ uint64_t pend_null_rd:1; ++ /* Set when there is a pending CLR_NSCHED. */ ++ uint64_t pend_nosched_clr:1; ++ uint64_t reserved_51:1; ++ /* This is the index when pend_nosched_clr is set. */ ++ uint64_t pend_index:11; ++ /* ++ * This is the new_grp when (pend_desched AND ++ * pend_desched_switch) is set. ++ */ ++ uint64_t pend_grp:4; ++ uint64_t reserved_34_35:2; ++ /* ++ * This is the tag type when pend_switch or ++ * (pend_desched AND pend_desched_switch) are set. ++ */ ++ uint64_t pend_type:2; ++ /* ++ * - this is the tag when pend_switch or (pend_desched ++ * AND pend_desched_switch) are set. ++ */ ++ uint64_t pend_tag:32; ++ } s_sstatus0; ++ ++ /** ++ * Result for a POW Status Load (when get_cur==0 and get_wqp==1) ++ */ ++ struct { ++ uint64_t reserved_62_63:2; ++ /* ++ * Set when there is a pending non-NULL SWTAG or ++ * SWTAG_FULL, and the POW entry has not left the list ++ * for the original tag. ++ */ ++ uint64_t pend_switch:1; ++ /* Set when SWTAG_FULL and pend_switch is set. */ ++ uint64_t pend_switch_full:1; ++ /* ++ * Set when there is a pending NULL SWTAG, or an ++ * implicit switch to NULL. ++ */ ++ uint64_t pend_switch_null:1; ++ /* ++ * Set when there is a pending DESCHED or ++ * SWTAG_DESCHED. ++ */ ++ uint64_t pend_desched:1; ++ /* ++ * Set when there is a pending SWTAG_DESCHED and ++ * pend_desched is set. ++ */ ++ uint64_t pend_desched_switch:1; ++ /* Set when nosched is desired and pend_desched is set. */ ++ uint64_t pend_nosched:1; ++ /* Set when there is a pending GET_WORK. */ ++ uint64_t pend_new_work:1; ++ /* ++ * When pend_new_work is set, this bit indicates that ++ * the wait bit was set. ++ */ ++ uint64_t pend_new_work_wait:1; ++ /* Set when there is a pending NULL_RD. */ ++ uint64_t pend_null_rd:1; ++ /* Set when there is a pending CLR_NSCHED. */ ++ uint64_t pend_nosched_clr:1; ++ uint64_t reserved_51:1; ++ /* This is the index when pend_nosched_clr is set. */ ++ uint64_t pend_index:11; ++ /* ++ * This is the new_grp when (pend_desched AND ++ * pend_desched_switch) is set. ++ */ ++ uint64_t pend_grp:4; ++ /* This is the wqp when pend_nosched_clr is set. */ ++ uint64_t pend_wqp:36; ++ } s_sstatus1; ++ ++ /** ++ * Result for a POW Status Load (when get_cur==1, get_wqp==0, and ++ * get_rev==0) ++ */ ++ struct { ++ uint64_t reserved_62_63:2; ++ /* ++ * Points to the next POW entry in the tag list when ++ * tail == 0 (and tag_type is not NULL or NULL_NULL). ++ */ ++ uint64_t link_index:11; ++ /* The POW entry attached to the core. */ ++ uint64_t index:11; ++ /* ++ * The group attached to the core (updated when new ++ * tag list entered on SWTAG_FULL). ++ */ ++ uint64_t grp:4; ++ /* ++ * Set when this POW entry is at the head of its tag ++ * list (also set when in the NULL or NULL_NULL ++ * state). ++ */ ++ uint64_t head:1; ++ /* ++ * Set when this POW entry is at the tail of its tag ++ * list (also set when in the NULL or NULL_NULL ++ * state). ++ */ ++ uint64_t tail:1; ++ /* ++ * The tag type attached to the core (updated when new ++ * tag list entered on SWTAG, SWTAG_FULL, or ++ * SWTAG_DESCHED). ++ */ ++ uint64_t tag_type:2; ++ /* ++ * The tag attached to the core (updated when new tag ++ * list entered on SWTAG, SWTAG_FULL, or ++ * SWTAG_DESCHED). ++ */ ++ uint64_t tag:32; ++ } s_sstatus2; ++ ++ /** ++ * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==1) ++ */ ++ struct { ++ uint64_t reserved_62_63:2; ++ /* ++ * Points to the prior POW entry in the tag list when ++ * head == 0 (and tag_type is not NULL or ++ * NULL_NULL). This field is unpredictable when the ++ * core's state is NULL or NULL_NULL. ++ */ ++ uint64_t revlink_index:11; ++ /* The POW entry attached to the core. */ ++ uint64_t index:11; ++ /* ++ * The group attached to the core (updated when new ++ * tag list entered on SWTAG_FULL). ++ */ ++ uint64_t grp:4; ++ /* Set when this POW entry is at the head of its tag ++ * list (also set when in the NULL or NULL_NULL ++ * state). ++ */ ++ uint64_t head:1; ++ /* ++ * Set when this POW entry is at the tail of its tag ++ * list (also set when in the NULL or NULL_NULL ++ * state). ++ */ ++ uint64_t tail:1; ++ /* ++ * The tag type attached to the core (updated when new ++ * tag list entered on SWTAG, SWTAG_FULL, or ++ * SWTAG_DESCHED). ++ */ ++ uint64_t tag_type:2; ++ /* ++ * The tag attached to the core (updated when new tag ++ * list entered on SWTAG, SWTAG_FULL, or ++ * SWTAG_DESCHED). ++ */ ++ uint64_t tag:32; ++ } s_sstatus3; ++ ++ /** ++ * Result for a POW Status Load (when get_cur==1, get_wqp==1, and ++ * get_rev==0) ++ */ ++ struct { ++ uint64_t reserved_62_63:2; ++ /* ++ * Points to the next POW entry in the tag list when ++ * tail == 0 (and tag_type is not NULL or NULL_NULL). ++ */ ++ uint64_t link_index:11; ++ /* The POW entry attached to the core. */ ++ uint64_t index:11; ++ /* ++ * The group attached to the core (updated when new ++ * tag list entered on SWTAG_FULL). ++ */ ++ uint64_t grp:4; ++ /* ++ * The wqp attached to the core (updated when new tag ++ * list entered on SWTAG_FULL). ++ */ ++ uint64_t wqp:36; ++ } s_sstatus4; ++ ++ /** ++ * Result for a POW Status Load (when get_cur==1, get_wqp==1, and ++ * get_rev==1) ++ */ ++ struct { ++ uint64_t reserved_62_63:2; ++ /* ++ * Points to the prior POW entry in the tag list when ++ * head == 0 (and tag_type is not NULL or ++ * NULL_NULL). This field is unpredictable when the ++ * core's state is NULL or NULL_NULL. ++ */ ++ uint64_t revlink_index:11; ++ /* The POW entry attached to the core. */ ++ uint64_t index:11; ++ /* ++ * The group attached to the core (updated when new ++ * tag list entered on SWTAG_FULL). ++ */ ++ uint64_t grp:4; ++ /* ++ * The wqp attached to the core (updated when new tag ++ * list entered on SWTAG_FULL). ++ */ ++ uint64_t wqp:36; ++ } s_sstatus5; ++ ++ /** ++ * Result For POW Memory Load (get_des == 0 and get_wqp == 0) ++ */ ++ struct { ++ uint64_t reserved_51_63:13; ++ /* ++ * The next entry in the input, free, descheduled_head ++ * list (unpredictable if entry is the tail of the ++ * list). ++ */ ++ uint64_t next_index:11; ++ /* The group of the POW entry. */ ++ uint64_t grp:4; ++ uint64_t reserved_35:1; ++ /* ++ * Set when this POW entry is at the tail of its tag ++ * list (also set when in the NULL or NULL_NULL ++ * state). ++ */ ++ uint64_t tail:1; ++ /* The tag type of the POW entry. */ ++ uint64_t tag_type:2; ++ /* The tag of the POW entry. */ ++ uint64_t tag:32; ++ } s_smemload0; ++ ++ /** ++ * Result For POW Memory Load (get_des == 0 and get_wqp == 1) ++ */ ++ struct { ++ uint64_t reserved_51_63:13; ++ /* ++ * The next entry in the input, free, descheduled_head ++ * list (unpredictable if entry is the tail of the ++ * list). ++ */ ++ uint64_t next_index:11; ++ /* The group of the POW entry. */ ++ uint64_t grp:4; ++ /* The WQP held in the POW entry. */ ++ uint64_t wqp:36; ++ } s_smemload1; ++ ++ /** ++ * Result For POW Memory Load (get_des == 1) ++ */ ++ struct { ++ uint64_t reserved_51_63:13; ++ /* ++ * The next entry in the tag list connected to the ++ * descheduled head. ++ */ ++ uint64_t fwd_index:11; ++ /* The group of the POW entry. */ ++ uint64_t grp:4; ++ /* The nosched bit for the POW entry. */ ++ uint64_t nosched:1; ++ /* There is a pending tag switch */ ++ uint64_t pend_switch:1; ++ /* ++ * The next tag type for the new tag list when ++ * pend_switch is set. ++ */ ++ uint64_t pend_type:2; ++ /* ++ * The next tag for the new tag list when pend_switch ++ * is set. ++ */ ++ uint64_t pend_tag:32; ++ } s_smemload2; ++ ++ /** ++ * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 0) ++ */ ++ struct { ++ uint64_t reserved_52_63:12; ++ /* ++ * set when there is one or more POW entries on the ++ * free list. ++ */ ++ uint64_t free_val:1; ++ /* ++ * set when there is exactly one POW entry on the free ++ * list. ++ */ ++ uint64_t free_one:1; ++ uint64_t reserved_49:1; ++ /* ++ * when free_val is set, indicates the first entry on ++ * the free list. ++ */ ++ uint64_t free_head:11; ++ uint64_t reserved_37:1; ++ /* ++ * when free_val is set, indicates the last entry on ++ * the free list. ++ */ ++ uint64_t free_tail:11; ++ /* ++ * set when there is one or more POW entries on the ++ * input Q list selected by qosgrp. ++ */ ++ uint64_t loc_val:1; ++ /* ++ * set when there is exactly one POW entry on the ++ * input Q list selected by qosgrp. ++ */ ++ uint64_t loc_one:1; ++ uint64_t reserved_23:1; ++ /* ++ * when loc_val is set, indicates the first entry on ++ * the input Q list selected by qosgrp. ++ */ ++ uint64_t loc_head:11; ++ uint64_t reserved_11:1; ++ /* ++ * when loc_val is set, indicates the last entry on ++ * the input Q list selected by qosgrp. ++ */ ++ uint64_t loc_tail:11; ++ } sindexload0; ++ ++ /** ++ * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 1) ++ */ ++ struct { ++ uint64_t reserved_52_63:12; ++ /* ++ * set when there is one or more POW entries on the ++ * nosched list. ++ */ ++ uint64_t nosched_val:1; ++ /* ++ * set when there is exactly one POW entry on the ++ * nosched list. ++ */ ++ uint64_t nosched_one:1; ++ uint64_t reserved_49:1; ++ /* ++ * when nosched_val is set, indicates the first entry ++ * on the nosched list. ++ */ ++ uint64_t nosched_head:11; ++ uint64_t reserved_37:1; ++ /* ++ * when nosched_val is set, indicates the last entry ++ * on the nosched list. ++ */ ++ uint64_t nosched_tail:11; ++ /* ++ * set when there is one or more descheduled heads on ++ * the descheduled list selected by qosgrp. ++ */ ++ uint64_t des_val:1; ++ /* ++ * set when there is exactly one descheduled head on ++ * the descheduled list selected by qosgrp. ++ */ ++ uint64_t des_one:1; ++ uint64_t reserved_23:1; ++ /* ++ * when des_val is set, indicates the first ++ * descheduled head on the descheduled list selected ++ * by qosgrp. ++ */ ++ uint64_t des_head:11; ++ uint64_t reserved_11:1; ++ /* ++ * when des_val is set, indicates the last descheduled ++ * head on the descheduled list selected by qosgrp. ++ */ ++ uint64_t des_tail:11; ++ } sindexload1; ++ ++ /** ++ * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 0) ++ */ ++ struct { ++ uint64_t reserved_39_63:25; ++ /* ++ * Set when this DRAM list is the current head ++ * (i.e. is the next to be reloaded when the POW ++ * hardware reloads a POW entry from DRAM). The POW ++ * hardware alternates between the two DRAM lists ++ * associated with a QOS level when it reloads work ++ * from DRAM into the POW unit. ++ */ ++ uint64_t rmt_is_head:1; ++ /* ++ * Set when the DRAM portion of the input Q list ++ * selected by qosgrp contains one or more pieces of ++ * work. ++ */ ++ uint64_t rmt_val:1; ++ /* ++ * Set when the DRAM portion of the input Q list ++ * selected by qosgrp contains exactly one piece of ++ * work. ++ */ ++ uint64_t rmt_one:1; ++ /* ++ * When rmt_val is set, indicates the first piece of ++ * work on the DRAM input Q list selected by ++ * qosgrp. ++ */ ++ uint64_t rmt_head:36; ++ } sindexload2; ++ ++ /** ++ * Result For POW Index/Pointer Load (get_rmt == ++ * 1/get_des_get_tail == 1) ++ */ ++ struct { ++ uint64_t reserved_39_63:25; ++ /* ++ * set when this DRAM list is the current head ++ * (i.e. is the next to be reloaded when the POW ++ * hardware reloads a POW entry from DRAM). The POW ++ * hardware alternates between the two DRAM lists ++ * associated with a QOS level when it reloads work ++ * from DRAM into the POW unit. ++ */ ++ uint64_t rmt_is_head:1; ++ /* ++ * set when the DRAM portion of the input Q list ++ * selected by qosgrp contains one or more pieces of ++ * work. ++ */ ++ uint64_t rmt_val:1; ++ /* ++ * set when the DRAM portion of the input Q list ++ * selected by qosgrp contains exactly one piece of ++ * work. ++ */ ++ uint64_t rmt_one:1; ++ /* ++ * when rmt_val is set, indicates the last piece of ++ * work on the DRAM input Q list selected by ++ * qosgrp. ++ */ ++ uint64_t rmt_tail:36; ++ } sindexload3; ++ ++ /** ++ * Response to NULL_RD request loads ++ */ ++ struct { ++ uint64_t unused:62; ++ /* of type cvmx_pow_tag_type_t. state is one of the ++ * following: ++ * ++ * - CVMX_POW_TAG_TYPE_ORDERED ++ * - CVMX_POW_TAG_TYPE_ATOMIC ++ * - CVMX_POW_TAG_TYPE_NULL ++ * - CVMX_POW_TAG_TYPE_NULL_NULL ++ */ ++ uint64_t state:2; ++ } s_null_rd; ++ ++} cvmx_pow_tag_load_resp_t; ++ ++/** ++ * This structure describes the address used for stores to the POW. ++ * The store address is meaningful on stores to the POW. The ++ * hardware assumes that an aligned 64-bit store was used for all ++ * these stores. Note the assumption that the work queue entry is ++ * aligned on an 8-byte boundary (since the low-order 3 address bits ++ * must be zero). Note that not all fields are used by all ++ * operations. ++ * ++ * NOTE: The following is the behavior of the pending switch bit at the PP ++ * for POW stores (i.e. when did<7:3> == 0xc) ++ * - did<2:0> == 0 => pending switch bit is set ++ * - did<2:0> == 1 => no affect on the pending switch bit ++ * - did<2:0> == 3 => pending switch bit is cleared ++ * - did<2:0> == 7 => no affect on the pending switch bit ++ * - did<2:0> == others => must not be used ++ * - No other loads/stores have an affect on the pending switch bit ++ * - The switch bus from POW can clear the pending switch bit ++ * ++ * NOTE: did<2:0> == 2 is used by the HW for a special single-cycle ++ * ADDWQ command that only contains the pointer). SW must never use ++ * did<2:0> == 2. ++ */ ++typedef union { ++ /** ++ * Unsigned 64 bit integer representation of store address ++ */ ++ uint64_t u64; ++ ++ struct { ++ /* Memory region. Should be CVMX_IO_SEG in most cases */ ++ uint64_t mem_reg:2; ++ uint64_t reserved_49_61:13; /* Must be zero */ ++ uint64_t is_io:1; /* Must be one */ ++ /* Device ID of POW. Note that different sub-dids are used. */ ++ uint64_t did:8; ++ uint64_t reserved_36_39:4; /* Must be zero */ ++ /* Address field. addr<2:0> must be zero */ ++ uint64_t addr:36; ++ } stag; ++} cvmx_pow_tag_store_addr_t; ++ ++/** ++ * decode of the store data when an IOBDMA SENDSINGLE is sent to POW ++ */ ++typedef union { ++ uint64_t u64; ++ ++ struct { ++ /* ++ * the (64-bit word) location in scratchpad to write ++ * to (if len != 0) ++ */ ++ uint64_t scraddr:8; ++ /* the number of words in the response (0 => no response) */ ++ uint64_t len:8; ++ /* the ID of the device on the non-coherent bus */ ++ uint64_t did:8; ++ uint64_t unused:36; ++ /* if set, don't return load response until work is available */ ++ uint64_t wait:1; ++ uint64_t unused2:3; ++ } s; ++ ++} cvmx_pow_iobdma_store_t; ++ ++/* CSR typedefs have been moved to cvmx-csr-*.h */ ++ ++/** ++ * Get the POW tag for this core. This returns the current ++ * tag type, tag, group, and POW entry index associated with ++ * this core. Index is only valid if the tag type isn't NULL_NULL. ++ * If a tag switch is pending this routine returns the tag before ++ * the tag switch, not after. ++ * ++ * Returns Current tag ++ */ ++static inline cvmx_pow_tag_req_t cvmx_pow_get_current_tag(void) ++{ ++ cvmx_pow_load_addr_t load_addr; ++ cvmx_pow_tag_load_resp_t load_resp; ++ cvmx_pow_tag_req_t result; ++ ++ load_addr.u64 = 0; ++ load_addr.sstatus.mem_region = CVMX_IO_SEG; ++ load_addr.sstatus.is_io = 1; ++ load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1; ++ load_addr.sstatus.coreid = cvmx_get_core_num(); ++ load_addr.sstatus.get_cur = 1; ++ load_resp.u64 = cvmx_read_csr(load_addr.u64); ++ result.u64 = 0; ++ result.s.grp = load_resp.s_sstatus2.grp; ++ result.s.index = load_resp.s_sstatus2.index; ++ result.s.type = load_resp.s_sstatus2.tag_type; ++ result.s.tag = load_resp.s_sstatus2.tag; ++ return result; ++} ++ ++/** ++ * Get the POW WQE for this core. This returns the work queue ++ * entry currently associated with this core. ++ * ++ * Returns WQE pointer ++ */ ++static inline cvmx_wqe_t *cvmx_pow_get_current_wqp(void) ++{ ++ cvmx_pow_load_addr_t load_addr; ++ cvmx_pow_tag_load_resp_t load_resp; ++ ++ load_addr.u64 = 0; ++ load_addr.sstatus.mem_region = CVMX_IO_SEG; ++ load_addr.sstatus.is_io = 1; ++ load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1; ++ load_addr.sstatus.coreid = cvmx_get_core_num(); ++ load_addr.sstatus.get_cur = 1; ++ load_addr.sstatus.get_wqp = 1; ++ load_resp.u64 = cvmx_read_csr(load_addr.u64); ++ return (cvmx_wqe_t *) cvmx_phys_to_ptr(load_resp.s_sstatus4.wqp); ++} ++ ++#ifndef CVMX_MF_CHORD ++#define CVMX_MF_CHORD(dest) CVMX_RDHWR(dest, 30) ++#endif ++ ++/** ++ * Print a warning if a tag switch is pending for this core ++ * ++ * @function: Function name checking for a pending tag switch ++ */ ++static inline void __cvmx_pow_warn_if_pending_switch(const char *function) ++{ ++ uint64_t switch_complete; ++ CVMX_MF_CHORD(switch_complete); ++ if (!switch_complete) ++ pr_warning("%s called with tag switch in progress\n", function); ++} ++ ++/** ++ * Waits for a tag switch to complete by polling the completion bit. ++ * Note that switches to NULL complete immediately and do not need ++ * to be waited for. ++ */ ++static inline void cvmx_pow_tag_sw_wait(void) ++{ ++ const uint64_t MAX_CYCLES = 1ull << 31; ++ uint64_t switch_complete; ++ uint64_t start_cycle = cvmx_get_cycle(); ++ while (1) { ++ CVMX_MF_CHORD(switch_complete); ++ if (unlikely(switch_complete)) ++ break; ++ if (unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES)) { ++ pr_warning("Tag switch is taking a long time, " ++ "possible deadlock\n"); ++ start_cycle = -MAX_CYCLES - 1; ++ } ++ } ++} ++ ++/** ++ * Synchronous work request. Requests work from the POW. ++ * This function does NOT wait for previous tag switches to complete, ++ * so the caller must ensure that there is not a pending tag switch. ++ * ++ * @wait: When set, call stalls until work becomes avaiable, or times out. ++ * If not set, returns immediately. ++ * ++ * Returns Returns the WQE pointer from POW. Returns NULL if no work ++ * was available. ++ */ ++static inline cvmx_wqe_t *cvmx_pow_work_request_sync_nocheck(cvmx_pow_wait_t ++ wait) ++{ ++ cvmx_pow_load_addr_t ptr; ++ cvmx_pow_tag_load_resp_t result; ++ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ ptr.u64 = 0; ++ ptr.swork.mem_region = CVMX_IO_SEG; ++ ptr.swork.is_io = 1; ++ ptr.swork.did = CVMX_OCT_DID_TAG_SWTAG; ++ ptr.swork.wait = wait; ++ ++ result.u64 = cvmx_read_csr(ptr.u64); ++ ++ if (result.s_work.no_work) ++ return NULL; ++ else ++ return (cvmx_wqe_t *) cvmx_phys_to_ptr(result.s_work.addr); ++} ++ ++/** ++ * Synchronous work request. Requests work from the POW. ++ * This function waits for any previous tag switch to complete before ++ * requesting the new work. ++ * ++ * @wait: When set, call stalls until work becomes avaiable, or times out. ++ * If not set, returns immediately. ++ * ++ * Returns Returns the WQE pointer from POW. Returns NULL if no work ++ * was available. ++ */ ++static inline cvmx_wqe_t *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait) ++{ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* Must not have a switch pending when requesting work */ ++ cvmx_pow_tag_sw_wait(); ++ return cvmx_pow_work_request_sync_nocheck(wait); ++ ++} ++ ++/** ++ * Synchronous null_rd request. Requests a switch out of NULL_NULL POW state. ++ * This function waits for any previous tag switch to complete before ++ * requesting the null_rd. ++ * ++ * Returns Returns the POW state of type cvmx_pow_tag_type_t. ++ */ ++static inline enum cvmx_pow_tag_type cvmx_pow_work_request_null_rd(void) ++{ ++ cvmx_pow_load_addr_t ptr; ++ cvmx_pow_tag_load_resp_t result; ++ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* Must not have a switch pending when requesting work */ ++ cvmx_pow_tag_sw_wait(); ++ ++ ptr.u64 = 0; ++ ptr.snull_rd.mem_region = CVMX_IO_SEG; ++ ptr.snull_rd.is_io = 1; ++ ptr.snull_rd.did = CVMX_OCT_DID_TAG_NULL_RD; ++ ++ result.u64 = cvmx_read_csr(ptr.u64); ++ ++ return (enum cvmx_pow_tag_type) result.s_null_rd.state; ++} ++ ++/** ++ * Asynchronous work request. Work is requested from the POW unit, ++ * and should later be checked with function ++ * cvmx_pow_work_response_async. This function does NOT wait for ++ * previous tag switches to complete, so the caller must ensure that ++ * there is not a pending tag switch. ++ * ++ * @scr_addr: Scratch memory address that response will be returned ++ * to, which is either a valid WQE, or a response with the ++ * invalid bit set. Byte address, must be 8 byte aligned. ++ * ++ * @wait: 1 to cause response to wait for work to become available (or ++ * timeout), 0 to cause response to return immediately ++ */ ++static inline void cvmx_pow_work_request_async_nocheck(int scr_addr, ++ cvmx_pow_wait_t wait) ++{ ++ cvmx_pow_iobdma_store_t data; ++ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* scr_addr must be 8 byte aligned */ ++ data.s.scraddr = scr_addr >> 3; ++ data.s.len = 1; ++ data.s.did = CVMX_OCT_DID_TAG_SWTAG; ++ data.s.wait = wait; ++ cvmx_send_single(data.u64); ++} ++ ++/** ++ * Asynchronous work request. Work is requested from the POW unit, ++ * and should later be checked with function ++ * cvmx_pow_work_response_async. This function waits for any previous ++ * tag switch to complete before requesting the new work. ++ * ++ * @scr_addr: Scratch memory address that response will be returned ++ * to, which is either a valid WQE, or a response with the ++ * invalid bit set. Byte address, must be 8 byte aligned. ++ * ++ * @wait: 1 to cause response to wait for work to become available (or ++ * timeout), 0 to cause response to return immediately ++ */ ++static inline void cvmx_pow_work_request_async(int scr_addr, ++ cvmx_pow_wait_t wait) ++{ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* Must not have a switch pending when requesting work */ ++ cvmx_pow_tag_sw_wait(); ++ cvmx_pow_work_request_async_nocheck(scr_addr, wait); ++} ++ ++/** ++ * Gets result of asynchronous work request. Performs a IOBDMA sync ++ * to wait for the response. ++ * ++ * @scr_addr: Scratch memory address to get result from Byte address, ++ * must be 8 byte aligned. ++ * ++ * Returns Returns the WQE from the scratch register, or NULL if no ++ * work was available. ++ */ ++static inline cvmx_wqe_t *cvmx_pow_work_response_async(int scr_addr) ++{ ++ cvmx_pow_tag_load_resp_t result; ++ ++ CVMX_SYNCIOBDMA; ++ result.u64 = cvmx_scratch_read64(scr_addr); ++ ++ if (result.s_work.no_work) ++ return NULL; ++ else ++ return (cvmx_wqe_t *) cvmx_phys_to_ptr(result.s_work.addr); ++} ++ ++/** ++ * Checks if a work queue entry pointer returned by a work ++ * request is valid. It may be invalid due to no work ++ * being available or due to a timeout. ++ * ++ * @wqe_ptr: pointer to a work queue entry returned by the POW ++ * ++ * Returns 0 if pointer is valid ++ * 1 if invalid (no work was returned) ++ */ ++static inline uint64_t cvmx_pow_work_invalid(cvmx_wqe_t *wqe_ptr) ++{ ++ return wqe_ptr == NULL; ++} ++ ++/** ++ * Starts a tag switch to the provided tag value and tag type. ++ * Completion for the tag switch must be checked for separately. This ++ * function does NOT update the work queue entry in dram to match tag ++ * value and type, so the application must keep track of these if they ++ * are important to the application. This tag switch command must not ++ * be used for switches to NULL, as the tag switch pending bit will be ++ * set by the switch request, but never cleared by the hardware. ++ * ++ * NOTE: This should not be used when switching from a NULL tag. Use ++ * cvmx_pow_tag_sw_full() instead. ++ * ++ * This function does no checks, so the caller must ensure that any ++ * previous tag switch has completed. ++ * ++ * @tag: new tag value ++ * @tag_type: new tag type (ordered or atomic) ++ */ ++static inline void cvmx_pow_tag_sw_nocheck(uint32_t tag, ++ enum cvmx_pow_tag_type tag_type) ++{ ++ cvmx_addr_t ptr; ++ cvmx_pow_tag_req_t tag_req; ++ ++ if (CVMX_ENABLE_POW_CHECKS) { ++ cvmx_pow_tag_req_t current_tag; ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ current_tag = cvmx_pow_get_current_tag(); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) ++ pr_warning("%s called with NULL_NULL tag\n", ++ __func__); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) ++ pr_warning("%s called with NULL tag\n", __func__); ++ if ((current_tag.s.type == tag_type) ++ && (current_tag.s.tag == tag)) ++ pr_warning("%s called to perform a tag switch to the " ++ "same tag\n", ++ __func__); ++ if (tag_type == CVMX_POW_TAG_TYPE_NULL) ++ pr_warning("%s called to perform a tag switch to " ++ "NULL. Use cvmx_pow_tag_sw_null() instead\n", ++ __func__); ++ } ++ ++ /* ++ * Note that WQE in DRAM is not updated here, as the POW does ++ * not read from DRAM once the WQE is in flight. See hardware ++ * manual for complete details. It is the application's ++ * responsibility to keep track of the current tag value if ++ * that is important. ++ */ ++ ++ tag_req.u64 = 0; ++ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG; ++ tag_req.s.tag = tag; ++ tag_req.s.type = tag_type; ++ ++ ptr.u64 = 0; ++ ptr.sio.mem_region = CVMX_IO_SEG; ++ ptr.sio.is_io = 1; ++ ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG; ++ ++ /* once this store arrives at POW, it will attempt the switch ++ software must wait for the switch to complete separately */ ++ cvmx_write_io(ptr.u64, tag_req.u64); ++} ++ ++/** ++ * Starts a tag switch to the provided tag value and tag type. ++ * Completion for the tag switch must be checked for separately. This ++ * function does NOT update the work queue entry in dram to match tag ++ * value and type, so the application must keep track of these if they ++ * are important to the application. This tag switch command must not ++ * be used for switches to NULL, as the tag switch pending bit will be ++ * set by the switch request, but never cleared by the hardware. ++ * ++ * NOTE: This should not be used when switching from a NULL tag. Use ++ * cvmx_pow_tag_sw_full() instead. ++ * ++ * This function waits for any previous tag switch to complete, and also ++ * displays an error on tag switches to NULL. ++ * ++ * @tag: new tag value ++ * @tag_type: new tag type (ordered or atomic) ++ */ ++static inline void cvmx_pow_tag_sw(uint32_t tag, ++ enum cvmx_pow_tag_type tag_type) ++{ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* ++ * Note that WQE in DRAM is not updated here, as the POW does ++ * not read from DRAM once the WQE is in flight. See hardware ++ * manual for complete details. It is the application's ++ * responsibility to keep track of the current tag value if ++ * that is important. ++ */ ++ ++ /* ++ * Ensure that there is not a pending tag switch, as a tag ++ * switch cannot be started if a previous switch is still ++ * pending. ++ */ ++ cvmx_pow_tag_sw_wait(); ++ cvmx_pow_tag_sw_nocheck(tag, tag_type); ++} ++ ++/** ++ * Starts a tag switch to the provided tag value and tag type. ++ * Completion for the tag switch must be checked for separately. This ++ * function does NOT update the work queue entry in dram to match tag ++ * value and type, so the application must keep track of these if they ++ * are important to the application. This tag switch command must not ++ * be used for switches to NULL, as the tag switch pending bit will be ++ * set by the switch request, but never cleared by the hardware. ++ * ++ * This function must be used for tag switches from NULL. ++ * ++ * This function does no checks, so the caller must ensure that any ++ * previous tag switch has completed. ++ * ++ * @wqp: pointer to work queue entry to submit. This entry is ++ * updated to match the other parameters ++ * @tag: tag value to be assigned to work queue entry ++ * @tag_type: type of tag ++ * @group: group value for the work queue entry. ++ */ ++static inline void cvmx_pow_tag_sw_full_nocheck(cvmx_wqe_t *wqp, uint32_t tag, ++ enum cvmx_pow_tag_type tag_type, ++ uint64_t group) ++{ ++ cvmx_addr_t ptr; ++ cvmx_pow_tag_req_t tag_req; ++ ++ if (CVMX_ENABLE_POW_CHECKS) { ++ cvmx_pow_tag_req_t current_tag; ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ current_tag = cvmx_pow_get_current_tag(); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) ++ pr_warning("%s called with NULL_NULL tag\n", ++ __func__); ++ if ((current_tag.s.type == tag_type) ++ && (current_tag.s.tag == tag)) ++ pr_warning("%s called to perform a tag switch to " ++ "the same tag\n", ++ __func__); ++ if (tag_type == CVMX_POW_TAG_TYPE_NULL) ++ pr_warning("%s called to perform a tag switch to " ++ "NULL. Use cvmx_pow_tag_sw_null() instead\n", ++ __func__); ++ if (wqp != cvmx_phys_to_ptr(0x80)) ++ if (wqp != cvmx_pow_get_current_wqp()) ++ pr_warning("%s passed WQE(%p) doesn't match " ++ "the address in the POW(%p)\n", ++ __func__, wqp, ++ cvmx_pow_get_current_wqp()); ++ } ++ ++ /* ++ * Note that WQE in DRAM is not updated here, as the POW does ++ * not read from DRAM once the WQE is in flight. See hardware ++ * manual for complete details. It is the application's ++ * responsibility to keep track of the current tag value if ++ * that is important. ++ */ ++ ++ tag_req.u64 = 0; ++ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_FULL; ++ tag_req.s.tag = tag; ++ tag_req.s.type = tag_type; ++ tag_req.s.grp = group; ++ ++ ptr.u64 = 0; ++ ptr.sio.mem_region = CVMX_IO_SEG; ++ ptr.sio.is_io = 1; ++ ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG; ++ ptr.sio.offset = CAST64(wqp); ++ ++ /* ++ * once this store arrives at POW, it will attempt the switch ++ * software must wait for the switch to complete separately. ++ */ ++ cvmx_write_io(ptr.u64, tag_req.u64); ++} ++ ++/** ++ * Starts a tag switch to the provided tag value and tag type. ++ * Completion for the tag switch must be checked for separately. This ++ * function does NOT update the work queue entry in dram to match tag ++ * value and type, so the application must keep track of these if they ++ * are important to the application. This tag switch command must not ++ * be used for switches to NULL, as the tag switch pending bit will be ++ * set by the switch request, but never cleared by the hardware. ++ * ++ * This function must be used for tag switches from NULL. ++ * ++ * This function waits for any pending tag switches to complete ++ * before requesting the tag switch. ++ * ++ * @wqp: pointer to work queue entry to submit. This entry is updated ++ * to match the other parameters ++ * @tag: tag value to be assigned to work queue entry ++ * @tag_type: type of tag ++ * @group: group value for the work queue entry. ++ */ ++static inline void cvmx_pow_tag_sw_full(cvmx_wqe_t *wqp, uint32_t tag, ++ enum cvmx_pow_tag_type tag_type, ++ uint64_t group) ++{ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* ++ * Ensure that there is not a pending tag switch, as a tag ++ * switch cannot be started if a previous switch is still ++ * pending. ++ */ ++ cvmx_pow_tag_sw_wait(); ++ cvmx_pow_tag_sw_full_nocheck(wqp, tag, tag_type, group); ++} ++ ++/** ++ * Switch to a NULL tag, which ends any ordering or ++ * synchronization provided by the POW for the current ++ * work queue entry. This operation completes immediatly, ++ * so completetion should not be waited for. ++ * This function does NOT wait for previous tag switches to complete, ++ * so the caller must ensure that any previous tag switches have completed. ++ */ ++static inline void cvmx_pow_tag_sw_null_nocheck(void) ++{ ++ cvmx_addr_t ptr; ++ cvmx_pow_tag_req_t tag_req; ++ ++ if (CVMX_ENABLE_POW_CHECKS) { ++ cvmx_pow_tag_req_t current_tag; ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ current_tag = cvmx_pow_get_current_tag(); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) ++ pr_warning("%s called with NULL_NULL tag\n", ++ __func__); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) ++ pr_warning("%s called when we already have a " ++ "NULL tag\n", ++ __func__); ++ } ++ ++ tag_req.u64 = 0; ++ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG; ++ tag_req.s.type = CVMX_POW_TAG_TYPE_NULL; ++ ++ ptr.u64 = 0; ++ ptr.sio.mem_region = CVMX_IO_SEG; ++ ptr.sio.is_io = 1; ++ ptr.sio.did = CVMX_OCT_DID_TAG_TAG1; ++ ++ cvmx_write_io(ptr.u64, tag_req.u64); ++ ++ /* switch to NULL completes immediately */ ++} ++ ++/** ++ * Switch to a NULL tag, which ends any ordering or ++ * synchronization provided by the POW for the current ++ * work queue entry. This operation completes immediatly, ++ * so completetion should not be waited for. ++ * This function waits for any pending tag switches to complete ++ * before requesting the switch to NULL. ++ */ ++static inline void cvmx_pow_tag_sw_null(void) ++{ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* ++ * Ensure that there is not a pending tag switch, as a tag ++ * switch cannot be started if a previous switch is still ++ * pending. ++ */ ++ cvmx_pow_tag_sw_wait(); ++ cvmx_pow_tag_sw_null_nocheck(); ++ ++ /* switch to NULL completes immediately */ ++} ++ ++/** ++ * Submits work to an input queue. This function updates the work ++ * queue entry in DRAM to match the arguments given. Note that the ++ * tag provided is for the work queue entry submitted, and is ++ * unrelated to the tag that the core currently holds. ++ * ++ * @wqp: pointer to work queue entry to submit. This entry is ++ * updated to match the other parameters ++ * @tag: tag value to be assigned to work queue entry ++ * @tag_type: type of tag ++ * @qos: Input queue to add to. ++ * @grp: group value for the work queue entry. ++ */ ++static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag, ++ enum cvmx_pow_tag_type tag_type, ++ uint64_t qos, uint64_t grp) ++{ ++ cvmx_addr_t ptr; ++ cvmx_pow_tag_req_t tag_req; ++ ++ wqp->qos = qos; ++ wqp->tag = tag; ++ wqp->tag_type = tag_type; ++ wqp->grp = grp; ++ ++ tag_req.u64 = 0; ++ tag_req.s.op = CVMX_POW_TAG_OP_ADDWQ; ++ tag_req.s.type = tag_type; ++ tag_req.s.tag = tag; ++ tag_req.s.qos = qos; ++ tag_req.s.grp = grp; ++ ++ ptr.u64 = 0; ++ ptr.sio.mem_region = CVMX_IO_SEG; ++ ptr.sio.is_io = 1; ++ ptr.sio.did = CVMX_OCT_DID_TAG_TAG1; ++ ptr.sio.offset = cvmx_ptr_to_phys(wqp); ++ ++ /* ++ * SYNC write to memory before the work submit. This is ++ * necessary as POW may read values from DRAM at this time. ++ */ ++ CVMX_SYNCWS; ++ cvmx_write_io(ptr.u64, tag_req.u64); ++} ++ ++/** ++ * This function sets the group mask for a core. The group mask ++ * indicates which groups each core will accept work from. There are ++ * 16 groups. ++ * ++ * @core_num: core to apply mask to ++ * @mask: Group mask. There are 16 groups, so only bits 0-15 are valid, ++ * representing groups 0-15. ++ * Each 1 bit in the mask enables the core to accept work from ++ * the corresponding group. ++ */ ++static inline void cvmx_pow_set_group_mask(uint64_t core_num, uint64_t mask) ++{ ++ union cvmx_pow_pp_grp_mskx grp_msk; ++ ++ grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num)); ++ grp_msk.s.grp_msk = mask; ++ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64); ++} ++ ++/** ++ * This function sets POW static priorities for a core. Each input queue has ++ * an associated priority value. ++ * ++ * @core_num: core to apply priorities to ++ * @priority: Vector of 8 priorities, one per POW Input Queue (0-7). ++ * Highest priority is 0 and lowest is 7. A priority value ++ * of 0xF instructs POW to skip the Input Queue when ++ * scheduling to this specific core. ++ * NOTE: priorities should not have gaps in values, meaning ++ * {0,1,1,1,1,1,1,1} is a valid configuration while ++ * {0,2,2,2,2,2,2,2} is not. ++ */ ++static inline void cvmx_pow_set_priority(uint64_t core_num, ++ const uint8_t priority[]) ++{ ++ /* POW priorities are supported on CN5xxx and later */ ++ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ union cvmx_pow_pp_grp_mskx grp_msk; ++ ++ grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num)); ++ grp_msk.s.qos0_pri = priority[0]; ++ grp_msk.s.qos1_pri = priority[1]; ++ grp_msk.s.qos2_pri = priority[2]; ++ grp_msk.s.qos3_pri = priority[3]; ++ grp_msk.s.qos4_pri = priority[4]; ++ grp_msk.s.qos5_pri = priority[5]; ++ grp_msk.s.qos6_pri = priority[6]; ++ grp_msk.s.qos7_pri = priority[7]; ++ ++ /* Detect gaps between priorities and flag error */ ++ { ++ int i; ++ uint32_t prio_mask = 0; ++ ++ for (i = 0; i < 8; i++) ++ if (priority[i] != 0xF) ++ prio_mask |= 1 << priority[i]; ++ ++ if (prio_mask ^ ((1 << cvmx_pop(prio_mask)) - 1)) { ++ pr_err("POW static priorities should be " ++ "contiguous (0x%llx)\n", ++ (unsigned long long)prio_mask); ++ return; ++ } ++ } ++ ++ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64); ++ } ++} ++ ++/** ++ * Performs a tag switch and then an immediate deschedule. This completes ++ * immediatly, so completion must not be waited for. This function does NOT ++ * update the wqe in DRAM to match arguments. ++ * ++ * This function does NOT wait for any prior tag switches to complete, so the ++ * calling code must do this. ++ * ++ * Note the following CAVEAT of the Octeon HW behavior when ++ * re-scheduling DE-SCHEDULEd items whose (next) state is ++ * ORDERED: ++ * - If there are no switches pending at the time that the ++ * HW executes the de-schedule, the HW will only re-schedule ++ * the head of the FIFO associated with the given tag. This ++ * means that in many respects, the HW treats this ORDERED ++ * tag as an ATOMIC tag. Note that in the SWTAG_DESCH ++ * case (to an ORDERED tag), the HW will do the switch ++ * before the deschedule whenever it is possible to do ++ * the switch immediately, so it may often look like ++ * this case. ++ * - If there is a pending switch to ORDERED at the time ++ * the HW executes the de-schedule, the HW will perform ++ * the switch at the time it re-schedules, and will be ++ * able to reschedule any/all of the entries with the ++ * same tag. ++ * Due to this behavior, the RECOMMENDATION to software is ++ * that they have a (next) state of ATOMIC when they ++ * DE-SCHEDULE. If an ORDERED tag is what was really desired, ++ * SW can choose to immediately switch to an ORDERED tag ++ * after the work (that has an ATOMIC tag) is re-scheduled. ++ * Note that since there are never any tag switches pending ++ * when the HW re-schedules, this switch can be IMMEDIATE upon ++ * the reception of the pointer during the re-schedule. ++ * ++ * @tag: New tag value ++ * @tag_type: New tag type ++ * @group: New group value ++ * @no_sched: Control whether this work queue entry will be rescheduled. ++ * - 1 : don't schedule this work ++ * - 0 : allow this work to be scheduled. ++ */ ++static inline void cvmx_pow_tag_sw_desched_nocheck( ++ uint32_t tag, ++ enum cvmx_pow_tag_type tag_type, ++ uint64_t group, ++ uint64_t no_sched) ++{ ++ cvmx_addr_t ptr; ++ cvmx_pow_tag_req_t tag_req; ++ ++ if (CVMX_ENABLE_POW_CHECKS) { ++ cvmx_pow_tag_req_t current_tag; ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ current_tag = cvmx_pow_get_current_tag(); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) ++ pr_warning("%s called with NULL_NULL tag\n", ++ __func__); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) ++ pr_warning("%s called with NULL tag. Deschedule not " ++ "allowed from NULL state\n", ++ __func__); ++ if ((current_tag.s.type != CVMX_POW_TAG_TYPE_ATOMIC) ++ && (tag_type != CVMX_POW_TAG_TYPE_ATOMIC)) ++ pr_warning("%s called where neither the before or " ++ "after tag is ATOMIC\n", ++ __func__); ++ } ++ ++ tag_req.u64 = 0; ++ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_DESCH; ++ tag_req.s.tag = tag; ++ tag_req.s.type = tag_type; ++ tag_req.s.grp = group; ++ tag_req.s.no_sched = no_sched; ++ ++ ptr.u64 = 0; ++ ptr.sio.mem_region = CVMX_IO_SEG; ++ ptr.sio.is_io = 1; ++ ptr.sio.did = CVMX_OCT_DID_TAG_TAG3; ++ /* ++ * since TAG3 is used, this store will clear the local pending ++ * switch bit. ++ */ ++ cvmx_write_io(ptr.u64, tag_req.u64); ++} ++ ++/** ++ * Performs a tag switch and then an immediate deschedule. This completes ++ * immediatly, so completion must not be waited for. This function does NOT ++ * update the wqe in DRAM to match arguments. ++ * ++ * This function waits for any prior tag switches to complete, so the ++ * calling code may call this function with a pending tag switch. ++ * ++ * Note the following CAVEAT of the Octeon HW behavior when ++ * re-scheduling DE-SCHEDULEd items whose (next) state is ++ * ORDERED: ++ * - If there are no switches pending at the time that the ++ * HW executes the de-schedule, the HW will only re-schedule ++ * the head of the FIFO associated with the given tag. This ++ * means that in many respects, the HW treats this ORDERED ++ * tag as an ATOMIC tag. Note that in the SWTAG_DESCH ++ * case (to an ORDERED tag), the HW will do the switch ++ * before the deschedule whenever it is possible to do ++ * the switch immediately, so it may often look like ++ * this case. ++ * - If there is a pending switch to ORDERED at the time ++ * the HW executes the de-schedule, the HW will perform ++ * the switch at the time it re-schedules, and will be ++ * able to reschedule any/all of the entries with the ++ * same tag. ++ * Due to this behavior, the RECOMMENDATION to software is ++ * that they have a (next) state of ATOMIC when they ++ * DE-SCHEDULE. If an ORDERED tag is what was really desired, ++ * SW can choose to immediately switch to an ORDERED tag ++ * after the work (that has an ATOMIC tag) is re-scheduled. ++ * Note that since there are never any tag switches pending ++ * when the HW re-schedules, this switch can be IMMEDIATE upon ++ * the reception of the pointer during the re-schedule. ++ * ++ * @tag: New tag value ++ * @tag_type: New tag type ++ * @group: New group value ++ * @no_sched: Control whether this work queue entry will be rescheduled. ++ * - 1 : don't schedule this work ++ * - 0 : allow this work to be scheduled. ++ */ ++static inline void cvmx_pow_tag_sw_desched(uint32_t tag, ++ enum cvmx_pow_tag_type tag_type, ++ uint64_t group, uint64_t no_sched) ++{ ++ if (CVMX_ENABLE_POW_CHECKS) ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ ++ /* Need to make sure any writes to the work queue entry are complete */ ++ CVMX_SYNCWS; ++ /* ++ * Ensure that there is not a pending tag switch, as a tag ++ * switch cannot be started if a previous switch is still ++ * pending. ++ */ ++ cvmx_pow_tag_sw_wait(); ++ cvmx_pow_tag_sw_desched_nocheck(tag, tag_type, group, no_sched); ++} ++ ++/** ++ * Descchedules the current work queue entry. ++ * ++ * @no_sched: no schedule flag value to be set on the work queue ++ * entry. If this is set the entry will not be ++ * rescheduled. ++ */ ++static inline void cvmx_pow_desched(uint64_t no_sched) ++{ ++ cvmx_addr_t ptr; ++ cvmx_pow_tag_req_t tag_req; ++ ++ if (CVMX_ENABLE_POW_CHECKS) { ++ cvmx_pow_tag_req_t current_tag; ++ __cvmx_pow_warn_if_pending_switch(__func__); ++ current_tag = cvmx_pow_get_current_tag(); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) ++ pr_warning("%s called with NULL_NULL tag\n", ++ __func__); ++ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) ++ pr_warning("%s called with NULL tag. Deschedule not " ++ "expected from NULL state\n", ++ __func__); ++ } ++ ++ /* Need to make sure any writes to the work queue entry are complete */ ++ CVMX_SYNCWS; ++ ++ tag_req.u64 = 0; ++ tag_req.s.op = CVMX_POW_TAG_OP_DESCH; ++ tag_req.s.no_sched = no_sched; ++ ++ ptr.u64 = 0; ++ ptr.sio.mem_region = CVMX_IO_SEG; ++ ptr.sio.is_io = 1; ++ ptr.sio.did = CVMX_OCT_DID_TAG_TAG3; ++ /* ++ * since TAG3 is used, this store will clear the local pending ++ * switch bit. ++ */ ++ cvmx_write_io(ptr.u64, tag_req.u64); ++} ++ ++/**************************************************** ++* Define usage of bits within the 32 bit tag values. ++*****************************************************/ ++ ++/* ++ * Number of bits of the tag used by software. The SW bits are always ++ * a contiguous block of the high starting at bit 31. The hardware ++ * bits are always the low bits. By default, the top 8 bits of the ++ * tag are reserved for software, and the low 24 are set by the IPD ++ * unit. ++ */ ++#define CVMX_TAG_SW_BITS (8) ++#define CVMX_TAG_SW_SHIFT (32 - CVMX_TAG_SW_BITS) ++ ++/* Below is the list of values for the top 8 bits of the tag. */ ++/* ++ * Tag values with top byte of this value are reserved for internal ++ * executive uses. ++ */ ++#define CVMX_TAG_SW_BITS_INTERNAL 0x1 ++/* The executive divides the remaining 24 bits as follows: ++ * - the upper 8 bits (bits 23 - 16 of the tag) define a subgroup ++ * ++ * - the lower 16 bits (bits 15 - 0 of the tag) define are the value ++ * with the subgroup ++ * ++ * Note that this section describes the format of tags generated by ++ * software - refer to the hardware documentation for a description of ++ * the tags values generated by the packet input hardware. Subgroups ++ * are defined here. ++ */ ++/* Mask for the value portion of the tag */ ++#define CVMX_TAG_SUBGROUP_MASK 0xFFFF ++#define CVMX_TAG_SUBGROUP_SHIFT 16 ++#define CVMX_TAG_SUBGROUP_PKO 0x1 ++ ++/* End of executive tag subgroup definitions */ ++ ++/* ++ * The remaining values software bit values 0x2 - 0xff are available ++ * for application use. ++ */ ++ ++/** ++ * This function creates a 32 bit tag value from the two values provided. ++ * ++ * @sw_bits: The upper bits (number depends on configuration) are set ++ * to this value. The remainder of bits are set by the ++ * hw_bits parameter. ++ * ++ * @hw_bits: The lower bits (number depends on configuration) are set ++ * to this value. The remainder of bits are set by the ++ * sw_bits parameter. ++ * ++ * Returns 32 bit value of the combined hw and sw bits. ++ */ ++static inline uint32_t cvmx_pow_tag_compose(uint64_t sw_bits, uint64_t hw_bits) ++{ ++ return ((sw_bits & cvmx_build_mask(CVMX_TAG_SW_BITS)) << ++ CVMX_TAG_SW_SHIFT) | ++ (hw_bits & cvmx_build_mask(32 - CVMX_TAG_SW_BITS)); ++} ++ ++/** ++ * Extracts the bits allocated for software use from the tag ++ * ++ * @tag: 32 bit tag value ++ * ++ * Returns N bit software tag value, where N is configurable with the ++ * CVMX_TAG_SW_BITS define ++ */ ++static inline uint32_t cvmx_pow_tag_get_sw_bits(uint64_t tag) ++{ ++ return (tag >> (32 - CVMX_TAG_SW_BITS)) & ++ cvmx_build_mask(CVMX_TAG_SW_BITS); ++} ++ ++/** ++ * ++ * Extracts the bits allocated for hardware use from the tag ++ * ++ * @tag: 32 bit tag value ++ * ++ * Returns (32 - N) bit software tag value, where N is configurable ++ * with the CVMX_TAG_SW_BITS define ++ */ ++static inline uint32_t cvmx_pow_tag_get_hw_bits(uint64_t tag) ++{ ++ return tag & cvmx_build_mask(32 - CVMX_TAG_SW_BITS); ++} ++ ++/** ++ * Store the current POW internal state into the supplied ++ * buffer. It is recommended that you pass a buffer of at least ++ * 128KB. The format of the capture may change based on SDK ++ * version and Octeon chip. ++ * ++ * @buffer: Buffer to store capture into ++ * @buffer_size: ++ * The size of the supplied buffer ++ * ++ * Returns Zero on sucess, negative on failure ++ */ ++extern int cvmx_pow_capture(void *buffer, int buffer_size); ++ ++/** ++ * Dump a POW capture to the console in a human readable format. ++ * ++ * @buffer: POW capture from cvmx_pow_capture() ++ * @buffer_size: ++ * Size of the buffer ++ */ ++extern void cvmx_pow_display(void *buffer, int buffer_size); ++ ++/** ++ * Return the number of POW entries supported by this chip ++ * ++ * Returns Number of POW entries ++ */ ++extern int cvmx_pow_get_num_entries(void); ++ ++#endif /* __CVMX_POW_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-scratch.h +@@ -0,0 +1,139 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * This file provides support for the processor local scratch memory. ++ * Scratch memory is byte addressable - all addresses are byte addresses. ++ * ++ */ ++ ++#ifndef __CVMX_SCRATCH_H__ ++#define __CVMX_SCRATCH_H__ ++ ++/* ++ * Note: This define must be a long, not a long long in order to ++ * compile without warnings for both 32bit and 64bit. ++ */ ++#define CVMX_SCRATCH_BASE (-32768l) /* 0xffffffffffff8000 */ ++ ++/** ++ * Reads an 8 bit value from the processor local scratchpad memory. ++ * ++ * @address: byte address to read from ++ * ++ * Returns value read ++ */ ++static inline uint8_t cvmx_scratch_read8(uint64_t address) ++{ ++ return *CASTPTR(volatile uint8_t, CVMX_SCRATCH_BASE + address); ++} ++ ++/** ++ * Reads a 16 bit value from the processor local scratchpad memory. ++ * ++ * @address: byte address to read from ++ * ++ * Returns value read ++ */ ++static inline uint16_t cvmx_scratch_read16(uint64_t address) ++{ ++ return *CASTPTR(volatile uint16_t, CVMX_SCRATCH_BASE + address); ++} ++ ++/** ++ * Reads a 32 bit value from the processor local scratchpad memory. ++ * ++ * @address: byte address to read from ++ * ++ * Returns value read ++ */ ++static inline uint32_t cvmx_scratch_read32(uint64_t address) ++{ ++ return *CASTPTR(volatile uint32_t, CVMX_SCRATCH_BASE + address); ++} ++ ++/** ++ * Reads a 64 bit value from the processor local scratchpad memory. ++ * ++ * @address: byte address to read from ++ * ++ * Returns value read ++ */ ++static inline uint64_t cvmx_scratch_read64(uint64_t address) ++{ ++ return *CASTPTR(volatile uint64_t, CVMX_SCRATCH_BASE + address); ++} ++ ++/** ++ * Writes an 8 bit value to the processor local scratchpad memory. ++ * ++ * @address: byte address to write to ++ * @value: value to write ++ */ ++static inline void cvmx_scratch_write8(uint64_t address, uint64_t value) ++{ ++ *CASTPTR(volatile uint8_t, CVMX_SCRATCH_BASE + address) = ++ (uint8_t) value; ++} ++ ++/** ++ * Writes a 32 bit value to the processor local scratchpad memory. ++ * ++ * @address: byte address to write to ++ * @value: value to write ++ */ ++static inline void cvmx_scratch_write16(uint64_t address, uint64_t value) ++{ ++ *CASTPTR(volatile uint16_t, CVMX_SCRATCH_BASE + address) = ++ (uint16_t) value; ++} ++ ++/** ++ * Writes a 16 bit value to the processor local scratchpad memory. ++ * ++ * @address: byte address to write to ++ * @value: value to write ++ */ ++static inline void cvmx_scratch_write32(uint64_t address, uint64_t value) ++{ ++ *CASTPTR(volatile uint32_t, CVMX_SCRATCH_BASE + address) = ++ (uint32_t) value; ++} ++ ++/** ++ * Writes a 64 bit value to the processor local scratchpad memory. ++ * ++ * @address: byte address to write to ++ * @value: value to write ++ */ ++static inline void cvmx_scratch_write64(uint64_t address, uint64_t value) ++{ ++ *CASTPTR(volatile uint64_t, CVMX_SCRATCH_BASE + address) = value; ++} ++ ++#endif /* __CVMX_SCRATCH_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-smix-defs.h +@@ -0,0 +1,178 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_SMIX_DEFS_H__ ++#define __CVMX_SMIX_DEFS_H__ ++ ++#define CVMX_SMIX_CLK(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_CMD(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_EN(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_RD_DAT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256)) ++#define CVMX_SMIX_WR_DAT(offset) \ ++ CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256)) ++ ++union cvmx_smix_clk { ++ uint64_t u64; ++ struct cvmx_smix_clk_s { ++ uint64_t reserved_25_63:39; ++ uint64_t mode:1; ++ uint64_t reserved_21_23:3; ++ uint64_t sample_hi:5; ++ uint64_t sample_mode:1; ++ uint64_t reserved_14_14:1; ++ uint64_t clk_idle:1; ++ uint64_t preamble:1; ++ uint64_t sample:4; ++ uint64_t phase:8; ++ } s; ++ struct cvmx_smix_clk_cn30xx { ++ uint64_t reserved_21_63:43; ++ uint64_t sample_hi:5; ++ uint64_t reserved_14_15:2; ++ uint64_t clk_idle:1; ++ uint64_t preamble:1; ++ uint64_t sample:4; ++ uint64_t phase:8; ++ } cn30xx; ++ struct cvmx_smix_clk_cn30xx cn31xx; ++ struct cvmx_smix_clk_cn30xx cn38xx; ++ struct cvmx_smix_clk_cn30xx cn38xxp2; ++ struct cvmx_smix_clk_cn50xx { ++ uint64_t reserved_25_63:39; ++ uint64_t mode:1; ++ uint64_t reserved_21_23:3; ++ uint64_t sample_hi:5; ++ uint64_t reserved_14_15:2; ++ uint64_t clk_idle:1; ++ uint64_t preamble:1; ++ uint64_t sample:4; ++ uint64_t phase:8; ++ } cn50xx; ++ struct cvmx_smix_clk_s cn52xx; ++ struct cvmx_smix_clk_cn50xx cn52xxp1; ++ struct cvmx_smix_clk_s cn56xx; ++ struct cvmx_smix_clk_cn50xx cn56xxp1; ++ struct cvmx_smix_clk_cn30xx cn58xx; ++ struct cvmx_smix_clk_cn30xx cn58xxp1; ++}; ++ ++union cvmx_smix_cmd { ++ uint64_t u64; ++ struct cvmx_smix_cmd_s { ++ uint64_t reserved_18_63:46; ++ uint64_t phy_op:2; ++ uint64_t reserved_13_15:3; ++ uint64_t phy_adr:5; ++ uint64_t reserved_5_7:3; ++ uint64_t reg_adr:5; ++ } s; ++ struct cvmx_smix_cmd_cn30xx { ++ uint64_t reserved_17_63:47; ++ uint64_t phy_op:1; ++ uint64_t reserved_13_15:3; ++ uint64_t phy_adr:5; ++ uint64_t reserved_5_7:3; ++ uint64_t reg_adr:5; ++ } cn30xx; ++ struct cvmx_smix_cmd_cn30xx cn31xx; ++ struct cvmx_smix_cmd_cn30xx cn38xx; ++ struct cvmx_smix_cmd_cn30xx cn38xxp2; ++ struct cvmx_smix_cmd_s cn50xx; ++ struct cvmx_smix_cmd_s cn52xx; ++ struct cvmx_smix_cmd_s cn52xxp1; ++ struct cvmx_smix_cmd_s cn56xx; ++ struct cvmx_smix_cmd_s cn56xxp1; ++ struct cvmx_smix_cmd_cn30xx cn58xx; ++ struct cvmx_smix_cmd_cn30xx cn58xxp1; ++}; ++ ++union cvmx_smix_en { ++ uint64_t u64; ++ struct cvmx_smix_en_s { ++ uint64_t reserved_1_63:63; ++ uint64_t en:1; ++ } s; ++ struct cvmx_smix_en_s cn30xx; ++ struct cvmx_smix_en_s cn31xx; ++ struct cvmx_smix_en_s cn38xx; ++ struct cvmx_smix_en_s cn38xxp2; ++ struct cvmx_smix_en_s cn50xx; ++ struct cvmx_smix_en_s cn52xx; ++ struct cvmx_smix_en_s cn52xxp1; ++ struct cvmx_smix_en_s cn56xx; ++ struct cvmx_smix_en_s cn56xxp1; ++ struct cvmx_smix_en_s cn58xx; ++ struct cvmx_smix_en_s cn58xxp1; ++}; ++ ++union cvmx_smix_rd_dat { ++ uint64_t u64; ++ struct cvmx_smix_rd_dat_s { ++ uint64_t reserved_18_63:46; ++ uint64_t pending:1; ++ uint64_t val:1; ++ uint64_t dat:16; ++ } s; ++ struct cvmx_smix_rd_dat_s cn30xx; ++ struct cvmx_smix_rd_dat_s cn31xx; ++ struct cvmx_smix_rd_dat_s cn38xx; ++ struct cvmx_smix_rd_dat_s cn38xxp2; ++ struct cvmx_smix_rd_dat_s cn50xx; ++ struct cvmx_smix_rd_dat_s cn52xx; ++ struct cvmx_smix_rd_dat_s cn52xxp1; ++ struct cvmx_smix_rd_dat_s cn56xx; ++ struct cvmx_smix_rd_dat_s cn56xxp1; ++ struct cvmx_smix_rd_dat_s cn58xx; ++ struct cvmx_smix_rd_dat_s cn58xxp1; ++}; ++ ++union cvmx_smix_wr_dat { ++ uint64_t u64; ++ struct cvmx_smix_wr_dat_s { ++ uint64_t reserved_18_63:46; ++ uint64_t pending:1; ++ uint64_t val:1; ++ uint64_t dat:16; ++ } s; ++ struct cvmx_smix_wr_dat_s cn30xx; ++ struct cvmx_smix_wr_dat_s cn31xx; ++ struct cvmx_smix_wr_dat_s cn38xx; ++ struct cvmx_smix_wr_dat_s cn38xxp2; ++ struct cvmx_smix_wr_dat_s cn50xx; ++ struct cvmx_smix_wr_dat_s cn52xx; ++ struct cvmx_smix_wr_dat_s cn52xxp1; ++ struct cvmx_smix_wr_dat_s cn56xx; ++ struct cvmx_smix_wr_dat_s cn56xxp1; ++ struct cvmx_smix_wr_dat_s cn58xx; ++ struct cvmx_smix_wr_dat_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-spi.c +@@ -0,0 +1,667 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * Support library for the SPI ++ */ ++#include ++ ++#include "cvmx-config.h" ++ ++#include "cvmx-pko.h" ++#include "cvmx-spi.h" ++ ++#include "cvmx-spxx-defs.h" ++#include "cvmx-stxx-defs.h" ++#include "cvmx-srxx-defs.h" ++ ++#define INVOKE_CB(function_p, args...) \ ++ do { \ ++ if (function_p) { \ ++ res = function_p(args); \ ++ if (res) \ ++ return res; \ ++ } \ ++ } while (0) ++ ++#if CVMX_ENABLE_DEBUG_PRINTS ++static const char *modes[] = ++ { "UNKNOWN", "TX Halfplex", "Rx Halfplex", "Duplex" }; ++#endif ++ ++/* Default callbacks, can be overridden ++ * using cvmx_spi_get_callbacks/cvmx_spi_set_callbacks ++ */ ++static cvmx_spi_callbacks_t cvmx_spi_callbacks = { ++ .reset_cb = cvmx_spi_reset_cb, ++ .calendar_setup_cb = cvmx_spi_calendar_setup_cb, ++ .clock_detect_cb = cvmx_spi_clock_detect_cb, ++ .training_cb = cvmx_spi_training_cb, ++ .calendar_sync_cb = cvmx_spi_calendar_sync_cb, ++ .interface_up_cb = cvmx_spi_interface_up_cb ++}; ++ ++/** ++ * Get current SPI4 initialization callbacks ++ * ++ * @callbacks: Pointer to the callbacks structure.to fill ++ * ++ * Returns Pointer to cvmx_spi_callbacks_t structure. ++ */ ++void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks) ++{ ++ memcpy(callbacks, &cvmx_spi_callbacks, sizeof(cvmx_spi_callbacks)); ++} ++ ++/** ++ * Set new SPI4 initialization callbacks ++ * ++ * @new_callbacks: Pointer to an updated callbacks structure. ++ */ ++void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks) ++{ ++ memcpy(&cvmx_spi_callbacks, new_callbacks, sizeof(cvmx_spi_callbacks)); ++} ++ ++/** ++ * Initialize and start the SPI interface. ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for clock synchronization in seconds ++ * @num_ports: Number of SPI ports to configure ++ * ++ * Returns Zero on success, negative of failure. ++ */ ++int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode, int timeout, ++ int num_ports) ++{ ++ int res = -1; ++ ++ if (!(OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))) ++ return res; ++ ++ /* Callback to perform SPI4 reset */ ++ INVOKE_CB(cvmx_spi_callbacks.reset_cb, interface, mode); ++ ++ /* Callback to perform calendar setup */ ++ INVOKE_CB(cvmx_spi_callbacks.calendar_setup_cb, interface, mode, ++ num_ports); ++ ++ /* Callback to perform clock detection */ ++ INVOKE_CB(cvmx_spi_callbacks.clock_detect_cb, interface, mode, timeout); ++ ++ /* Callback to perform SPI4 link training */ ++ INVOKE_CB(cvmx_spi_callbacks.training_cb, interface, mode, timeout); ++ ++ /* Callback to perform calendar sync */ ++ INVOKE_CB(cvmx_spi_callbacks.calendar_sync_cb, interface, mode, ++ timeout); ++ ++ /* Callback to handle interface coming up */ ++ INVOKE_CB(cvmx_spi_callbacks.interface_up_cb, interface, mode); ++ ++ return res; ++} ++ ++/** ++ * This routine restarts the SPI interface after it has lost synchronization ++ * with its correspondent system. ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for clock synchronization in seconds ++ * ++ * Returns Zero on success, negative of failure. ++ */ ++int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, int timeout) ++{ ++ int res = -1; ++ ++ if (!(OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))) ++ return res; ++ ++ cvmx_dprintf("SPI%d: Restart %s\n", interface, modes[mode]); ++ ++ /* Callback to perform SPI4 reset */ ++ INVOKE_CB(cvmx_spi_callbacks.reset_cb, interface, mode); ++ ++ /* NOTE: Calendar setup is not performed during restart */ ++ /* Refer to cvmx_spi_start_interface() for the full sequence */ ++ ++ /* Callback to perform clock detection */ ++ INVOKE_CB(cvmx_spi_callbacks.clock_detect_cb, interface, mode, timeout); ++ ++ /* Callback to perform SPI4 link training */ ++ INVOKE_CB(cvmx_spi_callbacks.training_cb, interface, mode, timeout); ++ ++ /* Callback to perform calendar sync */ ++ INVOKE_CB(cvmx_spi_callbacks.calendar_sync_cb, interface, mode, ++ timeout); ++ ++ /* Callback to handle interface coming up */ ++ INVOKE_CB(cvmx_spi_callbacks.interface_up_cb, interface, mode); ++ ++ return res; ++} ++ ++/** ++ * Callback to perform SPI4 reset ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode) ++{ ++ union cvmx_spxx_dbg_deskew_ctl spxx_dbg_deskew_ctl; ++ union cvmx_spxx_clk_ctl spxx_clk_ctl; ++ union cvmx_spxx_bist_stat spxx_bist_stat; ++ union cvmx_spxx_int_msk spxx_int_msk; ++ union cvmx_stxx_int_msk stxx_int_msk; ++ union cvmx_spxx_trn4_ctl spxx_trn4_ctl; ++ int index; ++ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; ++ ++ /* Disable SPI error events while we run BIST */ ++ spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); ++ stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); ++ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); ++ ++ /* Run BIST in the SPI interface */ ++ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), 0); ++ cvmx_write_csr(CVMX_STXX_COM_CTL(interface), 0); ++ spxx_clk_ctl.u64 = 0; ++ spxx_clk_ctl.s.runbist = 1; ++ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); ++ cvmx_wait(10 * MS); ++ spxx_bist_stat.u64 = cvmx_read_csr(CVMX_SPXX_BIST_STAT(interface)); ++ if (spxx_bist_stat.s.stat0) ++ cvmx_dprintf ++ ("ERROR SPI%d: BIST failed on receive datapath FIFO\n", ++ interface); ++ if (spxx_bist_stat.s.stat1) ++ cvmx_dprintf("ERROR SPI%d: BIST failed on RX calendar table\n", ++ interface); ++ if (spxx_bist_stat.s.stat2) ++ cvmx_dprintf("ERROR SPI%d: BIST failed on TX calendar table\n", ++ interface); ++ ++ /* Clear the calendar table after BIST to fix parity errors */ ++ for (index = 0; index < 32; index++) { ++ union cvmx_srxx_spi4_calx srxx_spi4_calx; ++ union cvmx_stxx_spi4_calx stxx_spi4_calx; ++ ++ srxx_spi4_calx.u64 = 0; ++ srxx_spi4_calx.s.oddpar = 1; ++ cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), ++ srxx_spi4_calx.u64); ++ ++ stxx_spi4_calx.u64 = 0; ++ stxx_spi4_calx.s.oddpar = 1; ++ cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), ++ stxx_spi4_calx.u64); ++ } ++ ++ /* Re enable reporting of error interrupts */ ++ cvmx_write_csr(CVMX_SPXX_INT_REG(interface), ++ cvmx_read_csr(CVMX_SPXX_INT_REG(interface))); ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); ++ cvmx_write_csr(CVMX_STXX_INT_REG(interface), ++ cvmx_read_csr(CVMX_STXX_INT_REG(interface))); ++ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); ++ ++ /* Setup the CLKDLY right in the middle */ ++ spxx_clk_ctl.u64 = 0; ++ spxx_clk_ctl.s.seetrn = 0; ++ spxx_clk_ctl.s.clkdly = 0x10; ++ spxx_clk_ctl.s.runbist = 0; ++ spxx_clk_ctl.s.statdrv = 0; ++ /* This should always be on the opposite edge as statdrv */ ++ spxx_clk_ctl.s.statrcv = 1; ++ spxx_clk_ctl.s.sndtrn = 0; ++ spxx_clk_ctl.s.drptrn = 0; ++ spxx_clk_ctl.s.rcvtrn = 0; ++ spxx_clk_ctl.s.srxdlck = 0; ++ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); ++ cvmx_wait(100 * MS); ++ ++ /* Reset SRX0 DLL */ ++ spxx_clk_ctl.s.srxdlck = 1; ++ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); ++ ++ /* Waiting for Inf0 Spi4 RX DLL to lock */ ++ cvmx_wait(100 * MS); ++ ++ /* Enable dynamic alignment */ ++ spxx_trn4_ctl.s.trntest = 0; ++ spxx_trn4_ctl.s.jitter = 1; ++ spxx_trn4_ctl.s.clr_boot = 1; ++ spxx_trn4_ctl.s.set_boot = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) ++ spxx_trn4_ctl.s.maxdist = 3; ++ else ++ spxx_trn4_ctl.s.maxdist = 8; ++ spxx_trn4_ctl.s.macro_en = 1; ++ spxx_trn4_ctl.s.mux_en = 1; ++ cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64); ++ ++ spxx_dbg_deskew_ctl.u64 = 0; ++ cvmx_write_csr(CVMX_SPXX_DBG_DESKEW_CTL(interface), ++ spxx_dbg_deskew_ctl.u64); ++ ++ return 0; ++} ++ ++/** ++ * Callback to setup calendar and miscellaneous settings before clock detection ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @num_ports: Number of ports to configure on SPI ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode, ++ int num_ports) ++{ ++ int port; ++ int index; ++ if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { ++ union cvmx_srxx_com_ctl srxx_com_ctl; ++ union cvmx_srxx_spi4_stat srxx_spi4_stat; ++ ++ /* SRX0 number of Ports */ ++ srxx_com_ctl.u64 = 0; ++ srxx_com_ctl.s.prts = num_ports - 1; ++ srxx_com_ctl.s.st_en = 0; ++ srxx_com_ctl.s.inf_en = 0; ++ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); ++ ++ /* SRX0 Calendar Table. This round robbins through all ports */ ++ port = 0; ++ index = 0; ++ while (port < num_ports) { ++ union cvmx_srxx_spi4_calx srxx_spi4_calx; ++ srxx_spi4_calx.u64 = 0; ++ srxx_spi4_calx.s.prt0 = port++; ++ srxx_spi4_calx.s.prt1 = port++; ++ srxx_spi4_calx.s.prt2 = port++; ++ srxx_spi4_calx.s.prt3 = port++; ++ srxx_spi4_calx.s.oddpar = ++ ~(cvmx_dpop(srxx_spi4_calx.u64) & 1); ++ cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), ++ srxx_spi4_calx.u64); ++ index++; ++ } ++ srxx_spi4_stat.u64 = 0; ++ srxx_spi4_stat.s.len = num_ports; ++ srxx_spi4_stat.s.m = 1; ++ cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface), ++ srxx_spi4_stat.u64); ++ } ++ ++ if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { ++ union cvmx_stxx_arb_ctl stxx_arb_ctl; ++ union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max; ++ union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh; ++ union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl; ++ union cvmx_stxx_spi4_stat stxx_spi4_stat; ++ union cvmx_stxx_spi4_dat stxx_spi4_dat; ++ ++ /* STX0 Config */ ++ stxx_arb_ctl.u64 = 0; ++ stxx_arb_ctl.s.igntpa = 0; ++ stxx_arb_ctl.s.mintrn = 0; ++ cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64); ++ ++ gmxx_tx_spi_max.u64 = 0; ++ gmxx_tx_spi_max.s.max1 = 8; ++ gmxx_tx_spi_max.s.max2 = 4; ++ gmxx_tx_spi_max.s.slice = 0; ++ cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface), ++ gmxx_tx_spi_max.u64); ++ ++ gmxx_tx_spi_thresh.u64 = 0; ++ gmxx_tx_spi_thresh.s.thresh = 4; ++ cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface), ++ gmxx_tx_spi_thresh.u64); ++ ++ gmxx_tx_spi_ctl.u64 = 0; ++ gmxx_tx_spi_ctl.s.tpa_clr = 0; ++ gmxx_tx_spi_ctl.s.cont_pkt = 0; ++ cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface), ++ gmxx_tx_spi_ctl.u64); ++ ++ /* STX0 Training Control */ ++ stxx_spi4_dat.u64 = 0; ++ /*Minimum needed by dynamic alignment */ ++ stxx_spi4_dat.s.alpha = 32; ++ stxx_spi4_dat.s.max_t = 0xFFFF; /*Minimum interval is 0x20 */ ++ cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface), ++ stxx_spi4_dat.u64); ++ ++ /* STX0 Calendar Table. This round robbins through all ports */ ++ port = 0; ++ index = 0; ++ while (port < num_ports) { ++ union cvmx_stxx_spi4_calx stxx_spi4_calx; ++ stxx_spi4_calx.u64 = 0; ++ stxx_spi4_calx.s.prt0 = port++; ++ stxx_spi4_calx.s.prt1 = port++; ++ stxx_spi4_calx.s.prt2 = port++; ++ stxx_spi4_calx.s.prt3 = port++; ++ stxx_spi4_calx.s.oddpar = ++ ~(cvmx_dpop(stxx_spi4_calx.u64) & 1); ++ cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), ++ stxx_spi4_calx.u64); ++ index++; ++ } ++ stxx_spi4_stat.u64 = 0; ++ stxx_spi4_stat.s.len = num_ports; ++ stxx_spi4_stat.s.m = 1; ++ cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface), ++ stxx_spi4_stat.u64); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Callback to perform clock detection ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for clock synchronization in seconds ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode, int timeout) ++{ ++ int clock_transitions; ++ union cvmx_spxx_clk_stat stat; ++ uint64_t timeout_time; ++ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; ++ ++ /* ++ * Regardless of operating mode, both Tx and Rx clocks must be ++ * present for the SPI interface to operate. ++ */ ++ cvmx_dprintf("SPI%d: Waiting to see TsClk...\n", interface); ++ timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; ++ /* ++ * Require 100 clock transitions in order to avoid any noise ++ * in the beginning. ++ */ ++ clock_transitions = 100; ++ do { ++ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); ++ if (stat.s.s4clk0 && stat.s.s4clk1 && clock_transitions) { ++ /* ++ * We've seen a clock transition, so decrement ++ * the number we still need. ++ */ ++ clock_transitions--; ++ cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64); ++ stat.s.s4clk0 = 0; ++ stat.s.s4clk1 = 0; ++ } ++ if (cvmx_get_cycle() > timeout_time) { ++ cvmx_dprintf("SPI%d: Timeout\n", interface); ++ return -1; ++ } ++ } while (stat.s.s4clk0 == 0 || stat.s.s4clk1 == 0); ++ ++ cvmx_dprintf("SPI%d: Waiting to see RsClk...\n", interface); ++ timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; ++ /* ++ * Require 100 clock transitions in order to avoid any noise in the ++ * beginning. ++ */ ++ clock_transitions = 100; ++ do { ++ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); ++ if (stat.s.d4clk0 && stat.s.d4clk1 && clock_transitions) { ++ /* ++ * We've seen a clock transition, so decrement ++ * the number we still need ++ */ ++ clock_transitions--; ++ cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64); ++ stat.s.d4clk0 = 0; ++ stat.s.d4clk1 = 0; ++ } ++ if (cvmx_get_cycle() > timeout_time) { ++ cvmx_dprintf("SPI%d: Timeout\n", interface); ++ return -1; ++ } ++ } while (stat.s.d4clk0 == 0 || stat.s.d4clk1 == 0); ++ ++ return 0; ++} ++ ++/** ++ * Callback to perform link training ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for link to be trained (in seconds) ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout) ++{ ++ union cvmx_spxx_trn4_ctl spxx_trn4_ctl; ++ union cvmx_spxx_clk_stat stat; ++ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; ++ uint64_t timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; ++ int rx_training_needed; ++ ++ /* SRX0 & STX0 Inf0 Links are configured - begin training */ ++ union cvmx_spxx_clk_ctl spxx_clk_ctl; ++ spxx_clk_ctl.u64 = 0; ++ spxx_clk_ctl.s.seetrn = 0; ++ spxx_clk_ctl.s.clkdly = 0x10; ++ spxx_clk_ctl.s.runbist = 0; ++ spxx_clk_ctl.s.statdrv = 0; ++ /* This should always be on the opposite edge as statdrv */ ++ spxx_clk_ctl.s.statrcv = 1; ++ spxx_clk_ctl.s.sndtrn = 1; ++ spxx_clk_ctl.s.drptrn = 1; ++ spxx_clk_ctl.s.rcvtrn = 1; ++ spxx_clk_ctl.s.srxdlck = 1; ++ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); ++ cvmx_wait(1000 * MS); ++ ++ /* SRX0 clear the boot bit */ ++ spxx_trn4_ctl.u64 = cvmx_read_csr(CVMX_SPXX_TRN4_CTL(interface)); ++ spxx_trn4_ctl.s.clr_boot = 1; ++ cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64); ++ ++ /* Wait for the training sequence to complete */ ++ cvmx_dprintf("SPI%d: Waiting for training\n", interface); ++ cvmx_wait(1000 * MS); ++ /* Wait a really long time here */ ++ timeout_time = cvmx_get_cycle() + 1000ull * MS * 600; ++ /* ++ * The HRM says we must wait for 34 + 16 * MAXDIST training sequences. ++ * We'll be pessimistic and wait for a lot more. ++ */ ++ rx_training_needed = 500; ++ do { ++ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); ++ if (stat.s.srxtrn && rx_training_needed) { ++ rx_training_needed--; ++ cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64); ++ stat.s.srxtrn = 0; ++ } ++ if (cvmx_get_cycle() > timeout_time) { ++ cvmx_dprintf("SPI%d: Timeout\n", interface); ++ return -1; ++ } ++ } while (stat.s.srxtrn == 0); ++ ++ return 0; ++} ++ ++/** ++ * Callback to perform calendar data synchronization ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for calendar data in seconds ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, int timeout) ++{ ++ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; ++ if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { ++ /* SRX0 interface should be good, send calendar data */ ++ union cvmx_srxx_com_ctl srxx_com_ctl; ++ cvmx_dprintf ++ ("SPI%d: Rx is synchronized, start sending calendar data\n", ++ interface); ++ srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface)); ++ srxx_com_ctl.s.inf_en = 1; ++ srxx_com_ctl.s.st_en = 1; ++ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); ++ } ++ ++ if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { ++ /* STX0 has achieved sync */ ++ /* The corespondant board should be sending calendar data */ ++ /* Enable the STX0 STAT receiver. */ ++ union cvmx_spxx_clk_stat stat; ++ uint64_t timeout_time; ++ union cvmx_stxx_com_ctl stxx_com_ctl; ++ stxx_com_ctl.u64 = 0; ++ stxx_com_ctl.s.st_en = 1; ++ cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64); ++ ++ /* Waiting for calendar sync on STX0 STAT */ ++ cvmx_dprintf("SPI%d: Waiting to sync on STX[%d] STAT\n", ++ interface, interface); ++ timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; ++ /* SPX0_CLK_STAT - SPX0_CLK_STAT[STXCAL] should be 1 (bit10) */ ++ do { ++ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); ++ if (cvmx_get_cycle() > timeout_time) { ++ cvmx_dprintf("SPI%d: Timeout\n", interface); ++ return -1; ++ } ++ } while (stat.s.stxcal == 0); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Callback to handle interface up ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode) ++{ ++ union cvmx_gmxx_rxx_frm_min gmxx_rxx_frm_min; ++ union cvmx_gmxx_rxx_frm_max gmxx_rxx_frm_max; ++ union cvmx_gmxx_rxx_jabber gmxx_rxx_jabber; ++ ++ if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { ++ union cvmx_srxx_com_ctl srxx_com_ctl; ++ srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface)); ++ srxx_com_ctl.s.inf_en = 1; ++ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); ++ cvmx_dprintf("SPI%d: Rx is now up\n", interface); ++ } ++ ++ if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { ++ union cvmx_stxx_com_ctl stxx_com_ctl; ++ stxx_com_ctl.u64 = cvmx_read_csr(CVMX_STXX_COM_CTL(interface)); ++ stxx_com_ctl.s.inf_en = 1; ++ cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64); ++ cvmx_dprintf("SPI%d: Tx is now up\n", interface); ++ } ++ ++ gmxx_rxx_frm_min.u64 = 0; ++ gmxx_rxx_frm_min.s.len = 64; ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MIN(0, interface), ++ gmxx_rxx_frm_min.u64); ++ gmxx_rxx_frm_max.u64 = 0; ++ gmxx_rxx_frm_max.s.len = 64 * 1024 - 4; ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(0, interface), ++ gmxx_rxx_frm_max.u64); ++ gmxx_rxx_jabber.u64 = 0; ++ gmxx_rxx_jabber.s.cnt = 64 * 1024 - 4; ++ cvmx_write_csr(CVMX_GMXX_RXX_JABBER(0, interface), gmxx_rxx_jabber.u64); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-spi.h +@@ -0,0 +1,269 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/* ++ * ++ * This file contains defines for the SPI interface ++ */ ++#ifndef __CVMX_SPI_H__ ++#define __CVMX_SPI_H__ ++ ++#include "cvmx-gmxx-defs.h" ++ ++/* CSR typedefs have been moved to cvmx-csr-*.h */ ++ ++typedef enum { ++ CVMX_SPI_MODE_UNKNOWN = 0, ++ CVMX_SPI_MODE_TX_HALFPLEX = 1, ++ CVMX_SPI_MODE_RX_HALFPLEX = 2, ++ CVMX_SPI_MODE_DUPLEX = 3 ++} cvmx_spi_mode_t; ++ ++/** Callbacks structure to customize SPI4 initialization sequence */ ++typedef struct { ++ /** Called to reset SPI4 DLL */ ++ int (*reset_cb) (int interface, cvmx_spi_mode_t mode); ++ ++ /** Called to setup calendar */ ++ int (*calendar_setup_cb) (int interface, cvmx_spi_mode_t mode, ++ int num_ports); ++ ++ /** Called for Tx and Rx clock detection */ ++ int (*clock_detect_cb) (int interface, cvmx_spi_mode_t mode, ++ int timeout); ++ ++ /** Called to perform link training */ ++ int (*training_cb) (int interface, cvmx_spi_mode_t mode, int timeout); ++ ++ /** Called for calendar data synchronization */ ++ int (*calendar_sync_cb) (int interface, cvmx_spi_mode_t mode, ++ int timeout); ++ ++ /** Called when interface is up */ ++ int (*interface_up_cb) (int interface, cvmx_spi_mode_t mode); ++ ++} cvmx_spi_callbacks_t; ++ ++/** ++ * Return true if the supplied interface is configured for SPI ++ * ++ * @interface: Interface to check ++ * Returns True if interface is SPI ++ */ ++static inline int cvmx_spi_is_spi_interface(int interface) ++{ ++ uint64_t gmxState = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); ++ return (gmxState & 0x2) && (gmxState & 0x1); ++} ++ ++/** ++ * Initialize and start the SPI interface. ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for clock synchronization in seconds ++ * @num_ports: Number of SPI ports to configure ++ * ++ * Returns Zero on success, negative of failure. ++ */ ++extern int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode, ++ int timeout, int num_ports); ++ ++/** ++ * This routine restarts the SPI interface after it has lost synchronization ++ * with its corespondant system. ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for clock synchronization in seconds ++ * Returns Zero on success, negative of failure. ++ */ ++extern int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, ++ int timeout); ++ ++/** ++ * Return non-zero if the SPI interface has a SPI4000 attached ++ * ++ * @interface: SPI interface the SPI4000 is connected to ++ * ++ * Returns ++ */ ++static inline int cvmx_spi4000_is_present(int interface) ++{ ++ return 0; ++} ++ ++/** ++ * Initialize the SPI4000 for use ++ * ++ * @interface: SPI interface the SPI4000 is connected to ++ */ ++static inline int cvmx_spi4000_initialize(int interface) ++{ ++ return 0; ++} ++ ++/** ++ * Poll all the SPI4000 port and check its speed ++ * ++ * @interface: Interface the SPI4000 is on ++ * @port: Port to poll (0-9) ++ * Returns Status of the port. 0=down. All other values the port is up. ++ */ ++static inline union cvmx_gmxx_rxx_rx_inbnd cvmx_spi4000_check_speed( ++ int interface, ++ int port) ++{ ++ union cvmx_gmxx_rxx_rx_inbnd r; ++ r.u64 = 0; ++ return r; ++} ++ ++/** ++ * Get current SPI4 initialization callbacks ++ * ++ * @callbacks: Pointer to the callbacks structure.to fill ++ * ++ * Returns Pointer to cvmx_spi_callbacks_t structure. ++ */ ++extern void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks); ++ ++/** ++ * Set new SPI4 initialization callbacks ++ * ++ * @new_callbacks: Pointer to an updated callbacks structure. ++ */ ++extern void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks); ++ ++/** ++ * Callback to perform SPI4 reset ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++extern int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode); ++ ++/** ++ * Callback to setup calendar and miscellaneous settings before clock ++ * detection ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @num_ports: Number of ports to configure on SPI ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++extern int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode, ++ int num_ports); ++ ++/** ++ * Callback to perform clock detection ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for clock synchronization in seconds ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++extern int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode, ++ int timeout); ++ ++/** ++ * Callback to perform link training ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for link to be trained (in seconds) ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++extern int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, ++ int timeout); ++ ++/** ++ * Callback to perform calendar data synchronization ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * @timeout: Timeout to wait for calendar data in seconds ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++extern int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, ++ int timeout); ++ ++/** ++ * Callback to handle interface up ++ * ++ * @interface: The identifier of the packet interface to configure and ++ * use as a SPI interface. ++ * @mode: The operating mode for the SPI interface. The interface ++ * can operate as a full duplex (both Tx and Rx data paths ++ * active) or as a halfplex (either the Tx data path is ++ * active or the Rx data path is active, but not both). ++ * ++ * Returns Zero on success, non-zero error code on failure (will cause ++ * SPI initialization to abort) ++ */ ++extern int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode); ++ ++#endif /* __CVMX_SPI_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-spxx-defs.h +@@ -0,0 +1,347 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_SPXX_DEFS_H__ ++#define __CVMX_SPXX_DEFS_H__ ++ ++#define CVMX_SPXX_BCKPRS_CNT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000340ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_BIST_STAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800900007F8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_CLK_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000348ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_CLK_STAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000350ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_DBG_DESKEW_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000368ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_DBG_DESKEW_STATE(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000370ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_DRV_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000358ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_ERR_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000320ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_INT_DAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000318ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_INT_MSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000308ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_INT_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000300ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_INT_SYNC(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000310ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_TPA_ACC(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000338ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_TPA_MAX(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000330ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_TPA_SEL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000328ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SPXX_TRN4_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000360ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_spxx_bckprs_cnt { ++ uint64_t u64; ++ struct cvmx_spxx_bckprs_cnt_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_spxx_bckprs_cnt_s cn38xx; ++ struct cvmx_spxx_bckprs_cnt_s cn38xxp2; ++ struct cvmx_spxx_bckprs_cnt_s cn58xx; ++ struct cvmx_spxx_bckprs_cnt_s cn58xxp1; ++}; ++ ++union cvmx_spxx_bist_stat { ++ uint64_t u64; ++ struct cvmx_spxx_bist_stat_s { ++ uint64_t reserved_3_63:61; ++ uint64_t stat2:1; ++ uint64_t stat1:1; ++ uint64_t stat0:1; ++ } s; ++ struct cvmx_spxx_bist_stat_s cn38xx; ++ struct cvmx_spxx_bist_stat_s cn38xxp2; ++ struct cvmx_spxx_bist_stat_s cn58xx; ++ struct cvmx_spxx_bist_stat_s cn58xxp1; ++}; ++ ++union cvmx_spxx_clk_ctl { ++ uint64_t u64; ++ struct cvmx_spxx_clk_ctl_s { ++ uint64_t reserved_17_63:47; ++ uint64_t seetrn:1; ++ uint64_t reserved_12_15:4; ++ uint64_t clkdly:5; ++ uint64_t runbist:1; ++ uint64_t statdrv:1; ++ uint64_t statrcv:1; ++ uint64_t sndtrn:1; ++ uint64_t drptrn:1; ++ uint64_t rcvtrn:1; ++ uint64_t srxdlck:1; ++ } s; ++ struct cvmx_spxx_clk_ctl_s cn38xx; ++ struct cvmx_spxx_clk_ctl_s cn38xxp2; ++ struct cvmx_spxx_clk_ctl_s cn58xx; ++ struct cvmx_spxx_clk_ctl_s cn58xxp1; ++}; ++ ++union cvmx_spxx_clk_stat { ++ uint64_t u64; ++ struct cvmx_spxx_clk_stat_s { ++ uint64_t reserved_11_63:53; ++ uint64_t stxcal:1; ++ uint64_t reserved_9_9:1; ++ uint64_t srxtrn:1; ++ uint64_t s4clk1:1; ++ uint64_t s4clk0:1; ++ uint64_t d4clk1:1; ++ uint64_t d4clk0:1; ++ uint64_t reserved_0_3:4; ++ } s; ++ struct cvmx_spxx_clk_stat_s cn38xx; ++ struct cvmx_spxx_clk_stat_s cn38xxp2; ++ struct cvmx_spxx_clk_stat_s cn58xx; ++ struct cvmx_spxx_clk_stat_s cn58xxp1; ++}; ++ ++union cvmx_spxx_dbg_deskew_ctl { ++ uint64_t u64; ++ struct cvmx_spxx_dbg_deskew_ctl_s { ++ uint64_t reserved_30_63:34; ++ uint64_t fallnop:1; ++ uint64_t fall8:1; ++ uint64_t reserved_26_27:2; ++ uint64_t sstep_go:1; ++ uint64_t sstep:1; ++ uint64_t reserved_22_23:2; ++ uint64_t clrdly:1; ++ uint64_t dec:1; ++ uint64_t inc:1; ++ uint64_t mux:1; ++ uint64_t offset:5; ++ uint64_t bitsel:5; ++ uint64_t offdly:6; ++ uint64_t dllfrc:1; ++ uint64_t dlldis:1; ++ } s; ++ struct cvmx_spxx_dbg_deskew_ctl_s cn38xx; ++ struct cvmx_spxx_dbg_deskew_ctl_s cn38xxp2; ++ struct cvmx_spxx_dbg_deskew_ctl_s cn58xx; ++ struct cvmx_spxx_dbg_deskew_ctl_s cn58xxp1; ++}; ++ ++union cvmx_spxx_dbg_deskew_state { ++ uint64_t u64; ++ struct cvmx_spxx_dbg_deskew_state_s { ++ uint64_t reserved_9_63:55; ++ uint64_t testres:1; ++ uint64_t unxterm:1; ++ uint64_t muxsel:2; ++ uint64_t offset:5; ++ } s; ++ struct cvmx_spxx_dbg_deskew_state_s cn38xx; ++ struct cvmx_spxx_dbg_deskew_state_s cn38xxp2; ++ struct cvmx_spxx_dbg_deskew_state_s cn58xx; ++ struct cvmx_spxx_dbg_deskew_state_s cn58xxp1; ++}; ++ ++union cvmx_spxx_drv_ctl { ++ uint64_t u64; ++ struct cvmx_spxx_drv_ctl_s { ++ uint64_t reserved_0_63:64; ++ } s; ++ struct cvmx_spxx_drv_ctl_cn38xx { ++ uint64_t reserved_16_63:48; ++ uint64_t stx4ncmp:4; ++ uint64_t stx4pcmp:4; ++ uint64_t srx4cmp:8; ++ } cn38xx; ++ struct cvmx_spxx_drv_ctl_cn38xx cn38xxp2; ++ struct cvmx_spxx_drv_ctl_cn58xx { ++ uint64_t reserved_24_63:40; ++ uint64_t stx4ncmp:4; ++ uint64_t stx4pcmp:4; ++ uint64_t reserved_10_15:6; ++ uint64_t srx4cmp:10; ++ } cn58xx; ++ struct cvmx_spxx_drv_ctl_cn58xx cn58xxp1; ++}; ++ ++union cvmx_spxx_err_ctl { ++ uint64_t u64; ++ struct cvmx_spxx_err_ctl_s { ++ uint64_t reserved_9_63:55; ++ uint64_t prtnxa:1; ++ uint64_t dipcls:1; ++ uint64_t dippay:1; ++ uint64_t reserved_4_5:2; ++ uint64_t errcnt:4; ++ } s; ++ struct cvmx_spxx_err_ctl_s cn38xx; ++ struct cvmx_spxx_err_ctl_s cn38xxp2; ++ struct cvmx_spxx_err_ctl_s cn58xx; ++ struct cvmx_spxx_err_ctl_s cn58xxp1; ++}; ++ ++union cvmx_spxx_int_dat { ++ uint64_t u64; ++ struct cvmx_spxx_int_dat_s { ++ uint64_t reserved_32_63:32; ++ uint64_t mul:1; ++ uint64_t reserved_14_30:17; ++ uint64_t calbnk:2; ++ uint64_t rsvop:4; ++ uint64_t prt:8; ++ } s; ++ struct cvmx_spxx_int_dat_s cn38xx; ++ struct cvmx_spxx_int_dat_s cn38xxp2; ++ struct cvmx_spxx_int_dat_s cn58xx; ++ struct cvmx_spxx_int_dat_s cn58xxp1; ++}; ++ ++union cvmx_spxx_int_msk { ++ uint64_t u64; ++ struct cvmx_spxx_int_msk_s { ++ uint64_t reserved_12_63:52; ++ uint64_t calerr:1; ++ uint64_t syncerr:1; ++ uint64_t diperr:1; ++ uint64_t tpaovr:1; ++ uint64_t rsverr:1; ++ uint64_t drwnng:1; ++ uint64_t clserr:1; ++ uint64_t spiovr:1; ++ uint64_t reserved_2_3:2; ++ uint64_t abnorm:1; ++ uint64_t prtnxa:1; ++ } s; ++ struct cvmx_spxx_int_msk_s cn38xx; ++ struct cvmx_spxx_int_msk_s cn38xxp2; ++ struct cvmx_spxx_int_msk_s cn58xx; ++ struct cvmx_spxx_int_msk_s cn58xxp1; ++}; ++ ++union cvmx_spxx_int_reg { ++ uint64_t u64; ++ struct cvmx_spxx_int_reg_s { ++ uint64_t reserved_32_63:32; ++ uint64_t spf:1; ++ uint64_t reserved_12_30:19; ++ uint64_t calerr:1; ++ uint64_t syncerr:1; ++ uint64_t diperr:1; ++ uint64_t tpaovr:1; ++ uint64_t rsverr:1; ++ uint64_t drwnng:1; ++ uint64_t clserr:1; ++ uint64_t spiovr:1; ++ uint64_t reserved_2_3:2; ++ uint64_t abnorm:1; ++ uint64_t prtnxa:1; ++ } s; ++ struct cvmx_spxx_int_reg_s cn38xx; ++ struct cvmx_spxx_int_reg_s cn38xxp2; ++ struct cvmx_spxx_int_reg_s cn58xx; ++ struct cvmx_spxx_int_reg_s cn58xxp1; ++}; ++ ++union cvmx_spxx_int_sync { ++ uint64_t u64; ++ struct cvmx_spxx_int_sync_s { ++ uint64_t reserved_12_63:52; ++ uint64_t calerr:1; ++ uint64_t syncerr:1; ++ uint64_t diperr:1; ++ uint64_t tpaovr:1; ++ uint64_t rsverr:1; ++ uint64_t drwnng:1; ++ uint64_t clserr:1; ++ uint64_t spiovr:1; ++ uint64_t reserved_2_3:2; ++ uint64_t abnorm:1; ++ uint64_t prtnxa:1; ++ } s; ++ struct cvmx_spxx_int_sync_s cn38xx; ++ struct cvmx_spxx_int_sync_s cn38xxp2; ++ struct cvmx_spxx_int_sync_s cn58xx; ++ struct cvmx_spxx_int_sync_s cn58xxp1; ++}; ++ ++union cvmx_spxx_tpa_acc { ++ uint64_t u64; ++ struct cvmx_spxx_tpa_acc_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_spxx_tpa_acc_s cn38xx; ++ struct cvmx_spxx_tpa_acc_s cn38xxp2; ++ struct cvmx_spxx_tpa_acc_s cn58xx; ++ struct cvmx_spxx_tpa_acc_s cn58xxp1; ++}; ++ ++union cvmx_spxx_tpa_max { ++ uint64_t u64; ++ struct cvmx_spxx_tpa_max_s { ++ uint64_t reserved_32_63:32; ++ uint64_t max:32; ++ } s; ++ struct cvmx_spxx_tpa_max_s cn38xx; ++ struct cvmx_spxx_tpa_max_s cn38xxp2; ++ struct cvmx_spxx_tpa_max_s cn58xx; ++ struct cvmx_spxx_tpa_max_s cn58xxp1; ++}; ++ ++union cvmx_spxx_tpa_sel { ++ uint64_t u64; ++ struct cvmx_spxx_tpa_sel_s { ++ uint64_t reserved_4_63:60; ++ uint64_t prtsel:4; ++ } s; ++ struct cvmx_spxx_tpa_sel_s cn38xx; ++ struct cvmx_spxx_tpa_sel_s cn38xxp2; ++ struct cvmx_spxx_tpa_sel_s cn58xx; ++ struct cvmx_spxx_tpa_sel_s cn58xxp1; ++}; ++ ++union cvmx_spxx_trn4_ctl { ++ uint64_t u64; ++ struct cvmx_spxx_trn4_ctl_s { ++ uint64_t reserved_13_63:51; ++ uint64_t trntest:1; ++ uint64_t jitter:3; ++ uint64_t clr_boot:1; ++ uint64_t set_boot:1; ++ uint64_t maxdist:5; ++ uint64_t macro_en:1; ++ uint64_t mux_en:1; ++ } s; ++ struct cvmx_spxx_trn4_ctl_s cn38xx; ++ struct cvmx_spxx_trn4_ctl_s cn38xxp2; ++ struct cvmx_spxx_trn4_ctl_s cn58xx; ++ struct cvmx_spxx_trn4_ctl_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-srxx-defs.h +@@ -0,0 +1,126 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_SRXX_DEFS_H__ ++#define __CVMX_SRXX_DEFS_H__ ++ ++#define CVMX_SRXX_COM_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000200ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SRXX_IGN_RX_FULL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000218ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SRXX_SPI4_CALX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000000ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SRXX_SPI4_STAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000208ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SRXX_SW_TICK_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000220ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_SRXX_SW_TICK_DAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000228ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_srxx_com_ctl { ++ uint64_t u64; ++ struct cvmx_srxx_com_ctl_s { ++ uint64_t reserved_8_63:56; ++ uint64_t prts:4; ++ uint64_t st_en:1; ++ uint64_t reserved_1_2:2; ++ uint64_t inf_en:1; ++ } s; ++ struct cvmx_srxx_com_ctl_s cn38xx; ++ struct cvmx_srxx_com_ctl_s cn38xxp2; ++ struct cvmx_srxx_com_ctl_s cn58xx; ++ struct cvmx_srxx_com_ctl_s cn58xxp1; ++}; ++ ++union cvmx_srxx_ign_rx_full { ++ uint64_t u64; ++ struct cvmx_srxx_ign_rx_full_s { ++ uint64_t reserved_16_63:48; ++ uint64_t ignore:16; ++ } s; ++ struct cvmx_srxx_ign_rx_full_s cn38xx; ++ struct cvmx_srxx_ign_rx_full_s cn38xxp2; ++ struct cvmx_srxx_ign_rx_full_s cn58xx; ++ struct cvmx_srxx_ign_rx_full_s cn58xxp1; ++}; ++ ++union cvmx_srxx_spi4_calx { ++ uint64_t u64; ++ struct cvmx_srxx_spi4_calx_s { ++ uint64_t reserved_17_63:47; ++ uint64_t oddpar:1; ++ uint64_t prt3:4; ++ uint64_t prt2:4; ++ uint64_t prt1:4; ++ uint64_t prt0:4; ++ } s; ++ struct cvmx_srxx_spi4_calx_s cn38xx; ++ struct cvmx_srxx_spi4_calx_s cn38xxp2; ++ struct cvmx_srxx_spi4_calx_s cn58xx; ++ struct cvmx_srxx_spi4_calx_s cn58xxp1; ++}; ++ ++union cvmx_srxx_spi4_stat { ++ uint64_t u64; ++ struct cvmx_srxx_spi4_stat_s { ++ uint64_t reserved_16_63:48; ++ uint64_t m:8; ++ uint64_t reserved_7_7:1; ++ uint64_t len:7; ++ } s; ++ struct cvmx_srxx_spi4_stat_s cn38xx; ++ struct cvmx_srxx_spi4_stat_s cn38xxp2; ++ struct cvmx_srxx_spi4_stat_s cn58xx; ++ struct cvmx_srxx_spi4_stat_s cn58xxp1; ++}; ++ ++union cvmx_srxx_sw_tick_ctl { ++ uint64_t u64; ++ struct cvmx_srxx_sw_tick_ctl_s { ++ uint64_t reserved_14_63:50; ++ uint64_t eop:1; ++ uint64_t sop:1; ++ uint64_t mod:4; ++ uint64_t opc:4; ++ uint64_t adr:4; ++ } s; ++ struct cvmx_srxx_sw_tick_ctl_s cn38xx; ++ struct cvmx_srxx_sw_tick_ctl_s cn58xx; ++ struct cvmx_srxx_sw_tick_ctl_s cn58xxp1; ++}; ++ ++union cvmx_srxx_sw_tick_dat { ++ uint64_t u64; ++ struct cvmx_srxx_sw_tick_dat_s { ++ uint64_t dat:64; ++ } s; ++ struct cvmx_srxx_sw_tick_dat_s cn38xx; ++ struct cvmx_srxx_sw_tick_dat_s cn58xx; ++ struct cvmx_srxx_sw_tick_dat_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-stxx-defs.h +@@ -0,0 +1,292 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_STXX_DEFS_H__ ++#define __CVMX_STXX_DEFS_H__ ++ ++#define CVMX_STXX_ARB_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000608ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_BCKPRS_CNT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000688ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_COM_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000600ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_DIP_CNT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000690ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_IGN_CAL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000610ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_INT_MSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800900006A0ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_INT_REG(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000698ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_INT_SYNC(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800900006A8ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_MIN_BST(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000618ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_SPI4_CALX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000400ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_SPI4_DAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000628ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_SPI4_STAT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000630ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_STAT_BYTES_HI(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000648ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_STAT_BYTES_LO(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000680ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_STAT_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000638ull + (((block_id) & 1) * 0x8000000ull)) ++#define CVMX_STXX_STAT_PKT_XMT(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180090000640ull + (((block_id) & 1) * 0x8000000ull)) ++ ++union cvmx_stxx_arb_ctl { ++ uint64_t u64; ++ struct cvmx_stxx_arb_ctl_s { ++ uint64_t reserved_6_63:58; ++ uint64_t mintrn:1; ++ uint64_t reserved_4_4:1; ++ uint64_t igntpa:1; ++ uint64_t reserved_0_2:3; ++ } s; ++ struct cvmx_stxx_arb_ctl_s cn38xx; ++ struct cvmx_stxx_arb_ctl_s cn38xxp2; ++ struct cvmx_stxx_arb_ctl_s cn58xx; ++ struct cvmx_stxx_arb_ctl_s cn58xxp1; ++}; ++ ++union cvmx_stxx_bckprs_cnt { ++ uint64_t u64; ++ struct cvmx_stxx_bckprs_cnt_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_stxx_bckprs_cnt_s cn38xx; ++ struct cvmx_stxx_bckprs_cnt_s cn38xxp2; ++ struct cvmx_stxx_bckprs_cnt_s cn58xx; ++ struct cvmx_stxx_bckprs_cnt_s cn58xxp1; ++}; ++ ++union cvmx_stxx_com_ctl { ++ uint64_t u64; ++ struct cvmx_stxx_com_ctl_s { ++ uint64_t reserved_4_63:60; ++ uint64_t st_en:1; ++ uint64_t reserved_1_2:2; ++ uint64_t inf_en:1; ++ } s; ++ struct cvmx_stxx_com_ctl_s cn38xx; ++ struct cvmx_stxx_com_ctl_s cn38xxp2; ++ struct cvmx_stxx_com_ctl_s cn58xx; ++ struct cvmx_stxx_com_ctl_s cn58xxp1; ++}; ++ ++union cvmx_stxx_dip_cnt { ++ uint64_t u64; ++ struct cvmx_stxx_dip_cnt_s { ++ uint64_t reserved_8_63:56; ++ uint64_t frmmax:4; ++ uint64_t dipmax:4; ++ } s; ++ struct cvmx_stxx_dip_cnt_s cn38xx; ++ struct cvmx_stxx_dip_cnt_s cn38xxp2; ++ struct cvmx_stxx_dip_cnt_s cn58xx; ++ struct cvmx_stxx_dip_cnt_s cn58xxp1; ++}; ++ ++union cvmx_stxx_ign_cal { ++ uint64_t u64; ++ struct cvmx_stxx_ign_cal_s { ++ uint64_t reserved_16_63:48; ++ uint64_t igntpa:16; ++ } s; ++ struct cvmx_stxx_ign_cal_s cn38xx; ++ struct cvmx_stxx_ign_cal_s cn38xxp2; ++ struct cvmx_stxx_ign_cal_s cn58xx; ++ struct cvmx_stxx_ign_cal_s cn58xxp1; ++}; ++ ++union cvmx_stxx_int_msk { ++ uint64_t u64; ++ struct cvmx_stxx_int_msk_s { ++ uint64_t reserved_8_63:56; ++ uint64_t frmerr:1; ++ uint64_t unxfrm:1; ++ uint64_t nosync:1; ++ uint64_t diperr:1; ++ uint64_t datovr:1; ++ uint64_t ovrbst:1; ++ uint64_t calpar1:1; ++ uint64_t calpar0:1; ++ } s; ++ struct cvmx_stxx_int_msk_s cn38xx; ++ struct cvmx_stxx_int_msk_s cn38xxp2; ++ struct cvmx_stxx_int_msk_s cn58xx; ++ struct cvmx_stxx_int_msk_s cn58xxp1; ++}; ++ ++union cvmx_stxx_int_reg { ++ uint64_t u64; ++ struct cvmx_stxx_int_reg_s { ++ uint64_t reserved_9_63:55; ++ uint64_t syncerr:1; ++ uint64_t frmerr:1; ++ uint64_t unxfrm:1; ++ uint64_t nosync:1; ++ uint64_t diperr:1; ++ uint64_t datovr:1; ++ uint64_t ovrbst:1; ++ uint64_t calpar1:1; ++ uint64_t calpar0:1; ++ } s; ++ struct cvmx_stxx_int_reg_s cn38xx; ++ struct cvmx_stxx_int_reg_s cn38xxp2; ++ struct cvmx_stxx_int_reg_s cn58xx; ++ struct cvmx_stxx_int_reg_s cn58xxp1; ++}; ++ ++union cvmx_stxx_int_sync { ++ uint64_t u64; ++ struct cvmx_stxx_int_sync_s { ++ uint64_t reserved_8_63:56; ++ uint64_t frmerr:1; ++ uint64_t unxfrm:1; ++ uint64_t nosync:1; ++ uint64_t diperr:1; ++ uint64_t datovr:1; ++ uint64_t ovrbst:1; ++ uint64_t calpar1:1; ++ uint64_t calpar0:1; ++ } s; ++ struct cvmx_stxx_int_sync_s cn38xx; ++ struct cvmx_stxx_int_sync_s cn38xxp2; ++ struct cvmx_stxx_int_sync_s cn58xx; ++ struct cvmx_stxx_int_sync_s cn58xxp1; ++}; ++ ++union cvmx_stxx_min_bst { ++ uint64_t u64; ++ struct cvmx_stxx_min_bst_s { ++ uint64_t reserved_9_63:55; ++ uint64_t minb:9; ++ } s; ++ struct cvmx_stxx_min_bst_s cn38xx; ++ struct cvmx_stxx_min_bst_s cn38xxp2; ++ struct cvmx_stxx_min_bst_s cn58xx; ++ struct cvmx_stxx_min_bst_s cn58xxp1; ++}; ++ ++union cvmx_stxx_spi4_calx { ++ uint64_t u64; ++ struct cvmx_stxx_spi4_calx_s { ++ uint64_t reserved_17_63:47; ++ uint64_t oddpar:1; ++ uint64_t prt3:4; ++ uint64_t prt2:4; ++ uint64_t prt1:4; ++ uint64_t prt0:4; ++ } s; ++ struct cvmx_stxx_spi4_calx_s cn38xx; ++ struct cvmx_stxx_spi4_calx_s cn38xxp2; ++ struct cvmx_stxx_spi4_calx_s cn58xx; ++ struct cvmx_stxx_spi4_calx_s cn58xxp1; ++}; ++ ++union cvmx_stxx_spi4_dat { ++ uint64_t u64; ++ struct cvmx_stxx_spi4_dat_s { ++ uint64_t reserved_32_63:32; ++ uint64_t alpha:16; ++ uint64_t max_t:16; ++ } s; ++ struct cvmx_stxx_spi4_dat_s cn38xx; ++ struct cvmx_stxx_spi4_dat_s cn38xxp2; ++ struct cvmx_stxx_spi4_dat_s cn58xx; ++ struct cvmx_stxx_spi4_dat_s cn58xxp1; ++}; ++ ++union cvmx_stxx_spi4_stat { ++ uint64_t u64; ++ struct cvmx_stxx_spi4_stat_s { ++ uint64_t reserved_16_63:48; ++ uint64_t m:8; ++ uint64_t reserved_7_7:1; ++ uint64_t len:7; ++ } s; ++ struct cvmx_stxx_spi4_stat_s cn38xx; ++ struct cvmx_stxx_spi4_stat_s cn38xxp2; ++ struct cvmx_stxx_spi4_stat_s cn58xx; ++ struct cvmx_stxx_spi4_stat_s cn58xxp1; ++}; ++ ++union cvmx_stxx_stat_bytes_hi { ++ uint64_t u64; ++ struct cvmx_stxx_stat_bytes_hi_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_stxx_stat_bytes_hi_s cn38xx; ++ struct cvmx_stxx_stat_bytes_hi_s cn38xxp2; ++ struct cvmx_stxx_stat_bytes_hi_s cn58xx; ++ struct cvmx_stxx_stat_bytes_hi_s cn58xxp1; ++}; ++ ++union cvmx_stxx_stat_bytes_lo { ++ uint64_t u64; ++ struct cvmx_stxx_stat_bytes_lo_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_stxx_stat_bytes_lo_s cn38xx; ++ struct cvmx_stxx_stat_bytes_lo_s cn38xxp2; ++ struct cvmx_stxx_stat_bytes_lo_s cn58xx; ++ struct cvmx_stxx_stat_bytes_lo_s cn58xxp1; ++}; ++ ++union cvmx_stxx_stat_ctl { ++ uint64_t u64; ++ struct cvmx_stxx_stat_ctl_s { ++ uint64_t reserved_5_63:59; ++ uint64_t clr:1; ++ uint64_t bckprs:4; ++ } s; ++ struct cvmx_stxx_stat_ctl_s cn38xx; ++ struct cvmx_stxx_stat_ctl_s cn38xxp2; ++ struct cvmx_stxx_stat_ctl_s cn58xx; ++ struct cvmx_stxx_stat_ctl_s cn58xxp1; ++}; ++ ++union cvmx_stxx_stat_pkt_xmt { ++ uint64_t u64; ++ struct cvmx_stxx_stat_pkt_xmt_s { ++ uint64_t reserved_32_63:32; ++ uint64_t cnt:32; ++ } s; ++ struct cvmx_stxx_stat_pkt_xmt_s cn38xx; ++ struct cvmx_stxx_stat_pkt_xmt_s cn38xxp2; ++ struct cvmx_stxx_stat_pkt_xmt_s cn58xx; ++ struct cvmx_stxx_stat_pkt_xmt_s cn58xxp1; ++}; ++ ++#endif +--- /dev/null ++++ b/drivers/staging/octeon/cvmx-wqe.h +@@ -0,0 +1,397 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++/** ++ * ++ * This header file defines the work queue entry (wqe) data structure. ++ * Since this is a commonly used structure that depends on structures ++ * from several hardware blocks, those definitions have been placed ++ * in this file to create a single point of definition of the wqe ++ * format. ++ * Data structures are still named according to the block that they ++ * relate to. ++ * ++ */ ++ ++#ifndef __CVMX_WQE_H__ ++#define __CVMX_WQE_H__ ++ ++#include "cvmx-packet.h" ++ ++ ++#define OCT_TAG_TYPE_STRING(x) \ ++ (((x) == CVMX_POW_TAG_TYPE_ORDERED) ? "ORDERED" : \ ++ (((x) == CVMX_POW_TAG_TYPE_ATOMIC) ? "ATOMIC" : \ ++ (((x) == CVMX_POW_TAG_TYPE_NULL) ? "NULL" : \ ++ "NULL_NULL"))) ++ ++/** ++ * HW decode / err_code in work queue entry ++ */ ++typedef union { ++ uint64_t u64; ++ ++ /* Use this struct if the hardware determines that the packet is IP */ ++ struct { ++ /* HW sets this to the number of buffers used by this packet */ ++ uint64_t bufs:8; ++ /* HW sets to the number of L2 bytes prior to the IP */ ++ uint64_t ip_offset:8; ++ /* set to 1 if we found DSA/VLAN in the L2 */ ++ uint64_t vlan_valid:1; ++ /* Set to 1 if the DSA/VLAN tag is stacked */ ++ uint64_t vlan_stacked:1; ++ uint64_t unassigned:1; ++ /* HW sets to the DSA/VLAN CFI flag (valid when vlan_valid) */ ++ uint64_t vlan_cfi:1; ++ /* HW sets to the DSA/VLAN_ID field (valid when vlan_valid) */ ++ uint64_t vlan_id:12; ++ /* Ring Identifier (if PCIe). Requires PIP_GBL_CTL[RING_EN]=1 */ ++ uint64_t pr:4; ++ uint64_t unassigned2:8; ++ /* the packet needs to be decompressed */ ++ uint64_t dec_ipcomp:1; ++ /* the packet is either TCP or UDP */ ++ uint64_t tcp_or_udp:1; ++ /* the packet needs to be decrypted (ESP or AH) */ ++ uint64_t dec_ipsec:1; ++ /* the packet is IPv6 */ ++ uint64_t is_v6:1; ++ ++ /* ++ * (rcv_error, not_IP, IP_exc, is_frag, L4_error, ++ * software, etc.). ++ */ ++ ++ /* ++ * reserved for software use, hardware will clear on ++ * packet creation. ++ */ ++ uint64_t software:1; ++ /* exceptional conditions below */ ++ /* the receive interface hardware detected an L4 error ++ * (only applies if !is_frag) (only applies if ++ * !rcv_error && !not_IP && !IP_exc && !is_frag) ++ * failure indicated in err_code below, decode: ++ * ++ * - 1 = Malformed L4 ++ * - 2 = L4 Checksum Error: the L4 checksum value is ++ * - 3 = UDP Length Error: The UDP length field would ++ * make the UDP data longer than what remains in ++ * the IP packet (as defined by the IP header ++ * length field). ++ * - 4 = Bad L4 Port: either the source or destination ++ * TCP/UDP port is 0. ++ * - 8 = TCP FIN Only: the packet is TCP and only the ++ * FIN flag set. ++ * - 9 = TCP No Flags: the packet is TCP and no flags ++ * are set. ++ * - 10 = TCP FIN RST: the packet is TCP and both FIN ++ * and RST are set. ++ * - 11 = TCP SYN URG: the packet is TCP and both SYN ++ * and URG are set. ++ * - 12 = TCP SYN RST: the packet is TCP and both SYN ++ * and RST are set. ++ * - 13 = TCP SYN FIN: the packet is TCP and both SYN ++ * and FIN are set. ++ */ ++ uint64_t L4_error:1; ++ /* set if the packet is a fragment */ ++ uint64_t is_frag:1; ++ /* the receive interface hardware detected an IP error ++ * / exception (only applies if !rcv_error && !not_IP) ++ * failure indicated in err_code below, decode: ++ * ++ * - 1 = Not IP: the IP version field is neither 4 nor ++ * 6. ++ * - 2 = IPv4 Header Checksum Error: the IPv4 header ++ * has a checksum violation. ++ * - 3 = IP Malformed Header: the packet is not long ++ * enough to contain the IP header. ++ * - 4 = IP Malformed: the packet is not long enough ++ * to contain the bytes indicated by the IP ++ * header. Pad is allowed. ++ * - 5 = IP TTL Hop: the IPv4 TTL field or the IPv6 ++ * Hop Count field are zero. ++ * - 6 = IP Options ++ */ ++ uint64_t IP_exc:1; ++ /* ++ * Set if the hardware determined that the packet is a ++ * broadcast. ++ */ ++ uint64_t is_bcast:1; ++ /* ++ * St if the hardware determined that the packet is a ++ * multi-cast. ++ */ ++ uint64_t is_mcast:1; ++ /* ++ * Set if the packet may not be IP (must be zero in ++ * this case). ++ */ ++ uint64_t not_IP:1; ++ /* ++ * The receive interface hardware detected a receive ++ * error (must be zero in this case). ++ */ ++ uint64_t rcv_error:1; ++ /* lower err_code = first-level descriptor of the ++ * work */ ++ /* zero for packet submitted by hardware that isn't on ++ * the slow path */ ++ /* type is cvmx_pip_err_t */ ++ uint64_t err_code:8; ++ } s; ++ ++ /* use this to get at the 16 vlan bits */ ++ struct { ++ uint64_t unused1:16; ++ uint64_t vlan:16; ++ uint64_t unused2:32; ++ } svlan; ++ ++ /* ++ * use this struct if the hardware could not determine that ++ * the packet is ip. ++ */ ++ struct { ++ /* ++ * HW sets this to the number of buffers used by this ++ * packet. ++ */ ++ uint64_t bufs:8; ++ uint64_t unused:8; ++ /* set to 1 if we found DSA/VLAN in the L2 */ ++ uint64_t vlan_valid:1; ++ /* Set to 1 if the DSA/VLAN tag is stacked */ ++ uint64_t vlan_stacked:1; ++ uint64_t unassigned:1; ++ /* ++ * HW sets to the DSA/VLAN CFI flag (valid when ++ * vlan_valid) ++ */ ++ uint64_t vlan_cfi:1; ++ /* ++ * HW sets to the DSA/VLAN_ID field (valid when ++ * vlan_valid). ++ */ ++ uint64_t vlan_id:12; ++ /* ++ * Ring Identifier (if PCIe). Requires ++ * PIP_GBL_CTL[RING_EN]=1 ++ */ ++ uint64_t pr:4; ++ uint64_t unassigned2:12; ++ /* ++ * reserved for software use, hardware will clear on ++ * packet creation. ++ */ ++ uint64_t software:1; ++ uint64_t unassigned3:1; ++ /* ++ * set if the hardware determined that the packet is ++ * rarp. ++ */ ++ uint64_t is_rarp:1; ++ /* ++ * set if the hardware determined that the packet is ++ * arp ++ */ ++ uint64_t is_arp:1; ++ /* ++ * set if the hardware determined that the packet is a ++ * broadcast. ++ */ ++ uint64_t is_bcast:1; ++ /* ++ * set if the hardware determined that the packet is a ++ * multi-cast ++ */ ++ uint64_t is_mcast:1; ++ /* ++ * set if the packet may not be IP (must be one in ++ * this case) ++ */ ++ uint64_t not_IP:1; ++ /* The receive interface hardware detected a receive ++ * error. Failure indicated in err_code below, ++ * decode: ++ * ++ * - 1 = partial error: a packet was partially ++ * received, but internal buffering / bandwidth ++ * was not adequate to receive the entire ++ * packet. ++ * - 2 = jabber error: the RGMII packet was too large ++ * and is truncated. ++ * - 3 = overrun error: the RGMII packet is longer ++ * than allowed and had an FCS error. ++ * - 4 = oversize error: the RGMII packet is longer ++ * than allowed. ++ * - 5 = alignment error: the RGMII packet is not an ++ * integer number of bytes ++ * and had an FCS error (100M and 10M only). ++ * - 6 = fragment error: the RGMII packet is shorter ++ * than allowed and had an FCS error. ++ * - 7 = GMX FCS error: the RGMII packet had an FCS ++ * error. ++ * - 8 = undersize error: the RGMII packet is shorter ++ * than allowed. ++ * - 9 = extend error: the RGMII packet had an extend ++ * error. ++ * - 10 = length mismatch error: the RGMII packet had ++ * a length that did not match the length field ++ * in the L2 HDR. ++ * - 11 = RGMII RX error/SPI4 DIP4 Error: the RGMII ++ * packet had one or more data reception errors ++ * (RXERR) or the SPI4 packet had one or more ++ * DIP4 errors. ++ * - 12 = RGMII skip error/SPI4 Abort Error: the RGMII ++ * packet was not large enough to cover the ++ * skipped bytes or the SPI4 packet was ++ * terminated with an About EOPS. ++ * - 13 = RGMII nibble error/SPI4 Port NXA Error: the ++ * RGMII packet had a studder error (data not ++ * repeated - 10/100M only) or the SPI4 packet ++ * was sent to an NXA. ++ * - 16 = FCS error: a SPI4.2 packet had an FCS error. ++ * - 17 = Skip error: a packet was not large enough to ++ * cover the skipped bytes. ++ * - 18 = L2 header malformed: the packet is not long ++ * enough to contain the L2. ++ */ ++ ++ uint64_t rcv_error:1; ++ /* ++ * lower err_code = first-level descriptor of the ++ * work ++ */ ++ /* ++ * zero for packet submitted by hardware that isn't on ++ * the slow path ++ */ ++ /* type is cvmx_pip_err_t (union, so can't use directly */ ++ uint64_t err_code:8; ++ } snoip; ++ ++} cvmx_pip_wqe_word2; ++ ++/** ++ * Work queue entry format ++ * ++ * must be 8-byte aligned ++ */ ++typedef struct { ++ ++ /***************************************************************** ++ * WORD 0 ++ * HW WRITE: the following 64 bits are filled by HW when a packet arrives ++ */ ++ ++ /** ++ * raw chksum result generated by the HW ++ */ ++ uint16_t hw_chksum; ++ /** ++ * Field unused by hardware - available for software ++ */ ++ uint8_t unused; ++ /** ++ * Next pointer used by hardware for list maintenance. ++ * May be written/read by HW before the work queue ++ * entry is scheduled to a PP ++ * (Only 36 bits used in Octeon 1) ++ */ ++ uint64_t next_ptr:40; ++ ++ /***************************************************************** ++ * WORD 1 ++ * HW WRITE: the following 64 bits are filled by HW when a packet arrives ++ */ ++ ++ /** ++ * HW sets to the total number of bytes in the packet ++ */ ++ uint64_t len:16; ++ /** ++ * HW sets this to input physical port ++ */ ++ uint64_t ipprt:6; ++ ++ /** ++ * HW sets this to what it thought the priority of the input packet was ++ */ ++ uint64_t qos:3; ++ ++ /** ++ * the group that the work queue entry will be scheduled to ++ */ ++ uint64_t grp:4; ++ /** ++ * the type of the tag (ORDERED, ATOMIC, NULL) ++ */ ++ uint64_t tag_type:3; ++ /** ++ * the synchronization/ordering tag ++ */ ++ uint64_t tag:32; ++ ++ /** ++ * WORD 2 HW WRITE: the following 64-bits are filled in by ++ * hardware when a packet arrives This indicates a variety of ++ * status and error conditions. ++ */ ++ cvmx_pip_wqe_word2 word2; ++ ++ /** ++ * Pointer to the first segment of the packet. ++ */ ++ union cvmx_buf_ptr packet_ptr; ++ ++ /** ++ * HW WRITE: octeon will fill in a programmable amount from the ++ * packet, up to (at most, but perhaps less) the amount ++ * needed to fill the work queue entry to 128 bytes ++ * ++ * If the packet is recognized to be IP, the hardware starts ++ * (except that the IPv4 header is padded for appropriate ++ * alignment) writing here where the IP header starts. If the ++ * packet is not recognized to be IP, the hardware starts ++ * writing the beginning of the packet here. ++ */ ++ uint8_t packet_data[96]; ++ ++ /** ++ * If desired, SW can make the work Q entry any length. For the ++ * purposes of discussion here, Assume 128B always, as this is all that ++ * the hardware deals with. ++ * ++ */ ++ ++} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_t; ++ ++#endif /* __CVMX_WQE_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-common.c +@@ -0,0 +1,328 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "ethernet-defines.h" ++#include "ethernet-tx.h" ++#include "ethernet-mdio.h" ++#include "ethernet-util.h" ++#include "octeon-ethernet.h" ++#include "ethernet-common.h" ++ ++#include "cvmx-pip.h" ++#include "cvmx-pko.h" ++#include "cvmx-fau.h" ++#include "cvmx-helper.h" ++ ++#include "cvmx-gmxx-defs.h" ++ ++/** ++ * Get the low level ethernet statistics ++ * ++ * @dev: Device to get the statistics from ++ * Returns Pointer to the statistics ++ */ ++static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) ++{ ++ cvmx_pip_port_status_t rx_status; ++ cvmx_pko_port_status_t tx_status; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ ++ if (priv->port < CVMX_PIP_NUM_INPUT_PORTS) { ++ if (octeon_is_simulation()) { ++ /* The simulator doesn't support statistics */ ++ memset(&rx_status, 0, sizeof(rx_status)); ++ memset(&tx_status, 0, sizeof(tx_status)); ++ } else { ++ cvmx_pip_get_port_status(priv->port, 1, &rx_status); ++ cvmx_pko_get_port_status(priv->port, 1, &tx_status); ++ } ++ ++ priv->stats.rx_packets += rx_status.inb_packets; ++ priv->stats.tx_packets += tx_status.packets; ++ priv->stats.rx_bytes += rx_status.inb_octets; ++ priv->stats.tx_bytes += tx_status.octets; ++ priv->stats.multicast += rx_status.multicast_packets; ++ priv->stats.rx_crc_errors += rx_status.inb_errors; ++ priv->stats.rx_frame_errors += rx_status.fcs_align_err_packets; ++ ++ /* ++ * The drop counter must be incremented atomically ++ * since the RX tasklet also increments it. ++ */ ++#ifdef CONFIG_64BIT ++ atomic64_add(rx_status.dropped_packets, ++ (atomic64_t *)&priv->stats.rx_dropped); ++#else ++ atomic_add(rx_status.dropped_packets, ++ (atomic_t *)&priv->stats.rx_dropped); ++#endif ++ } ++ ++ return &priv->stats; ++} ++ ++/** ++ * Set the multicast list. Currently unimplemented. ++ * ++ * @dev: Device to work on ++ */ ++static void cvm_oct_common_set_multicast_list(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ if ((interface < 2) ++ && (cvmx_helper_interface_get_mode(interface) != ++ CVMX_HELPER_INTERFACE_MODE_SPI)) { ++ union cvmx_gmxx_rxx_adr_ctl control; ++ control.u64 = 0; ++ control.s.bcst = 1; /* Allow broadcast MAC addresses */ ++ ++ if (dev->mc_list || (dev->flags & IFF_ALLMULTI) || ++ (dev->flags & IFF_PROMISC)) ++ /* Force accept multicast packets */ ++ control.s.mcst = 2; ++ else ++ /* Force reject multicat packets */ ++ control.s.mcst = 1; ++ ++ if (dev->flags & IFF_PROMISC) ++ /* ++ * Reject matches if promisc. Since CAM is ++ * shut off, should accept everything. ++ */ ++ control.s.cam_mode = 0; ++ else ++ /* Filter packets based on the CAM */ ++ control.s.cam_mode = 1; ++ ++ gmx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), ++ gmx_cfg.u64 & ~1ull); ++ ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), ++ control.u64); ++ if (dev->flags & IFF_PROMISC) ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN ++ (index, interface), 0); ++ else ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN ++ (index, interface), 1); ++ ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), ++ gmx_cfg.u64); ++ } ++} ++ ++/** ++ * Set the hardware MAC address for a device ++ * ++ * @dev: Device to change the MAC address for ++ * @addr: Address structure to change it too. MAC address is addr + 2. ++ * Returns Zero on success ++ */ ++static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ memcpy(dev->dev_addr, addr + 2, 6); ++ ++ if ((interface < 2) ++ && (cvmx_helper_interface_get_mode(interface) != ++ CVMX_HELPER_INTERFACE_MODE_SPI)) { ++ int i; ++ uint8_t *ptr = addr; ++ uint64_t mac = 0; ++ for (i = 0; i < 6; i++) ++ mac = (mac << 8) | (uint64_t) (ptr[i + 2]); ++ ++ gmx_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), ++ gmx_cfg.u64 & ~1ull); ++ ++ cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), ++ ptr[2]); ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), ++ ptr[3]); ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), ++ ptr[4]); ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), ++ ptr[5]); ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), ++ ptr[6]); ++ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), ++ ptr[7]); ++ cvm_oct_common_set_multicast_list(dev); ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), ++ gmx_cfg.u64); ++ } ++ return 0; ++} ++ ++/** ++ * Change the link MTU. Unimplemented ++ * ++ * @dev: Device to change ++ * @new_mtu: The new MTU ++ * ++ * Returns Zero on success ++ */ ++static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++ int vlan_bytes = 4; ++#else ++ int vlan_bytes = 0; ++#endif ++ ++ /* ++ * Limit the MTU to make sure the ethernet packets are between ++ * 64 bytes and 65535 bytes. ++ */ ++ if ((new_mtu + 14 + 4 + vlan_bytes < 64) ++ || (new_mtu + 14 + 4 + vlan_bytes > 65392)) { ++ pr_err("MTU must be between %d and %d.\n", ++ 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); ++ return -EINVAL; ++ } ++ dev->mtu = new_mtu; ++ ++ if ((interface < 2) ++ && (cvmx_helper_interface_get_mode(interface) != ++ CVMX_HELPER_INTERFACE_MODE_SPI)) { ++ /* Add ethernet header and FCS, and VLAN if configured. */ ++ int max_packet = new_mtu + 14 + 4 + vlan_bytes; ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN3XXX) ++ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ /* Signal errors on packets larger than the MTU */ ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), ++ max_packet); ++ } else { ++ /* ++ * Set the hardware to truncate packets larger ++ * than the MTU and smaller the 64 bytes. ++ */ ++ union cvmx_pip_frm_len_chkx frm_len_chk; ++ frm_len_chk.u64 = 0; ++ frm_len_chk.s.minlen = 64; ++ frm_len_chk.s.maxlen = max_packet; ++ cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), ++ frm_len_chk.u64); ++ } ++ /* ++ * Set the hardware to truncate packets larger than ++ * the MTU. The jabber register must be set to a ++ * multiple of 8 bytes, so round up. ++ */ ++ cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), ++ (max_packet + 7) & ~7u); ++ } ++ return 0; ++} ++ ++/** ++ * Per network device initialization ++ * ++ * @dev: Device to initialize ++ * Returns Zero on success ++ */ ++int cvm_oct_common_init(struct net_device *dev) ++{ ++ static int count; ++ char mac[8] = { 0x00, 0x00, ++ octeon_bootinfo->mac_addr_base[0], ++ octeon_bootinfo->mac_addr_base[1], ++ octeon_bootinfo->mac_addr_base[2], ++ octeon_bootinfo->mac_addr_base[3], ++ octeon_bootinfo->mac_addr_base[4], ++ octeon_bootinfo->mac_addr_base[5] + count ++ }; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ ++ /* ++ * Force the interface to use the POW send if always_use_pow ++ * was specified or it is in the pow send list. ++ */ ++ if ((pow_send_group != -1) ++ && (always_use_pow || strstr(pow_send_list, dev->name))) ++ priv->queue = -1; ++ ++ if (priv->queue != -1) { ++ dev->hard_start_xmit = cvm_oct_xmit; ++ if (USE_HW_TCPUDP_CHECKSUM) ++ dev->features |= NETIF_F_IP_CSUM; ++ } else ++ dev->hard_start_xmit = cvm_oct_xmit_pow; ++ count++; ++ ++ dev->get_stats = cvm_oct_common_get_stats; ++ dev->set_mac_address = cvm_oct_common_set_mac_address; ++ dev->set_multicast_list = cvm_oct_common_set_multicast_list; ++ dev->change_mtu = cvm_oct_common_change_mtu; ++ dev->do_ioctl = cvm_oct_ioctl; ++ /* We do our own locking, Linux doesn't need to */ ++ dev->features |= NETIF_F_LLTX; ++ SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ dev->poll_controller = cvm_oct_poll_controller; ++#endif ++ ++ cvm_oct_mdio_setup_device(dev); ++ dev->set_mac_address(dev, mac); ++ dev->change_mtu(dev, dev->mtu); ++ ++ /* ++ * Zero out stats for port so we won't mistakenly show ++ * counters from the bootloader. ++ */ ++ memset(dev->get_stats(dev), 0, sizeof(struct net_device_stats)); ++ ++ return 0; ++} ++ ++void cvm_oct_common_uninit(struct net_device *dev) ++{ ++ /* Currently nothing to do */ ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-common.h +@@ -0,0 +1,29 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++ ++int cvm_oct_common_init(struct net_device *dev); ++void cvm_oct_common_uninit(struct net_device *dev); +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-defines.h +@@ -0,0 +1,134 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++ ++/* ++ * A few defines are used to control the operation of this driver: ++ * CONFIG_CAVIUM_RESERVE32 ++ * This kernel config options controls the amount of memory configured ++ * in a wired TLB entry for all processes to share. If this is set, the ++ * driver will use this memory instead of kernel memory for pools. This ++ * allows 32bit userspace application to access the buffers, but also ++ * requires all received packets to be copied. ++ * CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS ++ * This kernel config option allows the user to control the number of ++ * packet and work queue buffers allocated by the driver. If this is zero, ++ * the driver uses the default from below. ++ * USE_SKBUFFS_IN_HW ++ * Tells the driver to populate the packet buffers with kernel skbuffs. ++ * This allows the driver to receive packets without copying them. It also ++ * means that 32bit userspace can't access the packet buffers. ++ * USE_32BIT_SHARED ++ * This define tells the driver to allocate memory for buffers from the ++ * 32bit sahred region instead of the kernel memory space. ++ * USE_HW_TCPUDP_CHECKSUM ++ * Controls if the Octeon TCP/UDP checksum engine is used for packet ++ * output. If this is zero, the kernel will perform the checksum in ++ * software. ++ * USE_MULTICORE_RECEIVE ++ * Process receive interrupts on multiple cores. This spreads the network ++ * load across the first 8 processors. If ths is zero, only one core ++ * processes incomming packets. ++ * USE_ASYNC_IOBDMA ++ * Use asynchronous IO access to hardware. This uses Octeon's asynchronous ++ * IOBDMAs to issue IO accesses without stalling. Set this to zero ++ * to disable this. Note that IOBDMAs require CVMSEG. ++ * REUSE_SKBUFFS_WITHOUT_FREE ++ * Allows the TX path to free an skbuff into the FPA hardware pool. This ++ * can significantly improve performance for forwarding and bridging, but ++ * may be somewhat dangerous. Checks are made, but if any buffer is reused ++ * without the proper Linux cleanup, the networking stack may have very ++ * bizarre bugs. ++ */ ++#ifndef __ETHERNET_DEFINES_H__ ++#define __ETHERNET_DEFINES_H__ ++ ++#include "cvmx-config.h" ++ ++ ++#define OCTEON_ETHERNET_VERSION "1.9" ++ ++#ifndef CONFIG_CAVIUM_RESERVE32 ++#define CONFIG_CAVIUM_RESERVE32 0 ++#endif ++ ++#if CONFIG_CAVIUM_RESERVE32 ++#define USE_32BIT_SHARED 1 ++#define USE_SKBUFFS_IN_HW 0 ++#define REUSE_SKBUFFS_WITHOUT_FREE 0 ++#else ++#define USE_32BIT_SHARED 0 ++#define USE_SKBUFFS_IN_HW 1 ++#ifdef CONFIG_NETFILTER ++#define REUSE_SKBUFFS_WITHOUT_FREE 0 ++#else ++#define REUSE_SKBUFFS_WITHOUT_FREE 1 ++#endif ++#endif ++ ++/* Max interrupts per second per core */ ++#define INTERRUPT_LIMIT 10000 ++ ++/* Don't limit the number of interrupts */ ++/*#define INTERRUPT_LIMIT 0 */ ++#define USE_HW_TCPUDP_CHECKSUM 1 ++ ++#define USE_MULTICORE_RECEIVE 1 ++ ++/* Enable Random Early Dropping under load */ ++#define USE_RED 1 ++#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) ++ ++/* ++ * Allow SW based preamble removal at 10Mbps to workaround PHYs giving ++ * us bad preambles. ++ */ ++#define USE_10MBPS_PREAMBLE_WORKAROUND 1 ++/* ++ * Use this to have all FPA frees also tell the L2 not to write data ++ * to memory. ++ */ ++#define DONT_WRITEBACK(x) (x) ++/* Use this to not have FPA frees control L2 */ ++/*#define DONT_WRITEBACK(x) 0 */ ++ ++/* Maximum number of packets to process per interrupt. */ ++#define MAX_RX_PACKETS 120 ++#define MAX_OUT_QUEUE_DEPTH 1000 ++ ++#ifndef CONFIG_SMP ++#undef USE_MULTICORE_RECEIVE ++#define USE_MULTICORE_RECEIVE 0 ++#endif ++ ++#define IP_PROTOCOL_TCP 6 ++#define IP_PROTOCOL_UDP 0x11 ++ ++#define FAU_NUM_PACKET_BUFFERS_TO_FREE (CVMX_FAU_REG_END - sizeof(uint32_t)) ++#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS+1) ++ ++ ++#endif /* __ETHERNET_DEFINES_H__ */ +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-mdio.c +@@ -0,0 +1,231 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-mdio.h" ++ ++#include "cvmx-helper-board.h" ++ ++#include "cvmx-smix-defs.h" ++ ++DECLARE_MUTEX(mdio_sem); ++ ++/** ++ * Perform an MII read. Called by the generic MII routines ++ * ++ * @dev: Device to perform read for ++ * @phy_id: The MII phy id ++ * @location: Register location to read ++ * Returns Result from the read or zero on failure ++ */ ++static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_rd_dat smi_rd; ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = 1; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = location; ++ cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); ++ ++ do { ++ if (!in_interrupt()) ++ yield(); ++ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); ++ } while (smi_rd.s.pending); ++ ++ if (smi_rd.s.val) ++ return smi_rd.s.dat; ++ else ++ return 0; ++} ++ ++static int cvm_oct_mdio_dummy_read(struct net_device *dev, int phy_id, ++ int location) ++{ ++ return 0xffff; ++} ++ ++/** ++ * Perform an MII write. Called by the generic MII routines ++ * ++ * @dev: Device to perform write for ++ * @phy_id: The MII phy id ++ * @location: Register location to write ++ * @val: Value to write ++ */ ++static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location, ++ int val) ++{ ++ union cvmx_smix_cmd smi_cmd; ++ union cvmx_smix_wr_dat smi_wr; ++ ++ smi_wr.u64 = 0; ++ smi_wr.s.dat = val; ++ cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); ++ ++ smi_cmd.u64 = 0; ++ smi_cmd.s.phy_op = 0; ++ smi_cmd.s.phy_adr = phy_id; ++ smi_cmd.s.reg_adr = location; ++ cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); ++ ++ do { ++ if (!in_interrupt()) ++ yield(); ++ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); ++ } while (smi_wr.s.pending); ++} ++ ++static void cvm_oct_mdio_dummy_write(struct net_device *dev, int phy_id, ++ int location, int val) ++{ ++} ++ ++static void cvm_oct_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, "cavium-ethernet"); ++ strcpy(info->version, OCTEON_ETHERNET_VERSION); ++ strcpy(info->bus_info, "Builtin"); ++} ++ ++static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int ret; ++ ++ down(&mdio_sem); ++ ret = mii_ethtool_gset(&priv->mii_info, cmd); ++ up(&mdio_sem); ++ ++ return ret; ++} ++ ++static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int ret; ++ ++ down(&mdio_sem); ++ ret = mii_ethtool_sset(&priv->mii_info, cmd); ++ up(&mdio_sem); ++ ++ return ret; ++} ++ ++static int cvm_oct_nway_reset(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int ret; ++ ++ down(&mdio_sem); ++ ret = mii_nway_restart(&priv->mii_info); ++ up(&mdio_sem); ++ ++ return ret; ++} ++ ++static u32 cvm_oct_get_link(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ u32 ret; ++ ++ down(&mdio_sem); ++ ret = mii_link_ok(&priv->mii_info); ++ up(&mdio_sem); ++ ++ return ret; ++} ++ ++struct ethtool_ops cvm_oct_ethtool_ops = { ++ .get_drvinfo = cvm_oct_get_drvinfo, ++ .get_settings = cvm_oct_get_settings, ++ .set_settings = cvm_oct_set_settings, ++ .nway_reset = cvm_oct_nway_reset, ++ .get_link = cvm_oct_get_link, ++ .get_sg = ethtool_op_get_sg, ++ .get_tx_csum = ethtool_op_get_tx_csum, ++}; ++ ++/** ++ * IOCTL support for PHY control ++ * ++ * @dev: Device to change ++ * @rq: the request ++ * @cmd: the command ++ * Returns Zero on success ++ */ ++int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ struct mii_ioctl_data *data = if_mii(rq); ++ unsigned int duplex_chg; ++ int ret; ++ ++ down(&mdio_sem); ++ ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg); ++ up(&mdio_sem); ++ ++ return ret; ++} ++ ++/** ++ * Setup the MDIO device structures ++ * ++ * @dev: Device to setup ++ * ++ * Returns Zero on success, negative on failure ++ */ ++int cvm_oct_mdio_setup_device(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int phy_id = cvmx_helper_board_get_mii_address(priv->port); ++ if (phy_id != -1) { ++ priv->mii_info.dev = dev; ++ priv->mii_info.phy_id = phy_id; ++ priv->mii_info.phy_id_mask = 0xff; ++ priv->mii_info.supports_gmii = 1; ++ priv->mii_info.reg_num_mask = 0x1f; ++ priv->mii_info.mdio_read = cvm_oct_mdio_read; ++ priv->mii_info.mdio_write = cvm_oct_mdio_write; ++ } else { ++ /* Supply dummy MDIO routines so the kernel won't crash ++ if the user tries to read them */ ++ priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read; ++ priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write; ++ } ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-mdio.h +@@ -0,0 +1,46 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_XFRM ++#include ++#include ++#endif /* CONFIG_XFRM */ ++ ++extern struct ethtool_ops cvm_oct_ethtool_ops; ++int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); ++int cvm_oct_mdio_setup_device(struct net_device *dev); +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-mem.c +@@ -0,0 +1,198 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++ ++#include "cvmx-fpa.h" ++ ++/** ++ * Fill the supplied hardware pool with skbuffs ++ * ++ * @pool: Pool to allocate an skbuff for ++ * @size: Size of the buffer needed for the pool ++ * @elements: Number of buffers to allocate ++ */ ++static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements) ++{ ++ int freed = elements; ++ while (freed) { ++ ++ struct sk_buff *skb = dev_alloc_skb(size + 128); ++ if (unlikely(skb == NULL)) { ++ pr_warning ++ ("Failed to allocate skb for hardware pool %d\n", ++ pool); ++ break; ++ } ++ ++ skb_reserve(skb, 128 - (((unsigned long)skb->data) & 0x7f)); ++ *(struct sk_buff **)(skb->data - sizeof(void *)) = skb; ++ cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128)); ++ freed--; ++ } ++ return elements - freed; ++} ++ ++/** ++ * Free the supplied hardware pool of skbuffs ++ * ++ * @pool: Pool to allocate an skbuff for ++ * @size: Size of the buffer needed for the pool ++ * @elements: Number of buffers to allocate ++ */ ++static void cvm_oct_free_hw_skbuff(int pool, int size, int elements) ++{ ++ char *memory; ++ ++ do { ++ memory = cvmx_fpa_alloc(pool); ++ if (memory) { ++ struct sk_buff *skb = ++ *(struct sk_buff **)(memory - sizeof(void *)); ++ elements--; ++ dev_kfree_skb(skb); ++ } ++ } while (memory); ++ ++ if (elements < 0) ++ pr_warning("Freeing of pool %u had too many skbuffs (%d)\n", ++ pool, elements); ++ else if (elements > 0) ++ pr_warning("Freeing of pool %u is missing %d skbuffs\n", ++ pool, elements); ++} ++ ++/** ++ * This function fills a hardware pool with memory. Depending ++ * on the config defines, this memory might come from the ++ * kernel or global 32bit memory allocated with ++ * cvmx_bootmem_alloc. ++ * ++ * @pool: Pool to populate ++ * @size: Size of each buffer in the pool ++ * @elements: Number of buffers to allocate ++ */ ++static int cvm_oct_fill_hw_memory(int pool, int size, int elements) ++{ ++ char *memory; ++ int freed = elements; ++ ++ if (USE_32BIT_SHARED) { ++ extern uint64_t octeon_reserve32_memory; ++ ++ memory = ++ cvmx_bootmem_alloc_range(elements * size, 128, ++ octeon_reserve32_memory, ++ octeon_reserve32_memory + ++ (CONFIG_CAVIUM_RESERVE32 << 20) - ++ 1); ++ if (memory == NULL) ++ panic("Unable to allocate %u bytes for FPA pool %d\n", ++ elements * size, pool); ++ ++ pr_notice("Memory range %p - %p reserved for " ++ "hardware\n", memory, ++ memory + elements * size - 1); ++ ++ while (freed) { ++ cvmx_fpa_free(memory, pool, 0); ++ memory += size; ++ freed--; ++ } ++ } else { ++ while (freed) { ++ /* We need to force alignment to 128 bytes here */ ++ memory = kmalloc(size + 127, GFP_ATOMIC); ++ if (unlikely(memory == NULL)) { ++ pr_warning("Unable to allocate %u bytes for " ++ "FPA pool %d\n", ++ elements * size, pool); ++ break; ++ } ++ memory = (char *)(((unsigned long)memory + 127) & -128); ++ cvmx_fpa_free(memory, pool, 0); ++ freed--; ++ } ++ } ++ return elements - freed; ++} ++ ++/** ++ * Free memory previously allocated with cvm_oct_fill_hw_memory ++ * ++ * @pool: FPA pool to free ++ * @size: Size of each buffer in the pool ++ * @elements: Number of buffers that should be in the pool ++ */ ++static void cvm_oct_free_hw_memory(int pool, int size, int elements) ++{ ++ if (USE_32BIT_SHARED) { ++ pr_warning("Warning: 32 shared memory is not freeable\n"); ++ } else { ++ char *memory; ++ do { ++ memory = cvmx_fpa_alloc(pool); ++ if (memory) { ++ elements--; ++ kfree(phys_to_virt(cvmx_ptr_to_phys(memory))); ++ } ++ } while (memory); ++ ++ if (elements < 0) ++ pr_warning("Freeing of pool %u had too many " ++ "buffers (%d)\n", ++ pool, elements); ++ else if (elements > 0) ++ pr_warning("Warning: Freeing of pool %u is " ++ "missing %d buffers\n", ++ pool, elements); ++ } ++} ++ ++int cvm_oct_mem_fill_fpa(int pool, int size, int elements) ++{ ++ int freed; ++ if (USE_SKBUFFS_IN_HW) ++ freed = cvm_oct_fill_hw_skbuff(pool, size, elements); ++ else ++ freed = cvm_oct_fill_hw_memory(pool, size, elements); ++ return freed; ++} ++ ++void cvm_oct_mem_empty_fpa(int pool, int size, int elements) ++{ ++ if (USE_SKBUFFS_IN_HW) ++ cvm_oct_free_hw_skbuff(pool, size, elements); ++ else ++ cvm_oct_free_hw_memory(pool, size, elements); ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-mem.h +@@ -0,0 +1,29 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++********************************************************************/ ++ ++int cvm_oct_mem_fill_fpa(int pool, int size, int elements); ++void cvm_oct_mem_empty_fpa(int pool, int size, int elements); +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-proc.c +@@ -0,0 +1,256 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "octeon-ethernet.h" ++#include "ethernet-defines.h" ++ ++#include "cvmx-helper.h" ++#include "cvmx-pip.h" ++ ++static unsigned long long cvm_oct_stats_read_switch(struct net_device *dev, ++ int phy_id, int offset) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ ++ priv->mii_info.mdio_write(dev, phy_id, 0x1d, 0xcc00 | offset); ++ return ((uint64_t) priv->mii_info. ++ mdio_read(dev, phy_id, ++ 0x1e) << 16) | (uint64_t) priv->mii_info. ++ mdio_read(dev, phy_id, 0x1f); ++} ++ ++static int cvm_oct_stats_switch_show(struct seq_file *m, void *v) ++{ ++ static const int ports[] = { 0, 1, 2, 3, 9, -1 }; ++ struct net_device *dev = cvm_oct_device[0]; ++ int index = 0; ++ ++ while (ports[index] != -1) { ++ ++ /* Latch port */ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ ++ priv->mii_info.mdio_write(dev, 0x1b, 0x1d, ++ 0xdc00 | ports[index]); ++ seq_printf(m, "\nSwitch Port %d\n", ports[index]); ++ seq_printf(m, "InGoodOctets: %12llu\t" ++ "OutOctets: %12llu\t" ++ "64 Octets: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, ++ 0x00) | ++ (cvm_oct_stats_read_switch(dev, 0x1b, 0x01) << 32), ++ cvm_oct_stats_read_switch(dev, 0x1b, ++ 0x0E) | ++ (cvm_oct_stats_read_switch(dev, 0x1b, 0x0F) << 32), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x08)); ++ ++ seq_printf(m, "InBadOctets: %12llu\t" ++ "OutUnicast: %12llu\t" ++ "65-127 Octets: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x02), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x10), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x09)); ++ ++ seq_printf(m, "InUnicast: %12llu\t" ++ "OutBroadcasts: %12llu\t" ++ "128-255 Octets: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x04), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x13), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x0A)); ++ ++ seq_printf(m, "InBroadcasts: %12llu\t" ++ "OutMulticasts: %12llu\t" ++ "256-511 Octets: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x06), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x12), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x0B)); ++ ++ seq_printf(m, "InMulticasts: %12llu\t" ++ "OutPause: %12llu\t" ++ "512-1023 Octets:%12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x07), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x15), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x0C)); ++ ++ seq_printf(m, "InPause: %12llu\t" ++ "Excessive: %12llu\t" ++ "1024-Max Octets:%12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x16), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x11), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x0D)); ++ ++ seq_printf(m, "InUndersize: %12llu\t" ++ "Collisions: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x18), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x1E)); ++ ++ seq_printf(m, "InFragments: %12llu\t" ++ "Deferred: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x19), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x05)); ++ ++ seq_printf(m, "InOversize: %12llu\t" ++ "Single: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x1A), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x14)); ++ ++ seq_printf(m, "InJabber: %12llu\t" ++ "Multiple: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x1B), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x17)); ++ ++ seq_printf(m, "In RxErr: %12llu\t" ++ "OutFCSErr: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x1C), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x03)); ++ ++ seq_printf(m, "InFCSErr: %12llu\t" ++ "Late: %12llu\n", ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x1D), ++ cvm_oct_stats_read_switch(dev, 0x1b, 0x1F)); ++ index++; ++ } ++ return 0; ++} ++ ++/** ++ * User is reading /proc/octeon_ethernet_stats ++ * ++ * @m: ++ * @v: ++ * Returns ++ */ ++static int cvm_oct_stats_show(struct seq_file *m, void *v) ++{ ++ struct octeon_ethernet *priv; ++ int port; ++ ++ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { ++ ++ if (cvm_oct_device[port]) { ++ priv = netdev_priv(cvm_oct_device[port]); ++ ++ seq_printf(m, "\nOcteon Port %d (%s)\n", port, ++ cvm_oct_device[port]->name); ++ seq_printf(m, ++ "rx_packets: %12lu\t" ++ "tx_packets: %12lu\n", ++ priv->stats.rx_packets, ++ priv->stats.tx_packets); ++ seq_printf(m, ++ "rx_bytes: %12lu\t" ++ "tx_bytes: %12lu\n", ++ priv->stats.rx_bytes, priv->stats.tx_bytes); ++ seq_printf(m, ++ "rx_errors: %12lu\t" ++ "tx_errors: %12lu\n", ++ priv->stats.rx_errors, ++ priv->stats.tx_errors); ++ seq_printf(m, ++ "rx_dropped: %12lu\t" ++ "tx_dropped: %12lu\n", ++ priv->stats.rx_dropped, ++ priv->stats.tx_dropped); ++ seq_printf(m, ++ "rx_length_errors: %12lu\t" ++ "tx_aborted_errors: %12lu\n", ++ priv->stats.rx_length_errors, ++ priv->stats.tx_aborted_errors); ++ seq_printf(m, ++ "rx_over_errors: %12lu\t" ++ "tx_carrier_errors: %12lu\n", ++ priv->stats.rx_over_errors, ++ priv->stats.tx_carrier_errors); ++ seq_printf(m, ++ "rx_crc_errors: %12lu\t" ++ "tx_fifo_errors: %12lu\n", ++ priv->stats.rx_crc_errors, ++ priv->stats.tx_fifo_errors); ++ seq_printf(m, ++ "rx_frame_errors: %12lu\t" ++ "tx_heartbeat_errors: %12lu\n", ++ priv->stats.rx_frame_errors, ++ priv->stats.tx_heartbeat_errors); ++ seq_printf(m, ++ "rx_fifo_errors: %12lu\t" ++ "tx_window_errors: %12lu\n", ++ priv->stats.rx_fifo_errors, ++ priv->stats.tx_window_errors); ++ seq_printf(m, ++ "rx_missed_errors: %12lu\t" ++ "multicast: %12lu\n", ++ priv->stats.rx_missed_errors, ++ priv->stats.multicast); ++ } ++ } ++ ++ if (cvm_oct_device[0]) { ++ priv = netdev_priv(cvm_oct_device[0]); ++ if (priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) ++ cvm_oct_stats_switch_show(m, v); ++ } ++ return 0; ++} ++ ++/** ++ * /proc/octeon_ethernet_stats was openned. Use the single_open iterator ++ * ++ * @inode: ++ * @file: ++ * Returns ++ */ ++static int cvm_oct_stats_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, cvm_oct_stats_show, NULL); ++} ++ ++static const struct file_operations cvm_oct_stats_operations = { ++ .open = cvm_oct_stats_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++void cvm_oct_proc_initialize(void) ++{ ++ struct proc_dir_entry *entry = ++ create_proc_entry("octeon_ethernet_stats", 0, NULL); ++ if (entry) ++ entry->proc_fops = &cvm_oct_stats_operations; ++} ++ ++void cvm_oct_proc_shutdown(void) ++{ ++ remove_proc_entry("octeon_ethernet_stats", NULL); ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-proc.h +@@ -0,0 +1,29 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++ ++void cvm_oct_proc_initialize(void); ++void cvm_oct_proc_shutdown(void); +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-rgmii.c +@@ -0,0 +1,397 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-common.h" ++#include "ethernet-util.h" ++ ++#include "cvmx-helper.h" ++ ++#include ++#include ++#include "cvmx-gmxx-defs.h" ++ ++DEFINE_SPINLOCK(global_register_lock); ++ ++static int number_rgmii_ports; ++ ++static void cvm_oct_rgmii_poll(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ unsigned long flags; ++ cvmx_helper_link_info_t link_info; ++ ++ /* ++ * Take the global register lock since we are going to touch ++ * registers that affect more than one port. ++ */ ++ spin_lock_irqsave(&global_register_lock, flags); ++ ++ link_info = cvmx_helper_link_get(priv->port); ++ if (link_info.u64 == priv->link_info) { ++ ++ /* ++ * If the 10Mbps preamble workaround is supported and we're ++ * at 10Mbps we may need to do some special checking. ++ */ ++ if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) { ++ ++ /* ++ * Read the GMXX_RXX_INT_REG[PCTERR] bit and ++ * see if we are getting preamble errors. ++ */ ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; ++ gmxx_rxx_int_reg.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG ++ (index, interface)); ++ if (gmxx_rxx_int_reg.s.pcterr) { ++ ++ /* ++ * We are getting preamble errors at ++ * 10Mbps. Most likely the PHY is ++ * giving us packets with mis aligned ++ * preambles. In order to get these ++ * packets we need to disable preamble ++ * checking and do it in software. ++ */ ++ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; ++ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; ++ ++ /* Disable preamble checking */ ++ gmxx_rxx_frm_ctl.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL ++ (index, interface)); ++ gmxx_rxx_frm_ctl.s.pre_chk = 0; ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL ++ (index, interface), ++ gmxx_rxx_frm_ctl.u64); ++ ++ /* Disable FCS stripping */ ++ ipd_sub_port_fcs.u64 = ++ cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); ++ ipd_sub_port_fcs.s.port_bit &= ++ 0xffffffffull ^ (1ull << priv->port); ++ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ++ ipd_sub_port_fcs.u64); ++ ++ /* Clear any error bits */ ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG ++ (index, interface), ++ gmxx_rxx_int_reg.u64); ++ DEBUGPRINT("%s: Using 10Mbps with software " ++ "preamble removal\n", ++ dev->name); ++ } ++ } ++ spin_unlock_irqrestore(&global_register_lock, flags); ++ return; ++ } ++ ++ /* If the 10Mbps preamble workaround is allowed we need to on ++ preamble checking, FCS stripping, and clear error bits on ++ every speed change. If errors occur during 10Mbps operation ++ the above code will change this stuff */ ++ if (USE_10MBPS_PREAMBLE_WORKAROUND) { ++ ++ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; ++ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; ++ union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ /* Enable preamble checking */ ++ gmxx_rxx_frm_ctl.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); ++ gmxx_rxx_frm_ctl.s.pre_chk = 1; ++ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), ++ gmxx_rxx_frm_ctl.u64); ++ /* Enable FCS stripping */ ++ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); ++ ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; ++ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); ++ /* Clear any error bits */ ++ gmxx_rxx_int_reg.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface)); ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), ++ gmxx_rxx_int_reg.u64); ++ } ++ ++ link_info = cvmx_helper_link_autoconf(priv->port); ++ priv->link_info = link_info.u64; ++ spin_unlock_irqrestore(&global_register_lock, flags); ++ ++ /* Tell Linux */ ++ if (link_info.s.link_up) { ++ ++ if (!netif_carrier_ok(dev)) ++ netif_carrier_on(dev); ++ if (priv->queue != -1) ++ DEBUGPRINT ++ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", ++ dev->name, link_info.s.speed, ++ (link_info.s.full_duplex) ? "Full" : "Half", ++ priv->port, priv->queue); ++ else ++ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", ++ dev->name, link_info.s.speed, ++ (link_info.s.full_duplex) ? "Full" : "Half", ++ priv->port); ++ } else { ++ ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); ++ DEBUGPRINT("%s: Link down\n", dev->name); ++ } ++} ++ ++static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) ++{ ++ union cvmx_npi_rsl_int_blocks rsl_int_blocks; ++ int index; ++ irqreturn_t return_status = IRQ_NONE; ++ ++ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); ++ ++ /* Check and see if this interrupt was caused by the GMX0 block */ ++ if (rsl_int_blocks.s.gmx0) { ++ ++ int interface = 0; ++ /* Loop through every port of this interface */ ++ for (index = 0; ++ index < cvmx_helper_ports_on_interface(interface); ++ index++) { ++ ++ /* Read the GMX interrupt status bits */ ++ union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; ++ gmx_rx_int_reg.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG ++ (index, interface)); ++ gmx_rx_int_reg.u64 &= ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN ++ (index, interface)); ++ /* Poll the port if inband status changed */ ++ if (gmx_rx_int_reg.s.phy_dupx ++ || gmx_rx_int_reg.s.phy_link ++ || gmx_rx_int_reg.s.phy_spd) { ++ ++ struct net_device *dev = ++ cvm_oct_device[cvmx_helper_get_ipd_port ++ (interface, index)]; ++ if (dev) ++ cvm_oct_rgmii_poll(dev); ++ gmx_rx_int_reg.u64 = 0; ++ gmx_rx_int_reg.s.phy_dupx = 1; ++ gmx_rx_int_reg.s.phy_link = 1; ++ gmx_rx_int_reg.s.phy_spd = 1; ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG ++ (index, interface), ++ gmx_rx_int_reg.u64); ++ return_status = IRQ_HANDLED; ++ } ++ } ++ } ++ ++ /* Check and see if this interrupt was caused by the GMX1 block */ ++ if (rsl_int_blocks.s.gmx1) { ++ ++ int interface = 1; ++ /* Loop through every port of this interface */ ++ for (index = 0; ++ index < cvmx_helper_ports_on_interface(interface); ++ index++) { ++ ++ /* Read the GMX interrupt status bits */ ++ union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; ++ gmx_rx_int_reg.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG ++ (index, interface)); ++ gmx_rx_int_reg.u64 &= ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN ++ (index, interface)); ++ /* Poll the port if inband status changed */ ++ if (gmx_rx_int_reg.s.phy_dupx ++ || gmx_rx_int_reg.s.phy_link ++ || gmx_rx_int_reg.s.phy_spd) { ++ ++ struct net_device *dev = ++ cvm_oct_device[cvmx_helper_get_ipd_port ++ (interface, index)]; ++ if (dev) ++ cvm_oct_rgmii_poll(dev); ++ gmx_rx_int_reg.u64 = 0; ++ gmx_rx_int_reg.s.phy_dupx = 1; ++ gmx_rx_int_reg.s.phy_link = 1; ++ gmx_rx_int_reg.s.phy_spd = 1; ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG ++ (index, interface), ++ gmx_rx_int_reg.u64); ++ return_status = IRQ_HANDLED; ++ } ++ } ++ } ++ return return_status; ++} ++ ++static int cvm_oct_rgmii_open(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ cvmx_helper_link_info_t link_info; ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ ++ if (!octeon_is_simulation()) { ++ link_info = cvmx_helper_link_get(priv->port); ++ if (!link_info.s.link_up) ++ netif_carrier_off(dev); ++ } ++ ++ return 0; ++} ++ ++static int cvm_oct_rgmii_stop(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ return 0; ++} ++ ++int cvm_oct_rgmii_init(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int r; ++ ++ cvm_oct_common_init(dev); ++ dev->open = cvm_oct_rgmii_open; ++ dev->stop = cvm_oct_rgmii_stop; ++ dev->stop(dev); ++ ++ /* ++ * Due to GMX errata in CN3XXX series chips, it is necessary ++ * to take the link down immediately whne the PHY changes ++ * state. In order to do this we call the poll function every ++ * time the RGMII inband status changes. This may cause ++ * problems if the PHY doesn't implement inband status ++ * properly. ++ */ ++ if (number_rgmii_ports == 0) { ++ r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt, ++ IRQF_SHARED, "RGMII", &number_rgmii_ports); ++ } ++ number_rgmii_ports++; ++ ++ /* ++ * Only true RGMII ports need to be polled. In GMII mode, port ++ * 0 is really a RGMII port. ++ */ ++ if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) ++ && (priv->port == 0)) ++ || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { ++ ++ if (!octeon_is_simulation()) { ++ ++ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ /* ++ * Enable interrupts on inband status changes ++ * for this port. ++ */ ++ gmx_rx_int_en.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN ++ (index, interface)); ++ gmx_rx_int_en.s.phy_dupx = 1; ++ gmx_rx_int_en.s.phy_link = 1; ++ gmx_rx_int_en.s.phy_spd = 1; ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), ++ gmx_rx_int_en.u64); ++ priv->poll = cvm_oct_rgmii_poll; ++ } ++ } ++ ++ return 0; ++} ++ ++void cvm_oct_rgmii_uninit(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ cvm_oct_common_uninit(dev); ++ ++ /* ++ * Only true RGMII ports need to be polled. In GMII mode, port ++ * 0 is really a RGMII port. ++ */ ++ if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) ++ && (priv->port == 0)) ++ || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { ++ ++ if (!octeon_is_simulation()) { ++ ++ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ /* ++ * Disable interrupts on inband status changes ++ * for this port. ++ */ ++ gmx_rx_int_en.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN ++ (index, interface)); ++ gmx_rx_int_en.s.phy_dupx = 0; ++ gmx_rx_int_en.s.phy_link = 0; ++ gmx_rx_int_en.s.phy_spd = 0; ++ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), ++ gmx_rx_int_en.u64); ++ } ++ } ++ ++ /* Remove the interrupt handler when the last port is removed. */ ++ number_rgmii_ports--; ++ if (number_rgmii_ports == 0) ++ free_irq(OCTEON_IRQ_RML, &number_rgmii_ports); ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-rx.c +@@ -0,0 +1,505 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_XFRM ++#include ++#include ++#endif /* CONFIG_XFRM */ ++ ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-mem.h" ++#include "ethernet-util.h" ++ ++#include "cvmx-helper.h" ++#include "cvmx-wqe.h" ++#include "cvmx-fau.h" ++#include "cvmx-pow.h" ++#include "cvmx-pip.h" ++#include "cvmx-scratch.h" ++ ++#include "cvmx-gmxx-defs.h" ++ ++struct cvm_tasklet_wrapper { ++ struct tasklet_struct t; ++}; ++ ++/* ++ * Aligning the tasklet_struct on cachline boundries seems to decrease ++ * throughput even though in theory it would reduce contantion on the ++ * cache lines containing the locks. ++ */ ++ ++static struct cvm_tasklet_wrapper cvm_oct_tasklet[NR_CPUS]; ++ ++/** ++ * Interrupt handler. The interrupt occurs whenever the POW ++ * transitions from 0->1 packets in our group. ++ * ++ * @cpl: ++ * @dev_id: ++ * @regs: ++ * Returns ++ */ ++irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id) ++{ ++ /* Acknowledge the interrupt */ ++ if (INTERRUPT_LIMIT) ++ cvmx_write_csr(CVMX_POW_WQ_INT, 1 << pow_receive_group); ++ else ++ cvmx_write_csr(CVMX_POW_WQ_INT, 0x10001 << pow_receive_group); ++ preempt_disable(); ++ tasklet_schedule(&cvm_oct_tasklet[smp_processor_id()].t); ++ preempt_enable(); ++ return IRQ_HANDLED; ++} ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/** ++ * This is called when the kernel needs to manually poll the ++ * device. For Octeon, this is simply calling the interrupt ++ * handler. We actually poll all the devices, not just the ++ * one supplied. ++ * ++ * @dev: Device to poll. Unused ++ */ ++void cvm_oct_poll_controller(struct net_device *dev) ++{ ++ preempt_disable(); ++ tasklet_schedule(&cvm_oct_tasklet[smp_processor_id()].t); ++ preempt_enable(); ++} ++#endif ++ ++/** ++ * This is called on receive errors, and determines if the packet ++ * can be dropped early-on in cvm_oct_tasklet_rx(). ++ * ++ * @work: Work queue entry pointing to the packet. ++ * Returns Non-zero if the packet can be dropped, zero otherwise. ++ */ ++static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) ++{ ++ if ((work->word2.snoip.err_code == 10) && (work->len <= 64)) { ++ /* ++ * Ignore length errors on min size packets. Some ++ * equipment incorrectly pads packets to 64+4FCS ++ * instead of 60+4FCS. Note these packets still get ++ * counted as frame errors. ++ */ ++ } else ++ if (USE_10MBPS_PREAMBLE_WORKAROUND ++ && ((work->word2.snoip.err_code == 5) ++ || (work->word2.snoip.err_code == 7))) { ++ ++ /* ++ * We received a packet with either an alignment error ++ * or a FCS error. This may be signalling that we are ++ * running 10Mbps with GMXX_RXX_FRM_CTL[PRE_CHK} ++ * off. If this is the case we need to parse the ++ * packet to determine if we can remove a non spec ++ * preamble and generate a correct packet. ++ */ ++ int interface = cvmx_helper_get_interface_num(work->ipprt); ++ int index = cvmx_helper_get_interface_index_num(work->ipprt); ++ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; ++ gmxx_rxx_frm_ctl.u64 = ++ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); ++ if (gmxx_rxx_frm_ctl.s.pre_chk == 0) { ++ ++ uint8_t *ptr = ++ cvmx_phys_to_ptr(work->packet_ptr.s.addr); ++ int i = 0; ++ ++ while (i < work->len - 1) { ++ if (*ptr != 0x55) ++ break; ++ ptr++; ++ i++; ++ } ++ ++ if (*ptr == 0xd5) { ++ /* ++ DEBUGPRINT("Port %d received 0xd5 preamble\n", work->ipprt); ++ */ ++ work->packet_ptr.s.addr += i + 1; ++ work->len -= i + 5; ++ } else if ((*ptr & 0xf) == 0xd) { ++ /* ++ DEBUGPRINT("Port %d received 0x?d preamble\n", work->ipprt); ++ */ ++ work->packet_ptr.s.addr += i; ++ work->len -= i + 4; ++ for (i = 0; i < work->len; i++) { ++ *ptr = ++ ((*ptr & 0xf0) >> 4) | ++ ((*(ptr + 1) & 0xf) << 4); ++ ptr++; ++ } ++ } else { ++ DEBUGPRINT("Port %d unknown preamble, packet " ++ "dropped\n", ++ work->ipprt); ++ /* ++ cvmx_helper_dump_packet(work); ++ */ ++ cvm_oct_free_work(work); ++ return 1; ++ } ++ } ++ } else { ++ DEBUGPRINT("Port %d receive error code %d, packet dropped\n", ++ work->ipprt, work->word2.snoip.err_code); ++ cvm_oct_free_work(work); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * Tasklet function that is scheduled on a core when an interrupt occurs. ++ * ++ * @unused: ++ */ ++void cvm_oct_tasklet_rx(unsigned long unused) ++{ ++ const int coreid = cvmx_get_core_num(); ++ uint64_t old_group_mask; ++ uint64_t old_scratch; ++ int rx_count = 0; ++ int number_to_free; ++ int num_freed; ++ int packet_not_copied; ++ ++ /* Prefetch cvm_oct_device since we know we need it soon */ ++ prefetch(cvm_oct_device); ++ ++ if (USE_ASYNC_IOBDMA) { ++ /* Save scratch in case userspace is using it */ ++ CVMX_SYNCIOBDMA; ++ old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); ++ } ++ ++ /* Only allow work for our group (and preserve priorities) */ ++ old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid)); ++ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), ++ (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group); ++ ++ if (USE_ASYNC_IOBDMA) ++ cvmx_pow_work_request_async(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT); ++ ++ while (1) { ++ struct sk_buff *skb = NULL; ++ int skb_in_hw; ++ cvmx_wqe_t *work; ++ ++ if (USE_ASYNC_IOBDMA) { ++ work = cvmx_pow_work_response_async(CVMX_SCR_SCRATCH); ++ } else { ++ if ((INTERRUPT_LIMIT == 0) ++ || likely(rx_count < MAX_RX_PACKETS)) ++ work = ++ cvmx_pow_work_request_sync ++ (CVMX_POW_NO_WAIT); ++ else ++ work = NULL; ++ } ++ prefetch(work); ++ if (work == NULL) ++ break; ++ ++ /* ++ * Limit each core to processing MAX_RX_PACKETS ++ * packets without a break. This way the RX can't ++ * starve the TX task. ++ */ ++ if (USE_ASYNC_IOBDMA) { ++ ++ if ((INTERRUPT_LIMIT == 0) ++ || likely(rx_count < MAX_RX_PACKETS)) ++ cvmx_pow_work_request_async_nocheck ++ (CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT); ++ else { ++ cvmx_scratch_write64(CVMX_SCR_SCRATCH, ++ 0x8000000000000000ull); ++ cvmx_pow_tag_sw_null_nocheck(); ++ } ++ } ++ ++ skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1; ++ if (likely(skb_in_hw)) { ++ skb = ++ *(struct sk_buff ++ **)(cvm_oct_get_buffer_ptr(work->packet_ptr) - ++ sizeof(void *)); ++ prefetch(&skb->head); ++ prefetch(&skb->len); ++ } ++ prefetch(cvm_oct_device[work->ipprt]); ++ ++ rx_count++; ++ /* Immediately throw away all packets with receive errors */ ++ if (unlikely(work->word2.snoip.rcv_error)) { ++ if (cvm_oct_check_rcv_error(work)) ++ continue; ++ } ++ ++ /* ++ * We can only use the zero copy path if skbuffs are ++ * in the FPA pool and the packet fits in a single ++ * buffer. ++ */ ++ if (likely(skb_in_hw)) { ++ /* ++ * This calculation was changed in case the ++ * skb header is using a different address ++ * aliasing type than the buffer. It doesn't ++ * make any differnece now, but the new one is ++ * more correct. ++ */ ++ skb->data = ++ skb->head + work->packet_ptr.s.addr - ++ cvmx_ptr_to_phys(skb->head); ++ prefetch(skb->data); ++ skb->len = work->len; ++ skb_set_tail_pointer(skb, skb->len); ++ packet_not_copied = 1; ++ } else { ++ ++ /* ++ * We have to copy the packet. First allocate ++ * an skbuff for it. ++ */ ++ skb = dev_alloc_skb(work->len); ++ if (!skb) { ++ DEBUGPRINT("Port %d failed to allocate " ++ "skbuff, packet dropped\n", ++ work->ipprt); ++ cvm_oct_free_work(work); ++ continue; ++ } ++ ++ /* ++ * Check if we've received a packet that was ++ * entirely stored in the work entry. This is ++ * untested. ++ */ ++ if (unlikely(work->word2.s.bufs == 0)) { ++ uint8_t *ptr = work->packet_data; ++ ++ if (likely(!work->word2.s.not_IP)) { ++ /* ++ * The beginning of the packet ++ * moves for IP packets. ++ */ ++ if (work->word2.s.is_v6) ++ ptr += 2; ++ else ++ ptr += 6; ++ } ++ memcpy(skb_put(skb, work->len), ptr, work->len); ++ /* No packet buffers to free */ ++ } else { ++ int segments = work->word2.s.bufs; ++ union cvmx_buf_ptr segment_ptr = ++ work->packet_ptr; ++ int len = work->len; ++ ++ while (segments--) { ++ union cvmx_buf_ptr next_ptr = ++ *(union cvmx_buf_ptr *) ++ cvmx_phys_to_ptr(segment_ptr.s. ++ addr - 8); ++ /* ++ * Octeon Errata PKI-100: The segment size is ++ * wrong. Until it is fixed, calculate the ++ * segment size based on the packet pool ++ * buffer size. When it is fixed, the ++ * following line should be replaced with this ++ * one: int segment_size = ++ * segment_ptr.s.size; ++ */ ++ int segment_size = ++ CVMX_FPA_PACKET_POOL_SIZE - ++ (segment_ptr.s.addr - ++ (((segment_ptr.s.addr >> 7) - ++ segment_ptr.s.back) << 7)); ++ /* Don't copy more than what is left ++ in the packet */ ++ if (segment_size > len) ++ segment_size = len; ++ /* Copy the data into the packet */ ++ memcpy(skb_put(skb, segment_size), ++ cvmx_phys_to_ptr(segment_ptr.s. ++ addr), ++ segment_size); ++ /* Reduce the amount of bytes left ++ to copy */ ++ len -= segment_size; ++ segment_ptr = next_ptr; ++ } ++ } ++ packet_not_copied = 0; ++ } ++ ++ if (likely((work->ipprt < TOTAL_NUMBER_OF_PORTS) && ++ cvm_oct_device[work->ipprt])) { ++ struct net_device *dev = cvm_oct_device[work->ipprt]; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ ++ /* Only accept packets for devices ++ that are currently up */ ++ if (likely(dev->flags & IFF_UP)) { ++ skb->protocol = eth_type_trans(skb, dev); ++ skb->dev = dev; ++ ++ if (unlikely ++ (work->word2.s.not_IP ++ || work->word2.s.IP_exc ++ || work->word2.s.L4_error)) ++ skb->ip_summed = CHECKSUM_NONE; ++ else ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ /* Increment RX stats for virtual ports */ ++ if (work->ipprt >= CVMX_PIP_NUM_INPUT_PORTS) { ++#ifdef CONFIG_64BIT ++ atomic64_add(1, (atomic64_t *)&priv->stats.rx_packets); ++ atomic64_add(skb->len, (atomic64_t *)&priv->stats.rx_bytes); ++#else ++ atomic_add(1, (atomic_t *)&priv->stats.rx_packets); ++ atomic_add(skb->len, (atomic_t *)&priv->stats.rx_bytes); ++#endif ++ } ++ netif_receive_skb(skb); ++ } else { ++ /* ++ * Drop any packet received for a ++ * device that isn't up. ++ */ ++ /* ++ DEBUGPRINT("%s: Device not up, packet dropped\n", ++ dev->name); ++ */ ++#ifdef CONFIG_64BIT ++ atomic64_add(1, (atomic64_t *)&priv->stats.rx_dropped); ++#else ++ atomic_add(1, (atomic_t *)&priv->stats.rx_dropped); ++#endif ++ dev_kfree_skb_irq(skb); ++ } ++ } else { ++ /* ++ * Drop any packet received for a device that ++ * doesn't exist. ++ */ ++ DEBUGPRINT("Port %d not controlled by Linux, packet " ++ "dropped\n", ++ work->ipprt); ++ dev_kfree_skb_irq(skb); ++ } ++ /* ++ * Check to see if the skbuff and work share the same ++ * packet buffer. ++ */ ++ if (USE_SKBUFFS_IN_HW && likely(packet_not_copied)) { ++ /* ++ * This buffer needs to be replaced, increment ++ * the number of buffers we need to free by ++ * one. ++ */ ++ cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, ++ 1); ++ ++ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, ++ DONT_WRITEBACK(1)); ++ } else { ++ cvm_oct_free_work(work); ++ } ++ } ++ ++ /* Restore the original POW group mask */ ++ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask); ++ if (USE_ASYNC_IOBDMA) { ++ /* Restore the scratch area */ ++ cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); ++ } ++ ++ if (USE_SKBUFFS_IN_HW) { ++ /* Refill the packet buffer pool */ ++ number_to_free = ++ cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); ++ ++ if (number_to_free > 0) { ++ cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, ++ -number_to_free); ++ num_freed = ++ cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, ++ CVMX_FPA_PACKET_POOL_SIZE, ++ number_to_free); ++ if (num_freed != number_to_free) { ++ cvmx_fau_atomic_add32 ++ (FAU_NUM_PACKET_BUFFERS_TO_FREE, ++ number_to_free - num_freed); ++ } ++ } ++ } ++} ++ ++void cvm_oct_rx_initialize(void) ++{ ++ int i; ++ /* Initialize all of the tasklets */ ++ for (i = 0; i < NR_CPUS; i++) ++ tasklet_init(&cvm_oct_tasklet[i].t, cvm_oct_tasklet_rx, 0); ++} ++ ++void cvm_oct_rx_shutdown(void) ++{ ++ int i; ++ /* Shutdown all of the tasklets */ ++ for (i = 0; i < NR_CPUS; i++) ++ tasklet_kill(&cvm_oct_tasklet[i].t); ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-rx.h +@@ -0,0 +1,33 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++ ++irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id); ++void cvm_oct_poll_controller(struct net_device *dev); ++void cvm_oct_tasklet_rx(unsigned long unused); ++ ++void cvm_oct_rx_initialize(void); ++void cvm_oct_rx_shutdown(void); +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-sgmii.c +@@ -0,0 +1,129 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-util.h" ++#include "ethernet-common.h" ++ ++#include "cvmx-helper.h" ++ ++#include "cvmx-gmxx-defs.h" ++ ++static int cvm_oct_sgmii_open(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ cvmx_helper_link_info_t link_info; ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ ++ if (!octeon_is_simulation()) { ++ link_info = cvmx_helper_link_get(priv->port); ++ if (!link_info.s.link_up) ++ netif_carrier_off(dev); ++ } ++ ++ return 0; ++} ++ ++static int cvm_oct_sgmii_stop(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ return 0; ++} ++ ++static void cvm_oct_sgmii_poll(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ cvmx_helper_link_info_t link_info; ++ ++ link_info = cvmx_helper_link_get(priv->port); ++ if (link_info.u64 == priv->link_info) ++ return; ++ ++ link_info = cvmx_helper_link_autoconf(priv->port); ++ priv->link_info = link_info.u64; ++ ++ /* Tell Linux */ ++ if (link_info.s.link_up) { ++ ++ if (!netif_carrier_ok(dev)) ++ netif_carrier_on(dev); ++ if (priv->queue != -1) ++ DEBUGPRINT ++ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", ++ dev->name, link_info.s.speed, ++ (link_info.s.full_duplex) ? "Full" : "Half", ++ priv->port, priv->queue); ++ else ++ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", ++ dev->name, link_info.s.speed, ++ (link_info.s.full_duplex) ? "Full" : "Half", ++ priv->port); ++ } else { ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); ++ DEBUGPRINT("%s: Link down\n", dev->name); ++ } ++} ++ ++int cvm_oct_sgmii_init(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ cvm_oct_common_init(dev); ++ dev->open = cvm_oct_sgmii_open; ++ dev->stop = cvm_oct_sgmii_stop; ++ dev->stop(dev); ++ if (!octeon_is_simulation()) ++ priv->poll = cvm_oct_sgmii_poll; ++ ++ /* FIXME: Need autoneg logic */ ++ return 0; ++} ++ ++void cvm_oct_sgmii_uninit(struct net_device *dev) ++{ ++ cvm_oct_common_uninit(dev); ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-spi.c +@@ -0,0 +1,323 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-common.h" ++#include "ethernet-util.h" ++ ++#include "cvmx-spi.h" ++ ++#include ++#include "cvmx-spxx-defs.h" ++#include "cvmx-stxx-defs.h" ++ ++static int number_spi_ports; ++static int need_retrain[2] = { 0, 0 }; ++ ++static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) ++{ ++ irqreturn_t return_status = IRQ_NONE; ++ union cvmx_npi_rsl_int_blocks rsl_int_blocks; ++ ++ /* Check and see if this interrupt was caused by the GMX block */ ++ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); ++ if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */ ++ ++ union cvmx_spxx_int_reg spx_int_reg; ++ union cvmx_stxx_int_reg stx_int_reg; ++ ++ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1)); ++ cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64); ++ if (!need_retrain[1]) { ++ ++ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1)); ++ if (spx_int_reg.s.spf) ++ pr_err("SPI1: SRX Spi4 interface down\n"); ++ if (spx_int_reg.s.calerr) ++ pr_err("SPI1: SRX Spi4 Calendar table " ++ "parity error\n"); ++ if (spx_int_reg.s.syncerr) ++ pr_err("SPI1: SRX Consecutive Spi4 DIP4 " ++ "errors have exceeded " ++ "SPX_ERR_CTL[ERRCNT]\n"); ++ if (spx_int_reg.s.diperr) ++ pr_err("SPI1: SRX Spi4 DIP4 error\n"); ++ if (spx_int_reg.s.tpaovr) ++ pr_err("SPI1: SRX Selected port has hit " ++ "TPA overflow\n"); ++ if (spx_int_reg.s.rsverr) ++ pr_err("SPI1: SRX Spi4 reserved control " ++ "word detected\n"); ++ if (spx_int_reg.s.drwnng) ++ pr_err("SPI1: SRX Spi4 receive FIFO " ++ "drowning/overflow\n"); ++ if (spx_int_reg.s.clserr) ++ pr_err("SPI1: SRX Spi4 packet closed on " ++ "non-16B alignment without EOP\n"); ++ if (spx_int_reg.s.spiovr) ++ pr_err("SPI1: SRX Spi4 async FIFO overflow\n"); ++ if (spx_int_reg.s.abnorm) ++ pr_err("SPI1: SRX Abnormal packet " ++ "termination (ERR bit)\n"); ++ if (spx_int_reg.s.prtnxa) ++ pr_err("SPI1: SRX Port out of range\n"); ++ } ++ ++ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1)); ++ cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64); ++ if (!need_retrain[1]) { ++ ++ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1)); ++ if (stx_int_reg.s.syncerr) ++ pr_err("SPI1: STX Interface encountered a " ++ "fatal error\n"); ++ if (stx_int_reg.s.frmerr) ++ pr_err("SPI1: STX FRMCNT has exceeded " ++ "STX_DIP_CNT[MAXFRM]\n"); ++ if (stx_int_reg.s.unxfrm) ++ pr_err("SPI1: STX Unexpected framing " ++ "sequence\n"); ++ if (stx_int_reg.s.nosync) ++ pr_err("SPI1: STX ERRCNT has exceeded " ++ "STX_DIP_CNT[MAXDIP]\n"); ++ if (stx_int_reg.s.diperr) ++ pr_err("SPI1: STX DIP2 error on the Spi4 " ++ "Status channel\n"); ++ if (stx_int_reg.s.datovr) ++ pr_err("SPI1: STX Spi4 FIFO overflow error\n"); ++ if (stx_int_reg.s.ovrbst) ++ pr_err("SPI1: STX Transmit packet burst " ++ "too big\n"); ++ if (stx_int_reg.s.calpar1) ++ pr_err("SPI1: STX Calendar Table Parity " ++ "Error Bank1\n"); ++ if (stx_int_reg.s.calpar0) ++ pr_err("SPI1: STX Calendar Table Parity " ++ "Error Bank0\n"); ++ } ++ ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0); ++ cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0); ++ need_retrain[1] = 1; ++ return_status = IRQ_HANDLED; ++ } ++ ++ if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */ ++ union cvmx_spxx_int_reg spx_int_reg; ++ union cvmx_stxx_int_reg stx_int_reg; ++ ++ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0)); ++ cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64); ++ if (!need_retrain[0]) { ++ ++ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0)); ++ if (spx_int_reg.s.spf) ++ pr_err("SPI0: SRX Spi4 interface down\n"); ++ if (spx_int_reg.s.calerr) ++ pr_err("SPI0: SRX Spi4 Calendar table " ++ "parity error\n"); ++ if (spx_int_reg.s.syncerr) ++ pr_err("SPI0: SRX Consecutive Spi4 DIP4 " ++ "errors have exceeded " ++ "SPX_ERR_CTL[ERRCNT]\n"); ++ if (spx_int_reg.s.diperr) ++ pr_err("SPI0: SRX Spi4 DIP4 error\n"); ++ if (spx_int_reg.s.tpaovr) ++ pr_err("SPI0: SRX Selected port has hit " ++ "TPA overflow\n"); ++ if (spx_int_reg.s.rsverr) ++ pr_err("SPI0: SRX Spi4 reserved control " ++ "word detected\n"); ++ if (spx_int_reg.s.drwnng) ++ pr_err("SPI0: SRX Spi4 receive FIFO " ++ "drowning/overflow\n"); ++ if (spx_int_reg.s.clserr) ++ pr_err("SPI0: SRX Spi4 packet closed on " ++ "non-16B alignment without EOP\n"); ++ if (spx_int_reg.s.spiovr) ++ pr_err("SPI0: SRX Spi4 async FIFO overflow\n"); ++ if (spx_int_reg.s.abnorm) ++ pr_err("SPI0: SRX Abnormal packet " ++ "termination (ERR bit)\n"); ++ if (spx_int_reg.s.prtnxa) ++ pr_err("SPI0: SRX Port out of range\n"); ++ } ++ ++ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0)); ++ cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64); ++ if (!need_retrain[0]) { ++ ++ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0)); ++ if (stx_int_reg.s.syncerr) ++ pr_err("SPI0: STX Interface encountered a " ++ "fatal error\n"); ++ if (stx_int_reg.s.frmerr) ++ pr_err("SPI0: STX FRMCNT has exceeded " ++ "STX_DIP_CNT[MAXFRM]\n"); ++ if (stx_int_reg.s.unxfrm) ++ pr_err("SPI0: STX Unexpected framing " ++ "sequence\n"); ++ if (stx_int_reg.s.nosync) ++ pr_err("SPI0: STX ERRCNT has exceeded " ++ "STX_DIP_CNT[MAXDIP]\n"); ++ if (stx_int_reg.s.diperr) ++ pr_err("SPI0: STX DIP2 error on the Spi4 " ++ "Status channel\n"); ++ if (stx_int_reg.s.datovr) ++ pr_err("SPI0: STX Spi4 FIFO overflow error\n"); ++ if (stx_int_reg.s.ovrbst) ++ pr_err("SPI0: STX Transmit packet burst " ++ "too big\n"); ++ if (stx_int_reg.s.calpar1) ++ pr_err("SPI0: STX Calendar Table Parity " ++ "Error Bank1\n"); ++ if (stx_int_reg.s.calpar0) ++ pr_err("SPI0: STX Calendar Table Parity " ++ "Error Bank0\n"); ++ } ++ ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0); ++ cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0); ++ need_retrain[0] = 1; ++ return_status = IRQ_HANDLED; ++ } ++ ++ return return_status; ++} ++ ++static void cvm_oct_spi_enable_error_reporting(int interface) ++{ ++ union cvmx_spxx_int_msk spxx_int_msk; ++ union cvmx_stxx_int_msk stxx_int_msk; ++ ++ spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); ++ spxx_int_msk.s.calerr = 1; ++ spxx_int_msk.s.syncerr = 1; ++ spxx_int_msk.s.diperr = 1; ++ spxx_int_msk.s.tpaovr = 1; ++ spxx_int_msk.s.rsverr = 1; ++ spxx_int_msk.s.drwnng = 1; ++ spxx_int_msk.s.clserr = 1; ++ spxx_int_msk.s.spiovr = 1; ++ spxx_int_msk.s.abnorm = 1; ++ spxx_int_msk.s.prtnxa = 1; ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); ++ ++ stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); ++ stxx_int_msk.s.frmerr = 1; ++ stxx_int_msk.s.unxfrm = 1; ++ stxx_int_msk.s.nosync = 1; ++ stxx_int_msk.s.diperr = 1; ++ stxx_int_msk.s.datovr = 1; ++ stxx_int_msk.s.ovrbst = 1; ++ stxx_int_msk.s.calpar1 = 1; ++ stxx_int_msk.s.calpar0 = 1; ++ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); ++} ++ ++static void cvm_oct_spi_poll(struct net_device *dev) ++{ ++ static int spi4000_port; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface; ++ ++ for (interface = 0; interface < 2; interface++) { ++ ++ if ((priv->port == interface * 16) && need_retrain[interface]) { ++ ++ if (cvmx_spi_restart_interface ++ (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) { ++ need_retrain[interface] = 0; ++ cvm_oct_spi_enable_error_reporting(interface); ++ } ++ } ++ ++ /* ++ * The SPI4000 TWSI interface is very slow. In order ++ * not to bring the system to a crawl, we only poll a ++ * single port every second. This means negotiation ++ * speed changes take up to 10 seconds, but at least ++ * we don't waste absurd amounts of time waiting for ++ * TWSI. ++ */ ++ if (priv->port == spi4000_port) { ++ /* ++ * This function does nothing if it is called on an ++ * interface without a SPI4000. ++ */ ++ cvmx_spi4000_check_speed(interface, priv->port); ++ /* ++ * Normal ordering increments. By decrementing ++ * we only match once per iteration. ++ */ ++ spi4000_port--; ++ if (spi4000_port < 0) ++ spi4000_port = 10; ++ } ++ } ++} ++ ++int cvm_oct_spi_init(struct net_device *dev) ++{ ++ int r; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ ++ if (number_spi_ports == 0) { ++ r = request_irq(OCTEON_IRQ_RML, cvm_oct_spi_rml_interrupt, ++ IRQF_SHARED, "SPI", &number_spi_ports); ++ } ++ number_spi_ports++; ++ ++ if ((priv->port == 0) || (priv->port == 16)) { ++ cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port)); ++ priv->poll = cvm_oct_spi_poll; ++ } ++ cvm_oct_common_init(dev); ++ return 0; ++} ++ ++void cvm_oct_spi_uninit(struct net_device *dev) ++{ ++ int interface; ++ ++ cvm_oct_common_uninit(dev); ++ number_spi_ports--; ++ if (number_spi_ports == 0) { ++ for (interface = 0; interface < 2; interface++) { ++ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); ++ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); ++ } ++ free_irq(8 + 46, &number_spi_ports); ++ } ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-tx.c +@@ -0,0 +1,634 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_XFRM ++#include ++#include ++#endif /* CONFIG_XFRM */ ++ ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-util.h" ++ ++#include "cvmx-wqe.h" ++#include "cvmx-fau.h" ++#include "cvmx-pko.h" ++#include "cvmx-helper.h" ++ ++#include "cvmx-gmxx-defs.h" ++ ++/* ++ * You can define GET_SKBUFF_QOS() to override how the skbuff output ++ * function determines which output queue is used. The default ++ * implementation always uses the base queue for the port. If, for ++ * example, you wanted to use the skb->priority fieid, define ++ * GET_SKBUFF_QOS as: #define GET_SKBUFF_QOS(skb) ((skb)->priority) ++ */ ++#ifndef GET_SKBUFF_QOS ++#define GET_SKBUFF_QOS(skb) 0 ++#endif ++ ++/** ++ * Packet transmit ++ * ++ * @skb: Packet to send ++ * @dev: Device info structure ++ * Returns Always returns zero ++ */ ++int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ cvmx_pko_command_word0_t pko_command; ++ union cvmx_buf_ptr hw_buffer; ++ uint64_t old_scratch; ++ uint64_t old_scratch2; ++ int dropped; ++ int qos; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int32_t in_use; ++ int32_t buffers_to_free; ++#if REUSE_SKBUFFS_WITHOUT_FREE ++ unsigned char *fpa_head; ++#endif ++ ++ /* ++ * Prefetch the private data structure. It is larger that one ++ * cache line. ++ */ ++ prefetch(priv); ++ ++ /* Start off assuming no drop */ ++ dropped = 0; ++ ++ /* ++ * The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to ++ * completely remove "qos" in the event neither interface ++ * supports multiple queues per port. ++ */ ++ if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) || ++ (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) { ++ qos = GET_SKBUFF_QOS(skb); ++ if (qos <= 0) ++ qos = 0; ++ else if (qos >= cvmx_pko_get_num_queues(priv->port)) ++ qos = 0; ++ } else ++ qos = 0; ++ ++ if (USE_ASYNC_IOBDMA) { ++ /* Save scratch in case userspace is using it */ ++ CVMX_SYNCIOBDMA; ++ old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); ++ old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); ++ ++ /* ++ * Assume we're going to be able t osend this ++ * packet. Fetch and increment the number of pending ++ * packets for output. ++ */ ++ cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH + 8, ++ FAU_NUM_PACKET_BUFFERS_TO_FREE, ++ 0); ++ cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, ++ priv->fau + qos * 4, 1); ++ } ++ ++ /* ++ * The CN3XXX series of parts has an errata (GMX-401) which ++ * causes the GMX block to hang if a collision occurs towards ++ * the end of a <68 byte packet. As a workaround for this, we ++ * pad packets to be 68 bytes whenever we are in half duplex ++ * mode. We don't handle the case of having a small packet but ++ * no room to add the padding. The kernel should always give ++ * us at least a cache line ++ */ ++ if ((skb->len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ union cvmx_gmxx_prtx_cfg gmx_prt_cfg; ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ if (interface < 2) { ++ /* We only need to pad packet in half duplex mode */ ++ gmx_prt_cfg.u64 = ++ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ if (gmx_prt_cfg.s.duplex == 0) { ++ int add_bytes = 64 - skb->len; ++ if ((skb_tail_pointer(skb) + add_bytes) <= ++ skb_end_pointer(skb)) ++ memset(__skb_put(skb, add_bytes), 0, ++ add_bytes); ++ } ++ } ++ } ++ ++ /* Build the PKO buffer pointer */ ++ hw_buffer.u64 = 0; ++ hw_buffer.s.addr = cvmx_ptr_to_phys(skb->data); ++ hw_buffer.s.pool = 0; ++ hw_buffer.s.size = ++ (unsigned long)skb_end_pointer(skb) - (unsigned long)skb->head; ++ ++ /* Build the PKO command */ ++ pko_command.u64 = 0; ++ pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ ++ pko_command.s.segs = 1; ++ pko_command.s.total_bytes = skb->len; ++ pko_command.s.size0 = CVMX_FAU_OP_SIZE_32; ++ pko_command.s.subone0 = 1; ++ ++ pko_command.s.dontfree = 1; ++ pko_command.s.reg0 = priv->fau + qos * 4; ++ /* ++ * See if we can put this skb in the FPA pool. Any strange ++ * behavior from the Linux networking stack will most likely ++ * be caused by a bug in the following code. If some field is ++ * in use by the network stack and get carried over when a ++ * buffer is reused, bad thing may happen. If in doubt and ++ * you dont need the absolute best performance, disable the ++ * define REUSE_SKBUFFS_WITHOUT_FREE. The reuse of buffers has ++ * shown a 25% increase in performance under some loads. ++ */ ++#if REUSE_SKBUFFS_WITHOUT_FREE ++ fpa_head = skb->head + 128 - ((unsigned long)skb->head & 0x7f); ++ if (unlikely(skb->data < fpa_head)) { ++ /* ++ * printk("TX buffer beginning can't meet FPA ++ * alignment constraints\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely ++ ((skb_end_pointer(skb) - fpa_head) < CVMX_FPA_PACKET_POOL_SIZE)) { ++ /* ++ printk("TX buffer isn't large enough for the FPA\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely(skb_shared(skb))) { ++ /* ++ printk("TX buffer sharing data with someone else\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely(skb_cloned(skb))) { ++ /* ++ printk("TX buffer has been cloned\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely(skb_header_cloned(skb))) { ++ /* ++ printk("TX buffer header has been cloned\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely(skb->destructor)) { ++ /* ++ printk("TX buffer has a destructor\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely(skb_shinfo(skb)->nr_frags)) { ++ /* ++ printk("TX buffer has fragments\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ if (unlikely ++ (skb->truesize != ++ sizeof(*skb) + skb_end_pointer(skb) - skb->head)) { ++ /* ++ printk("TX buffer truesize has been changed\n"); ++ */ ++ goto dont_put_skbuff_in_hw; ++ } ++ ++ /* ++ * We can use this buffer in the FPA. We don't need the FAU ++ * update anymore ++ */ ++ pko_command.s.reg0 = 0; ++ pko_command.s.dontfree = 0; ++ ++ hw_buffer.s.back = (skb->data - fpa_head) >> 7; ++ *(struct sk_buff **)(fpa_head - sizeof(void *)) = skb; ++ ++ /* ++ * The skbuff will be reused without ever being freed. We must ++ * cleanup a bunch of Linux stuff. ++ */ ++ dst_release(skb->dst); ++ skb->dst = NULL; ++#ifdef CONFIG_XFRM ++ secpath_put(skb->sp); ++ skb->sp = NULL; ++#endif ++ nf_reset(skb); ++ ++#ifdef CONFIG_NET_SCHED ++ skb->tc_index = 0; ++#ifdef CONFIG_NET_CLS_ACT ++ skb->tc_verd = 0; ++#endif /* CONFIG_NET_CLS_ACT */ ++#endif /* CONFIG_NET_SCHED */ ++ ++dont_put_skbuff_in_hw: ++#endif /* REUSE_SKBUFFS_WITHOUT_FREE */ ++ ++ /* Check if we can use the hardware checksumming */ ++ if (USE_HW_TCPUDP_CHECKSUM && (skb->protocol == htons(ETH_P_IP)) && ++ (ip_hdr(skb)->version == 4) && (ip_hdr(skb)->ihl == 5) && ++ ((ip_hdr(skb)->frag_off == 0) || (ip_hdr(skb)->frag_off == 1 << 14)) ++ && ((ip_hdr(skb)->protocol == IP_PROTOCOL_TCP) ++ || (ip_hdr(skb)->protocol == IP_PROTOCOL_UDP))) { ++ /* Use hardware checksum calc */ ++ pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; ++ } ++ ++ if (USE_ASYNC_IOBDMA) { ++ /* Get the number of skbuffs in use by the hardware */ ++ CVMX_SYNCIOBDMA; ++ in_use = cvmx_scratch_read64(CVMX_SCR_SCRATCH); ++ buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); ++ } else { ++ /* Get the number of skbuffs in use by the hardware */ ++ in_use = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, 1); ++ buffers_to_free = ++ cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); ++ } ++ ++ /* ++ * If we're sending faster than the receive can free them then ++ * don't do the HW free. ++ */ ++ if ((buffers_to_free < -100) && !pko_command.s.dontfree) { ++ pko_command.s.dontfree = 1; ++ pko_command.s.reg0 = priv->fau + qos * 4; ++ } ++ ++ cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, ++ CVMX_PKO_LOCK_CMD_QUEUE); ++ ++ /* Drop this packet if we have too many already queued to the HW */ ++ if (unlikely ++ (skb_queue_len(&priv->tx_free_list[qos]) >= MAX_OUT_QUEUE_DEPTH)) { ++ /* ++ DEBUGPRINT("%s: Tx dropped. Too many queued\n", dev->name); ++ */ ++ dropped = 1; ++ } ++ /* Send the packet to the output queue */ ++ else if (unlikely ++ (cvmx_pko_send_packet_finish ++ (priv->port, priv->queue + qos, pko_command, hw_buffer, ++ CVMX_PKO_LOCK_CMD_QUEUE))) { ++ DEBUGPRINT("%s: Failed to send the packet\n", dev->name); ++ dropped = 1; ++ } ++ ++ if (USE_ASYNC_IOBDMA) { ++ /* Restore the scratch area */ ++ cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); ++ cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); ++ } ++ ++ if (unlikely(dropped)) { ++ dev_kfree_skb_any(skb); ++ cvmx_fau_atomic_add32(priv->fau + qos * 4, -1); ++ priv->stats.tx_dropped++; ++ } else { ++ if (USE_SKBUFFS_IN_HW) { ++ /* Put this packet on the queue to be freed later */ ++ if (pko_command.s.dontfree) ++ skb_queue_tail(&priv->tx_free_list[qos], skb); ++ else { ++ cvmx_fau_atomic_add32 ++ (FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); ++ cvmx_fau_atomic_add32(priv->fau + qos * 4, -1); ++ } ++ } else { ++ /* Put this packet on the queue to be freed later */ ++ skb_queue_tail(&priv->tx_free_list[qos], skb); ++ } ++ } ++ ++ /* Free skbuffs not in use by the hardware, possibly two at a time */ ++ if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) { ++ spin_lock(&priv->tx_free_list[qos].lock); ++ /* ++ * Check again now that we have the lock. It might ++ * have changed. ++ */ ++ if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) ++ dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); ++ if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) ++ dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); ++ spin_unlock(&priv->tx_free_list[qos].lock); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Packet transmit to the POW ++ * ++ * @skb: Packet to send ++ * @dev: Device info structure ++ * Returns Always returns zero ++ */ ++int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ void *packet_buffer; ++ void *copy_location; ++ ++ /* Get a work queue entry */ ++ cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL); ++ if (unlikely(work == NULL)) { ++ DEBUGPRINT("%s: Failed to allocate a work queue entry\n", ++ dev->name); ++ priv->stats.tx_dropped++; ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ ++ /* Get a packet buffer */ ++ packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); ++ if (unlikely(packet_buffer == NULL)) { ++ DEBUGPRINT("%s: Failed to allocate a packet buffer\n", ++ dev->name); ++ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); ++ priv->stats.tx_dropped++; ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ ++ /* ++ * Calculate where we need to copy the data to. We need to ++ * leave 8 bytes for a next pointer (unused). We also need to ++ * include any configure skip. Then we need to align the IP ++ * packet src and dest into the same 64bit word. The below ++ * calculation may add a little extra, but that doesn't ++ * hurt. ++ */ ++ copy_location = packet_buffer + sizeof(uint64_t); ++ copy_location += ((CVMX_HELPER_FIRST_MBUFF_SKIP + 7) & 0xfff8) + 6; ++ ++ /* ++ * We have to copy the packet since whoever processes this ++ * packet will free it to a hardware pool. We can't use the ++ * trick of counting outstanding packets like in ++ * cvm_oct_xmit. ++ */ ++ memcpy(copy_location, skb->data, skb->len); ++ ++ /* ++ * Fill in some of the work queue fields. We may need to add ++ * more if the software at the other end needs them. ++ */ ++ work->hw_chksum = skb->csum; ++ work->len = skb->len; ++ work->ipprt = priv->port; ++ work->qos = priv->port & 0x7; ++ work->grp = pow_send_group; ++ work->tag_type = CVMX_HELPER_INPUT_TAG_TYPE; ++ work->tag = pow_send_group; /* FIXME */ ++ /* Default to zero. Sets of zero later are commented out */ ++ work->word2.u64 = 0; ++ work->word2.s.bufs = 1; ++ work->packet_ptr.u64 = 0; ++ work->packet_ptr.s.addr = cvmx_ptr_to_phys(copy_location); ++ work->packet_ptr.s.pool = CVMX_FPA_PACKET_POOL; ++ work->packet_ptr.s.size = CVMX_FPA_PACKET_POOL_SIZE; ++ work->packet_ptr.s.back = (copy_location - packet_buffer) >> 7; ++ ++ if (skb->protocol == htons(ETH_P_IP)) { ++ work->word2.s.ip_offset = 14; ++#if 0 ++ work->word2.s.vlan_valid = 0; /* FIXME */ ++ work->word2.s.vlan_cfi = 0; /* FIXME */ ++ work->word2.s.vlan_id = 0; /* FIXME */ ++ work->word2.s.dec_ipcomp = 0; /* FIXME */ ++#endif ++ work->word2.s.tcp_or_udp = ++ (ip_hdr(skb)->protocol == IP_PROTOCOL_TCP) ++ || (ip_hdr(skb)->protocol == IP_PROTOCOL_UDP); ++#if 0 ++ /* FIXME */ ++ work->word2.s.dec_ipsec = 0; ++ /* We only support IPv4 right now */ ++ work->word2.s.is_v6 = 0; ++ /* Hardware would set to zero */ ++ work->word2.s.software = 0; ++ /* No error, packet is internal */ ++ work->word2.s.L4_error = 0; ++#endif ++ work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) ++ || (ip_hdr(skb)->frag_off == ++ 1 << 14)); ++#if 0 ++ /* Assume Linux is sending a good packet */ ++ work->word2.s.IP_exc = 0; ++#endif ++ work->word2.s.is_bcast = (skb->pkt_type == PACKET_BROADCAST); ++ work->word2.s.is_mcast = (skb->pkt_type == PACKET_MULTICAST); ++#if 0 ++ /* This is an IP packet */ ++ work->word2.s.not_IP = 0; ++ /* No error, packet is internal */ ++ work->word2.s.rcv_error = 0; ++ /* No error, packet is internal */ ++ work->word2.s.err_code = 0; ++#endif ++ ++ /* ++ * When copying the data, include 4 bytes of the ++ * ethernet header to align the same way hardware ++ * does. ++ */ ++ memcpy(work->packet_data, skb->data + 10, ++ sizeof(work->packet_data)); ++ } else { ++#if 0 ++ work->word2.snoip.vlan_valid = 0; /* FIXME */ ++ work->word2.snoip.vlan_cfi = 0; /* FIXME */ ++ work->word2.snoip.vlan_id = 0; /* FIXME */ ++ work->word2.snoip.software = 0; /* Hardware would set to zero */ ++#endif ++ work->word2.snoip.is_rarp = skb->protocol == htons(ETH_P_RARP); ++ work->word2.snoip.is_arp = skb->protocol == htons(ETH_P_ARP); ++ work->word2.snoip.is_bcast = ++ (skb->pkt_type == PACKET_BROADCAST); ++ work->word2.snoip.is_mcast = ++ (skb->pkt_type == PACKET_MULTICAST); ++ work->word2.snoip.not_IP = 1; /* IP was done up above */ ++#if 0 ++ /* No error, packet is internal */ ++ work->word2.snoip.rcv_error = 0; ++ /* No error, packet is internal */ ++ work->word2.snoip.err_code = 0; ++#endif ++ memcpy(work->packet_data, skb->data, sizeof(work->packet_data)); ++ } ++ ++ /* Submit the packet to the POW */ ++ cvmx_pow_work_submit(work, work->tag, work->tag_type, work->qos, ++ work->grp); ++ priv->stats.tx_packets++; ++ priv->stats.tx_bytes += skb->len; ++ dev_kfree_skb(skb); ++ return 0; ++} ++ ++/** ++ * Transmit a work queue entry out of the ethernet port. Both ++ * the work queue entry and the packet data can optionally be ++ * freed. The work will be freed on error as well. ++ * ++ * @dev: Device to transmit out. ++ * @work_queue_entry: ++ * Work queue entry to send ++ * @do_free: True if the work queue entry and packet data should be ++ * freed. If false, neither will be freed. ++ * @qos: Index into the queues for this port to transmit on. This ++ * is used to implement QoS if their are multiple queues per ++ * port. This parameter must be between 0 and the number of ++ * queues per port minus 1. Values outside of this range will ++ * be change to zero. ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, ++ int do_free, int qos) ++{ ++ unsigned long flags; ++ union cvmx_buf_ptr hw_buffer; ++ cvmx_pko_command_word0_t pko_command; ++ int dropped; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ cvmx_wqe_t *work = work_queue_entry; ++ ++ if (!(dev->flags & IFF_UP)) { ++ DEBUGPRINT("%s: Device not up\n", dev->name); ++ if (do_free) ++ cvm_oct_free_work(work); ++ return -1; ++ } ++ ++ /* The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to completely ++ remove "qos" in the event neither interface supports ++ multiple queues per port */ ++ if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) || ++ (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) { ++ if (qos <= 0) ++ qos = 0; ++ else if (qos >= cvmx_pko_get_num_queues(priv->port)) ++ qos = 0; ++ } else ++ qos = 0; ++ ++ /* Start off assuming no drop */ ++ dropped = 0; ++ ++ local_irq_save(flags); ++ cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, ++ CVMX_PKO_LOCK_CMD_QUEUE); ++ ++ /* Build the PKO buffer pointer */ ++ hw_buffer.u64 = 0; ++ hw_buffer.s.addr = work->packet_ptr.s.addr; ++ hw_buffer.s.pool = CVMX_FPA_PACKET_POOL; ++ hw_buffer.s.size = CVMX_FPA_PACKET_POOL_SIZE; ++ hw_buffer.s.back = work->packet_ptr.s.back; ++ ++ /* Build the PKO command */ ++ pko_command.u64 = 0; ++ pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ ++ pko_command.s.dontfree = !do_free; ++ pko_command.s.segs = work->word2.s.bufs; ++ pko_command.s.total_bytes = work->len; ++ ++ /* Check if we can use the hardware checksumming */ ++ if (unlikely(work->word2.s.not_IP || work->word2.s.IP_exc)) ++ pko_command.s.ipoffp1 = 0; ++ else ++ pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; ++ ++ /* Send the packet to the output queue */ ++ if (unlikely ++ (cvmx_pko_send_packet_finish ++ (priv->port, priv->queue + qos, pko_command, hw_buffer, ++ CVMX_PKO_LOCK_CMD_QUEUE))) { ++ DEBUGPRINT("%s: Failed to send the packet\n", dev->name); ++ dropped = -1; ++ } ++ local_irq_restore(flags); ++ ++ if (unlikely(dropped)) { ++ if (do_free) ++ cvm_oct_free_work(work); ++ priv->stats.tx_dropped++; ++ } else if (do_free) ++ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); ++ ++ return dropped; ++} ++EXPORT_SYMBOL(cvm_oct_transmit_qos); ++ ++/** ++ * This function frees all skb that are currenty queued for TX. ++ * ++ * @dev: Device being shutdown ++ */ ++void cvm_oct_tx_shutdown(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ unsigned long flags; ++ int qos; ++ ++ for (qos = 0; qos < 16; qos++) { ++ spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); ++ while (skb_queue_len(&priv->tx_free_list[qos])) ++ dev_kfree_skb_any(__skb_dequeue ++ (&priv->tx_free_list[qos])); ++ spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); ++ } ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-tx.h +@@ -0,0 +1,32 @@ ++/********************************************************************* ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++ ++int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev); ++int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev); ++int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, ++ int do_free, int qos); ++void cvm_oct_tx_shutdown(struct net_device *dev); +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-util.h +@@ -0,0 +1,81 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++*********************************************************************/ ++ ++#define DEBUGPRINT(format, ...) do { if (printk_ratelimit()) \ ++ printk(format, ##__VA_ARGS__); \ ++ } while (0) ++ ++/** ++ * Given a packet data address, return a pointer to the ++ * beginning of the packet buffer. ++ * ++ * @packet_ptr: Packet data hardware address ++ * Returns Packet buffer pointer ++ */ ++static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr) ++{ ++ return cvmx_phys_to_ptr(((packet_ptr.s.addr >> 7) - packet_ptr.s.back) ++ << 7); ++} ++ ++/** ++ * Given an IPD/PKO port number, return the logical interface it is ++ * on. ++ * ++ * @ipd_port: Port to check ++ * ++ * Returns Logical interface ++ */ ++static inline int INTERFACE(int ipd_port) ++{ ++ if (ipd_port < 32) /* Interface 0 or 1 for RGMII,GMII,SPI, etc */ ++ return ipd_port >> 4; ++ else if (ipd_port < 36) /* Interface 2 for NPI */ ++ return 2; ++ else if (ipd_port < 40) /* Interface 3 for loopback */ ++ return 3; ++ else if (ipd_port == 40) /* Non existant interface for POW0 */ ++ return 4; ++ else ++ panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port); ++} ++ ++/** ++ * Given an IPD/PKO port number, return the port's index on a ++ * logical interface. ++ * ++ * @ipd_port: Port to check ++ * ++ * Returns Index into interface port list ++ */ ++static inline int INDEX(int ipd_port) ++{ ++ if (ipd_port < 32) ++ return ipd_port & 15; ++ else ++ return ipd_port & 3; ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet-xaui.c +@@ -0,0 +1,127 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "octeon-ethernet.h" ++#include "ethernet-common.h" ++#include "ethernet-util.h" ++ ++#include "cvmx-helper.h" ++ ++#include "cvmx-gmxx-defs.h" ++ ++static int cvm_oct_xaui_open(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ cvmx_helper_link_info_t link_info; ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmx_cfg.s.en = 1; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ ++ if (!octeon_is_simulation()) { ++ link_info = cvmx_helper_link_get(priv->port); ++ if (!link_info.s.link_up) ++ netif_carrier_off(dev); ++ } ++ return 0; ++} ++ ++static int cvm_oct_xaui_stop(struct net_device *dev) ++{ ++ union cvmx_gmxx_prtx_cfg gmx_cfg; ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ int interface = INTERFACE(priv->port); ++ int index = INDEX(priv->port); ++ ++ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); ++ gmx_cfg.s.en = 0; ++ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); ++ return 0; ++} ++ ++static void cvm_oct_xaui_poll(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ cvmx_helper_link_info_t link_info; ++ ++ link_info = cvmx_helper_link_get(priv->port); ++ if (link_info.u64 == priv->link_info) ++ return; ++ ++ link_info = cvmx_helper_link_autoconf(priv->port); ++ priv->link_info = link_info.u64; ++ ++ /* Tell Linux */ ++ if (link_info.s.link_up) { ++ ++ if (!netif_carrier_ok(dev)) ++ netif_carrier_on(dev); ++ if (priv->queue != -1) ++ DEBUGPRINT ++ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", ++ dev->name, link_info.s.speed, ++ (link_info.s.full_duplex) ? "Full" : "Half", ++ priv->port, priv->queue); ++ else ++ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", ++ dev->name, link_info.s.speed, ++ (link_info.s.full_duplex) ? "Full" : "Half", ++ priv->port); ++ } else { ++ if (netif_carrier_ok(dev)) ++ netif_carrier_off(dev); ++ DEBUGPRINT("%s: Link down\n", dev->name); ++ } ++} ++ ++int cvm_oct_xaui_init(struct net_device *dev) ++{ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ cvm_oct_common_init(dev); ++ dev->open = cvm_oct_xaui_open; ++ dev->stop = cvm_oct_xaui_stop; ++ dev->stop(dev); ++ if (!octeon_is_simulation()) ++ priv->poll = cvm_oct_xaui_poll; ++ ++ return 0; ++} ++ ++void cvm_oct_xaui_uninit(struct net_device *dev) ++{ ++ cvm_oct_common_uninit(dev); ++} +--- /dev/null ++++ b/drivers/staging/octeon/ethernet.c +@@ -0,0 +1,507 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "ethernet-defines.h" ++#include "ethernet-mem.h" ++#include "ethernet-rx.h" ++#include "ethernet-tx.h" ++#include "ethernet-util.h" ++#include "ethernet-proc.h" ++#include "ethernet-common.h" ++#include "octeon-ethernet.h" ++ ++#include "cvmx-pip.h" ++#include "cvmx-pko.h" ++#include "cvmx-fau.h" ++#include "cvmx-ipd.h" ++#include "cvmx-helper.h" ++ ++#include "cvmx-smix-defs.h" ++ ++#if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \ ++ && CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS ++int num_packet_buffers = CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS; ++#else ++int num_packet_buffers = 1024; ++#endif ++module_param(num_packet_buffers, int, 0444); ++MODULE_PARM_DESC(num_packet_buffers, "\n" ++ "\tNumber of packet buffers to allocate and store in the\n" ++ "\tFPA. By default, 1024 packet buffers are used unless\n" ++ "\tCONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS is defined."); ++ ++int pow_receive_group = 15; ++module_param(pow_receive_group, int, 0444); ++MODULE_PARM_DESC(pow_receive_group, "\n" ++ "\tPOW group to receive packets from. All ethernet hardware\n" ++ "\twill be configured to send incomming packets to this POW\n" ++ "\tgroup. Also any other software can submit packets to this\n" ++ "\tgroup for the kernel to process."); ++ ++int pow_send_group = -1; ++module_param(pow_send_group, int, 0644); ++MODULE_PARM_DESC(pow_send_group, "\n" ++ "\tPOW group to send packets to other software on. This\n" ++ "\tcontrols the creation of the virtual device pow0.\n" ++ "\talways_use_pow also depends on this value."); ++ ++int always_use_pow; ++module_param(always_use_pow, int, 0444); ++MODULE_PARM_DESC(always_use_pow, "\n" ++ "\tWhen set, always send to the pow group. This will cause\n" ++ "\tpackets sent to real ethernet devices to be sent to the\n" ++ "\tPOW group instead of the hardware. Unless some other\n" ++ "\tapplication changes the config, packets will still be\n" ++ "\treceived from the low level hardware. Use this option\n" ++ "\tto allow a CVMX app to intercept all packets from the\n" ++ "\tlinux kernel. You must specify pow_send_group along with\n" ++ "\tthis option."); ++ ++char pow_send_list[128] = ""; ++module_param_string(pow_send_list, pow_send_list, sizeof(pow_send_list), 0444); ++MODULE_PARM_DESC(pow_send_list, "\n" ++ "\tComma separated list of ethernet devices that should use the\n" ++ "\tPOW for transmit instead of the actual ethernet hardware. This\n" ++ "\tis a per port version of always_use_pow. always_use_pow takes\n" ++ "\tprecedence over this list. For example, setting this to\n" ++ "\t\"eth2,spi3,spi7\" would cause these three devices to transmit\n" ++ "\tusing the pow_send_group."); ++ ++static int disable_core_queueing = 1; ++module_param(disable_core_queueing, int, 0444); ++MODULE_PARM_DESC(disable_core_queueing, "\n" ++ "\tWhen set the networking core's tx_queue_len is set to zero. This\n" ++ "\tallows packets to be sent without lock contention in the packet\n" ++ "\tscheduler resulting in some cases in improved throughput.\n"); ++ ++/** ++ * Periodic timer to check auto negotiation ++ */ ++static struct timer_list cvm_oct_poll_timer; ++ ++/** ++ * Array of every ethernet device owned by this driver indexed by ++ * the ipd input port number. ++ */ ++struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS]; ++ ++extern struct semaphore mdio_sem; ++ ++/** ++ * Periodic timer tick for slow management operations ++ * ++ * @arg: Device to check ++ */ ++static void cvm_do_timer(unsigned long arg) ++{ ++ static int port; ++ if (port < CVMX_PIP_NUM_INPUT_PORTS) { ++ if (cvm_oct_device[port]) { ++ int queues_per_port; ++ int qos; ++ struct octeon_ethernet *priv = ++ netdev_priv(cvm_oct_device[port]); ++ if (priv->poll) { ++ /* skip polling if we don't get the lock */ ++ if (!down_trylock(&mdio_sem)) { ++ priv->poll(cvm_oct_device[port]); ++ up(&mdio_sem); ++ } ++ } ++ ++ queues_per_port = cvmx_pko_get_num_queues(port); ++ /* Drain any pending packets in the free list */ ++ for (qos = 0; qos < queues_per_port; qos++) { ++ if (skb_queue_len(&priv->tx_free_list[qos])) { ++ spin_lock(&priv->tx_free_list[qos]. ++ lock); ++ while (skb_queue_len ++ (&priv->tx_free_list[qos]) > ++ cvmx_fau_fetch_and_add32(priv-> ++ fau + ++ qos * 4, ++ 0)) ++ dev_kfree_skb(__skb_dequeue ++ (&priv-> ++ tx_free_list ++ [qos])); ++ spin_unlock(&priv->tx_free_list[qos]. ++ lock); ++ } ++ } ++ cvm_oct_device[port]->get_stats(cvm_oct_device[port]); ++ } ++ port++; ++ /* Poll the next port in a 50th of a second. ++ This spreads the polling of ports out a little bit */ ++ mod_timer(&cvm_oct_poll_timer, jiffies + HZ / 50); ++ } else { ++ port = 0; ++ /* All ports have been polled. Start the next iteration through ++ the ports in one second */ ++ mod_timer(&cvm_oct_poll_timer, jiffies + HZ); ++ } ++} ++ ++/** ++ * Configure common hardware for all interfaces ++ */ ++static __init void cvm_oct_configure_common_hw(void) ++{ ++ int r; ++ /* Setup the FPA */ ++ cvmx_fpa_enable(); ++ cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, ++ num_packet_buffers); ++ cvm_oct_mem_fill_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, ++ num_packet_buffers); ++ if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) ++ cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, ++ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); ++ ++ if (USE_RED) ++ cvmx_helper_setup_red(num_packet_buffers / 4, ++ num_packet_buffers / 8); ++ ++ /* Enable the MII interface */ ++ if (!octeon_is_simulation()) ++ cvmx_write_csr(CVMX_SMIX_EN(0), 1); ++ ++ /* Register an IRQ hander for to receive POW interrupts */ ++ r = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, ++ cvm_oct_do_interrupt, IRQF_SHARED, "Ethernet", ++ cvm_oct_device); ++ ++#if defined(CONFIG_SMP) && 0 ++ if (USE_MULTICORE_RECEIVE) { ++ irq_set_affinity(OCTEON_IRQ_WORKQ0 + pow_receive_group, ++ cpu_online_mask); ++ } ++#endif ++} ++ ++/** ++ * Free a work queue entry received in a intercept callback. ++ * ++ * @work_queue_entry: ++ * Work queue entry to free ++ * Returns Zero on success, Negative on failure. ++ */ ++int cvm_oct_free_work(void *work_queue_entry) ++{ ++ cvmx_wqe_t *work = work_queue_entry; ++ ++ int segments = work->word2.s.bufs; ++ union cvmx_buf_ptr segment_ptr = work->packet_ptr; ++ ++ while (segments--) { ++ union cvmx_buf_ptr next_ptr = *(union cvmx_buf_ptr *) ++ cvmx_phys_to_ptr(segment_ptr.s.addr - 8); ++ if (unlikely(!segment_ptr.s.i)) ++ cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr), ++ segment_ptr.s.pool, ++ DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE / ++ 128)); ++ segment_ptr = next_ptr; ++ } ++ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cvm_oct_free_work); ++ ++/** ++ * Module/ driver initialization. Creates the linux network ++ * devices. ++ * ++ * Returns Zero on success ++ */ ++static int __init cvm_oct_init_module(void) ++{ ++ int num_interfaces; ++ int interface; ++ int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; ++ int qos; ++ ++ pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); ++ ++ cvm_oct_proc_initialize(); ++ cvm_oct_rx_initialize(); ++ cvm_oct_configure_common_hw(); ++ ++ cvmx_helper_initialize_packet_io_global(); ++ ++ /* Change the input group for all ports before input is enabled */ ++ num_interfaces = cvmx_helper_get_number_of_interfaces(); ++ for (interface = 0; interface < num_interfaces; interface++) { ++ int num_ports = cvmx_helper_ports_on_interface(interface); ++ int port; ++ ++ for (port = cvmx_helper_get_ipd_port(interface, 0); ++ port < cvmx_helper_get_ipd_port(interface, num_ports); ++ port++) { ++ union cvmx_pip_prt_tagx pip_prt_tagx; ++ pip_prt_tagx.u64 = ++ cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); ++ pip_prt_tagx.s.grp = pow_receive_group; ++ cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), ++ pip_prt_tagx.u64); ++ } ++ } ++ ++ cvmx_helper_ipd_and_packet_input_enable(); ++ ++ memset(cvm_oct_device, 0, sizeof(cvm_oct_device)); ++ ++ /* ++ * Initialize the FAU used for counting packet buffers that ++ * need to be freed. ++ */ ++ cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); ++ ++ if ((pow_send_group != -1)) { ++ struct net_device *dev; ++ pr_info("\tConfiguring device for POW only access\n"); ++ dev = alloc_etherdev(sizeof(struct octeon_ethernet)); ++ if (dev) { ++ /* Initialize the device private structure. */ ++ struct octeon_ethernet *priv = netdev_priv(dev); ++ memset(priv, 0, sizeof(struct octeon_ethernet)); ++ ++ dev->init = cvm_oct_common_init; ++ priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; ++ priv->port = CVMX_PIP_NUM_INPUT_PORTS; ++ priv->queue = -1; ++ strcpy(dev->name, "pow%d"); ++ for (qos = 0; qos < 16; qos++) ++ skb_queue_head_init(&priv->tx_free_list[qos]); ++ ++ if (register_netdev(dev) < 0) { ++ pr_err("Failed to register ethernet " ++ "device for POW\n"); ++ kfree(dev); ++ } else { ++ cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev; ++ pr_info("%s: POW send group %d, receive " ++ "group %d\n", ++ dev->name, pow_send_group, ++ pow_receive_group); ++ } ++ } else { ++ pr_err("Failed to allocate ethernet device " ++ "for POW\n"); ++ } ++ } ++ ++ num_interfaces = cvmx_helper_get_number_of_interfaces(); ++ for (interface = 0; interface < num_interfaces; interface++) { ++ cvmx_helper_interface_mode_t imode = ++ cvmx_helper_interface_get_mode(interface); ++ int num_ports = cvmx_helper_ports_on_interface(interface); ++ int port; ++ ++ for (port = cvmx_helper_get_ipd_port(interface, 0); ++ port < cvmx_helper_get_ipd_port(interface, num_ports); ++ port++) { ++ struct octeon_ethernet *priv; ++ struct net_device *dev = ++ alloc_etherdev(sizeof(struct octeon_ethernet)); ++ if (!dev) { ++ pr_err("Failed to allocate ethernet device " ++ "for port %d\n", port); ++ continue; ++ } ++ if (disable_core_queueing) ++ dev->tx_queue_len = 0; ++ ++ /* Initialize the device private structure. */ ++ priv = netdev_priv(dev); ++ memset(priv, 0, sizeof(struct octeon_ethernet)); ++ ++ priv->imode = imode; ++ priv->port = port; ++ priv->queue = cvmx_pko_get_base_queue(priv->port); ++ priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; ++ for (qos = 0; qos < 16; qos++) ++ skb_queue_head_init(&priv->tx_free_list[qos]); ++ for (qos = 0; qos < cvmx_pko_get_num_queues(port); ++ qos++) ++ cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); ++ ++ switch (priv->imode) { ++ ++ /* These types don't support ports to IPD/PKO */ ++ case CVMX_HELPER_INTERFACE_MODE_DISABLED: ++ case CVMX_HELPER_INTERFACE_MODE_PCIE: ++ case CVMX_HELPER_INTERFACE_MODE_PICMG: ++ break; ++ ++ case CVMX_HELPER_INTERFACE_MODE_NPI: ++ dev->init = cvm_oct_common_init; ++ dev->uninit = cvm_oct_common_uninit; ++ strcpy(dev->name, "npi%d"); ++ break; ++ ++ case CVMX_HELPER_INTERFACE_MODE_XAUI: ++ dev->init = cvm_oct_xaui_init; ++ dev->uninit = cvm_oct_xaui_uninit; ++ strcpy(dev->name, "xaui%d"); ++ break; ++ ++ case CVMX_HELPER_INTERFACE_MODE_LOOP: ++ dev->init = cvm_oct_common_init; ++ dev->uninit = cvm_oct_common_uninit; ++ strcpy(dev->name, "loop%d"); ++ break; ++ ++ case CVMX_HELPER_INTERFACE_MODE_SGMII: ++ dev->init = cvm_oct_sgmii_init; ++ dev->uninit = cvm_oct_sgmii_uninit; ++ strcpy(dev->name, "eth%d"); ++ break; ++ ++ case CVMX_HELPER_INTERFACE_MODE_SPI: ++ dev->init = cvm_oct_spi_init; ++ dev->uninit = cvm_oct_spi_uninit; ++ strcpy(dev->name, "spi%d"); ++ break; ++ ++ case CVMX_HELPER_INTERFACE_MODE_RGMII: ++ case CVMX_HELPER_INTERFACE_MODE_GMII: ++ dev->init = cvm_oct_rgmii_init; ++ dev->uninit = cvm_oct_rgmii_uninit; ++ strcpy(dev->name, "eth%d"); ++ break; ++ } ++ ++ if (!dev->init) { ++ kfree(dev); ++ } else if (register_netdev(dev) < 0) { ++ pr_err("Failed to register ethernet device " ++ "for interface %d, port %d\n", ++ interface, priv->port); ++ kfree(dev); ++ } else { ++ cvm_oct_device[priv->port] = dev; ++ fau -= ++ cvmx_pko_get_num_queues(priv->port) * ++ sizeof(uint32_t); ++ } ++ } ++ } ++ ++ if (INTERRUPT_LIMIT) { ++ /* ++ * Set the POW timer rate to give an interrupt at most ++ * INTERRUPT_LIMIT times per second. ++ */ ++ cvmx_write_csr(CVMX_POW_WQ_INT_PC, ++ octeon_bootinfo->eclock_hz / (INTERRUPT_LIMIT * ++ 16 * 256) << 8); ++ ++ /* ++ * Enable POW timer interrupt. It will count when ++ * there are packets available. ++ */ ++ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), ++ 0x1ful << 24); ++ } else { ++ /* Enable POW interrupt when our port has at least one packet */ ++ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0x1001); ++ } ++ ++ /* Enable the poll timer for checking RGMII status */ ++ init_timer(&cvm_oct_poll_timer); ++ cvm_oct_poll_timer.data = 0; ++ cvm_oct_poll_timer.function = cvm_do_timer; ++ mod_timer(&cvm_oct_poll_timer, jiffies + HZ); ++ ++ return 0; ++} ++ ++/** ++ * Module / driver shutdown ++ * ++ * Returns Zero on success ++ */ ++static void __exit cvm_oct_cleanup_module(void) ++{ ++ int port; ++ ++ /* Disable POW interrupt */ ++ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); ++ ++ cvmx_ipd_disable(); ++ ++ /* Free the interrupt handler */ ++ free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); ++ ++ del_timer(&cvm_oct_poll_timer); ++ cvm_oct_rx_shutdown(); ++ cvmx_pko_disable(); ++ ++ /* Free the ethernet devices */ ++ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { ++ if (cvm_oct_device[port]) { ++ cvm_oct_tx_shutdown(cvm_oct_device[port]); ++ unregister_netdev(cvm_oct_device[port]); ++ kfree(cvm_oct_device[port]); ++ cvm_oct_device[port] = NULL; ++ } ++ } ++ ++ cvmx_pko_shutdown(); ++ cvm_oct_proc_shutdown(); ++ ++ cvmx_ipd_free_ptr(); ++ ++ /* Free the HW pools */ ++ cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, ++ num_packet_buffers); ++ cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, ++ num_packet_buffers); ++ if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) ++ cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, ++ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); ++} ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Cavium Networks "); ++MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver."); ++module_init(cvm_oct_init_module); ++module_exit(cvm_oct_cleanup_module); +--- /dev/null ++++ b/drivers/staging/octeon/octeon-ethernet.h +@@ -0,0 +1,127 @@ ++/********************************************************************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2007 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++**********************************************************************/ ++ ++/* ++ * External interface for the Cavium Octeon ethernet driver. ++ */ ++#ifndef OCTEON_ETHERNET_H ++#define OCTEON_ETHERNET_H ++ ++/** ++ * This is the definition of the Ethernet driver's private ++ * driver state stored in netdev_priv(dev). ++ */ ++struct octeon_ethernet { ++ /* PKO hardware output port */ ++ int port; ++ /* PKO hardware queue for the port */ ++ int queue; ++ /* Hardware fetch and add to count outstanding tx buffers */ ++ int fau; ++ /* ++ * Type of port. This is one of the enums in ++ * cvmx_helper_interface_mode_t ++ */ ++ int imode; ++ /* List of outstanding tx buffers per queue */ ++ struct sk_buff_head tx_free_list[16]; ++ /* Device statistics */ ++ struct net_device_stats stats ++; /* Generic MII info structure */ ++ struct mii_if_info mii_info; ++ /* Last negotiated link state */ ++ uint64_t link_info; ++ /* Called periodically to check link status */ ++ void (*poll) (struct net_device *dev); ++}; ++ ++/** ++ * Free a work queue entry received in a intercept callback. ++ * ++ * @work_queue_entry: ++ * Work queue entry to free ++ * Returns Zero on success, Negative on failure. ++ */ ++int cvm_oct_free_work(void *work_queue_entry); ++ ++/** ++ * Transmit a work queue entry out of the ethernet port. Both ++ * the work queue entry and the packet data can optionally be ++ * freed. The work will be freed on error as well. ++ * ++ * @dev: Device to transmit out. ++ * @work_queue_entry: ++ * Work queue entry to send ++ * @do_free: True if the work queue entry and packet data should be ++ * freed. If false, neither will be freed. ++ * @qos: Index into the queues for this port to transmit on. This ++ * is used to implement QoS if their are multiple queues per ++ * port. This parameter must be between 0 and the number of ++ * queues per port minus 1. Values outside of this range will ++ * be change to zero. ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, ++ int do_free, int qos); ++ ++/** ++ * Transmit a work queue entry out of the ethernet port. Both ++ * the work queue entry and the packet data can optionally be ++ * freed. The work will be freed on error as well. This simply ++ * wraps cvmx_oct_transmit_qos() for backwards compatability. ++ * ++ * @dev: Device to transmit out. ++ * @work_queue_entry: ++ * Work queue entry to send ++ * @do_free: True if the work queue entry and packet data should be ++ * freed. If false, neither will be freed. ++ * ++ * Returns Zero on success, negative on failure. ++ */ ++static inline int cvm_oct_transmit(struct net_device *dev, ++ void *work_queue_entry, int do_free) ++{ ++ return cvm_oct_transmit_qos(dev, work_queue_entry, do_free, 0); ++} ++ ++extern int cvm_oct_rgmii_init(struct net_device *dev); ++extern void cvm_oct_rgmii_uninit(struct net_device *dev); ++extern int cvm_oct_sgmii_init(struct net_device *dev); ++extern void cvm_oct_sgmii_uninit(struct net_device *dev); ++extern int cvm_oct_spi_init(struct net_device *dev); ++extern void cvm_oct_spi_uninit(struct net_device *dev); ++extern int cvm_oct_xaui_init(struct net_device *dev); ++extern void cvm_oct_xaui_uninit(struct net_device *dev); ++ ++extern int always_use_pow; ++extern int pow_send_group; ++extern int pow_receive_group; ++extern char pow_send_list[]; ++extern struct net_device *cvm_oct_device[]; ++ ++#endif diff --git a/target/linux/octeon/patches-2.6.30/012-hook_up_eth_driver.patch b/target/linux/octeon/patches-2.6.30/012-hook_up_eth_driver.patch new file mode 100644 index 0000000000..1a9dc00649 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/012-hook_up_eth_driver.patch @@ -0,0 +1,26 @@ +The previous patch adds the driver files for octeon-ethernet. Here we +hook them up into the main kernel build system. + +Signed-off-by: David Daney +--- + drivers/staging/Kconfig | 2 ++ + drivers/staging/Makefile | 1 + + 2 files changed, 3 insertions(+), 0 deletions(-) + +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -115,5 +115,7 @@ source "drivers/staging/line6/Kconfig" + + source "drivers/staging/serqt_usb/Kconfig" + ++source "drivers/staging/octeon/Kconfig" ++ + endif # !STAGING_EXCLUDE_BUILD + endif # STAGING +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -40,3 +40,4 @@ obj-$(CONFIG_PLAN9AUTH) += p9auth/ + obj-$(CONFIG_HECI) += heci/ + obj-$(CONFIG_LINE6_USB) += line6/ + obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb/ ++obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ diff --git a/target/linux/octeon/patches-2.6.30/013-compile_fixes.patch b/target/linux/octeon/patches-2.6.30/013-compile_fixes.patch new file mode 100644 index 0000000000..89338f4e8f --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/013-compile_fixes.patch @@ -0,0 +1,85 @@ +--- a/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c +@@ -272,6 +272,7 @@ fix_ipd_exit: + * + * Returns Zero on success, negative on failure + */ ++#if 0 + int __cvmx_helper_errata_asx_pass1(int interface, int port, int cpu_clock_hz) + { + /* Set hi water mark as per errata GMX-4 */ +@@ -289,6 +290,7 @@ int __cvmx_helper_errata_asx_pass1(int i + cpu_clock_hz); + return 0; + } ++#endif + + /** + * This function needs to be called on all Octeon chips with +--- a/arch/mips/include/asm/octeon/cvmx-helper-errata.h ++++ b/arch/mips/include/asm/octeon/cvmx-helper-errata.h +@@ -60,8 +60,8 @@ extern int __cvmx_helper_errata_fix_ipd_ + * + * Returns Zero on success, negative on failure + */ +-extern int __cvmx_helper_errata_asx_pass1(int interface, int port, +- int cpu_clock_hz); ++//extern int __cvmx_helper_errata_asx_pass1(int interface, int port, ++// int cpu_clock_hz); + + /** + * This function needs to be called on all Octeon chips with +--- a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c +@@ -356,6 +356,7 @@ int cvmx_helper_get_ipd_port(int interfa + * + * Returns Interface number + */ ++#if 0 + int cvmx_helper_get_interface_num(int ipd_port) + { + if (ipd_port < 16) +@@ -372,6 +373,7 @@ int cvmx_helper_get_interface_num(int ip + + return -1; + } ++#endif + + /** + * Returns the interface index number for an IPD/PKO port +@@ -381,6 +383,7 @@ int cvmx_helper_get_interface_num(int ip + * + * Returns Interface index number + */ ++#if 0 + int cvmx_helper_get_interface_index_num(int ipd_port) + { + if (ipd_port < 32) +@@ -395,6 +398,7 @@ int cvmx_helper_get_interface_index_num( + + return -1; + } ++#endif + + /** + * Initialize the internal QLM JTAG logic to allow programming +--- a/arch/mips/include/asm/octeon/cvmx-helper-util.h ++++ b/arch/mips/include/asm/octeon/cvmx-helper-util.h +@@ -205,7 +205,7 @@ static inline void cvmx_helper_free_pack + * + * Returns Interface number + */ +-extern int cvmx_helper_get_interface_num(int ipd_port); ++//extern int cvmx_helper_get_interface_num(int ipd_port); + + /** + * Returns the interface index number for an IPD/PKO port +@@ -215,7 +215,7 @@ extern int cvmx_helper_get_interface_num + * + * Returns Interface index number + */ +-extern int cvmx_helper_get_interface_index_num(int ipd_port); ++//extern int cvmx_helper_get_interface_index_num(int ipd_port); + + /** + * Initialize the internal QLM JTAG logic to allow programming diff --git a/target/linux/octeon/patches-2.6.30/015-no_werror.patch b/target/linux/octeon/patches-2.6.30/015-no_werror.patch new file mode 100644 index 0000000000..71842dd1aa --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/015-no_werror.patch @@ -0,0 +1,8 @@ +--- a/arch/mips/cavium-octeon/Makefile ++++ b/arch/mips/cavium-octeon/Makefile +@@ -18,5 +18,3 @@ obj-$(CONFIG_PCI) += + obj-$(CONFIG_PCI) += pci.o + obj-$(CONFIG_PCI) += pcie.o + obj-$(CONFIG_PCI_MSI) += msi.o +- +-EXTRA_CFLAGS += -Werror diff --git a/target/linux/octeon/patches-2.6.30/016-octeon_hw_rng.patch b/target/linux/octeon/patches-2.6.30/016-octeon_hw_rng.patch new file mode 100644 index 0000000000..65afe7705a --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/016-octeon_hw_rng.patch @@ -0,0 +1,351 @@ +From: David Daney +Date: Thu, 20 Aug 2009 21:10:22 +0000 (-0700) +Subject: MIPS: Octeon: Add hardware RNG platform device. +X-Git-Tag: linux-2.6.32-rc1~34 +X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=c691b963;hp=a68577bc6ce2b5e422cdb7a993b1c07cc410e02a + +MIPS: Octeon: Add hardware RNG platform device. + +Add a platform device for the Octeon Random Number Generator (RNG). + +Signed-off-by: David Daney +Acked-by: Herbert Xu +Signed-off-by: Ralf Baechle +--- + +Index: linux-2.6.30.8/arch/mips/cavium-octeon/setup.c +=================================================================== +--- linux-2.6.30.8.orig/arch/mips/cavium-octeon/setup.c 2009-09-24 17:28:02.000000000 +0200 ++++ linux-2.6.30.8/arch/mips/cavium-octeon/setup.c 2009-10-08 13:10:09.000000000 +0200 +@@ -32,6 +32,7 @@ + #include + + #include ++#include + + #ifdef CONFIG_CAVIUM_DECODE_RSL + extern void cvmx_interrupt_rsl_decode(void); +@@ -925,3 +926,45 @@ + return ret; + } + device_initcall(octeon_cf_device_init); ++ ++/* Octeon Random Number Generator. */ ++static int __init octeon_rng_device_init(void) ++{ ++ struct platform_device *pd; ++ int ret = 0; ++ ++ struct resource rng_resources[] = { ++ { ++ .flags = IORESOURCE_MEM, ++ .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), ++ .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf ++ }, { ++ .flags = IORESOURCE_MEM, ++ .start = cvmx_build_io_address(8, 0), ++ .end = cvmx_build_io_address(8, 0) + 0x7 ++ } ++ }; ++ ++ pd = platform_device_alloc("octeon_rng", -1); ++ if (!pd) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = platform_device_add_resources(pd, rng_resources, ++ ARRAY_SIZE(rng_resources)); ++ if (ret) ++ goto fail; ++ ++ ret = platform_device_add(pd); ++ if (ret) ++ goto fail; ++ ++ return ret; ++fail: ++ platform_device_put(pd); ++ ++out: ++ return ret; ++} ++device_initcall(octeon_rng_device_init); +Index: linux-2.6.30.8/arch/mips/include/asm/octeon/cvmx-rnm-defs.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.30.8/arch/mips/include/asm/octeon/cvmx-rnm-defs.h 2009-10-08 13:10:09.000000000 +0200 +@@ -0,0 +1,88 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_RNM_DEFS_H__ ++#define __CVMX_RNM_DEFS_H__ ++ ++#include ++ ++#define CVMX_RNM_BIST_STATUS \ ++ CVMX_ADD_IO_SEG(0x0001180040000008ull) ++#define CVMX_RNM_CTL_STATUS \ ++ CVMX_ADD_IO_SEG(0x0001180040000000ull) ++ ++union cvmx_rnm_bist_status { ++ uint64_t u64; ++ struct cvmx_rnm_bist_status_s { ++ uint64_t reserved_2_63:62; ++ uint64_t rrc:1; ++ uint64_t mem:1; ++ } s; ++ struct cvmx_rnm_bist_status_s cn30xx; ++ struct cvmx_rnm_bist_status_s cn31xx; ++ struct cvmx_rnm_bist_status_s cn38xx; ++ struct cvmx_rnm_bist_status_s cn38xxp2; ++ struct cvmx_rnm_bist_status_s cn50xx; ++ struct cvmx_rnm_bist_status_s cn52xx; ++ struct cvmx_rnm_bist_status_s cn52xxp1; ++ struct cvmx_rnm_bist_status_s cn56xx; ++ struct cvmx_rnm_bist_status_s cn56xxp1; ++ struct cvmx_rnm_bist_status_s cn58xx; ++ struct cvmx_rnm_bist_status_s cn58xxp1; ++}; ++ ++union cvmx_rnm_ctl_status { ++ uint64_t u64; ++ struct cvmx_rnm_ctl_status_s { ++ uint64_t reserved_9_63:55; ++ uint64_t ent_sel:4; ++ uint64_t exp_ent:1; ++ uint64_t rng_rst:1; ++ uint64_t rnm_rst:1; ++ uint64_t rng_en:1; ++ uint64_t ent_en:1; ++ } s; ++ struct cvmx_rnm_ctl_status_cn30xx { ++ uint64_t reserved_4_63:60; ++ uint64_t rng_rst:1; ++ uint64_t rnm_rst:1; ++ uint64_t rng_en:1; ++ uint64_t ent_en:1; ++ } cn30xx; ++ struct cvmx_rnm_ctl_status_cn30xx cn31xx; ++ struct cvmx_rnm_ctl_status_cn30xx cn38xx; ++ struct cvmx_rnm_ctl_status_cn30xx cn38xxp2; ++ struct cvmx_rnm_ctl_status_s cn50xx; ++ struct cvmx_rnm_ctl_status_s cn52xx; ++ struct cvmx_rnm_ctl_status_s cn52xxp1; ++ struct cvmx_rnm_ctl_status_s cn56xx; ++ struct cvmx_rnm_ctl_status_s cn56xxp1; ++ struct cvmx_rnm_ctl_status_s cn58xx; ++ struct cvmx_rnm_ctl_status_s cn58xxp1; ++}; ++ ++#endif +Index: linux-2.6.30.8/drivers/char/hw_random/Kconfig +=================================================================== +--- linux-2.6.30.8.orig/drivers/char/hw_random/Kconfig 2009-09-24 17:28:02.000000000 +0200 ++++ linux-2.6.30.8/drivers/char/hw_random/Kconfig 2009-10-08 13:10:09.000000000 +0200 +@@ -126,6 +126,19 @@ + + If unsure, say Y. + ++config HW_RANDOM_OCTEON ++ tristate "Octeon Random Number Generator support" ++ depends on HW_RANDOM && CPU_CAVIUM_OCTEON ++ default HW_RANDOM ++ ---help--- ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Octeon processors. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called octeon-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_PASEMI + tristate "PA Semi HW Random Number Generator support" + depends on HW_RANDOM && PPC_PASEMI +Index: linux-2.6.30.8/drivers/char/hw_random/Makefile +=================================================================== +--- linux-2.6.30.8.orig/drivers/char/hw_random/Makefile 2009-09-24 17:28:02.000000000 +0200 ++++ linux-2.6.30.8/drivers/char/hw_random/Makefile 2009-10-08 13:10:23.000000000 +0200 +@@ -15,3 +15,4 @@ + obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o + obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o + obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o ++obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o +Index: linux-2.6.30.8/drivers/char/hw_random/octeon-rng.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.30.8/drivers/char/hw_random/octeon-rng.c 2009-10-08 13:10:09.000000000 +0200 +@@ -0,0 +1,147 @@ ++/* ++ * Hardware Random Number Generator support for Cavium Networks ++ * Octeon processor family. ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2009 Cavium Networks ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct octeon_rng { ++ struct hwrng ops; ++ void __iomem *control_status; ++ void __iomem *result; ++}; ++ ++static int octeon_rng_init(struct hwrng *rng) ++{ ++ union cvmx_rnm_ctl_status ctl; ++ struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); ++ ++ ctl.u64 = 0; ++ ctl.s.ent_en = 1; /* Enable the entropy source. */ ++ ctl.s.rng_en = 1; /* Enable the RNG hardware. */ ++ cvmx_write_csr((u64)p->control_status, ctl.u64); ++ return 0; ++} ++ ++static void octeon_rng_cleanup(struct hwrng *rng) ++{ ++ union cvmx_rnm_ctl_status ctl; ++ struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); ++ ++ ctl.u64 = 0; ++ /* Disable everything. */ ++ cvmx_write_csr((u64)p->control_status, ctl.u64); ++} ++ ++static int octeon_rng_data_read(struct hwrng *rng, u32 *data) ++{ ++ struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); ++ ++ *data = cvmx_read64_uint32((u64)p->result); ++ return sizeof(u32); ++} ++ ++static int __devinit octeon_rng_probe(struct platform_device *pdev) ++{ ++ struct resource *res_ports; ++ struct resource *res_result; ++ struct octeon_rng *rng; ++ int ret; ++ struct hwrng ops = { ++ .name = "octeon", ++ .init = octeon_rng_init, ++ .cleanup = octeon_rng_cleanup, ++ .data_read = octeon_rng_data_read ++ }; ++ ++ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); ++ if (!rng) ++ return -ENOMEM; ++ ++ res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res_ports) ++ goto err_ports; ++ ++ res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res_result) ++ goto err_ports; ++ ++ ++ rng->control_status = devm_ioremap_nocache(&pdev->dev, ++ res_ports->start, ++ sizeof(u64)); ++ if (!rng->control_status) ++ goto err_ports; ++ ++ rng->result = devm_ioremap_nocache(&pdev->dev, ++ res_result->start, ++ sizeof(u64)); ++ if (!rng->result) ++ goto err_r; ++ ++ rng->ops = ops; ++ ++ dev_set_drvdata(&pdev->dev, &rng->ops); ++ ret = hwrng_register(&rng->ops); ++ if (ret) ++ goto err; ++ ++ dev_info(&pdev->dev, "Octeon Random Number Generator\n"); ++ ++ return 0; ++err: ++ devm_iounmap(&pdev->dev, rng->control_status); ++err_r: ++ devm_iounmap(&pdev->dev, rng->result); ++err_ports: ++ devm_kfree(&pdev->dev, rng); ++ return -ENOENT; ++} ++ ++static int __exit octeon_rng_remove(struct platform_device *pdev) ++{ ++ struct hwrng *rng = dev_get_drvdata(&pdev->dev); ++ ++ hwrng_unregister(rng); ++ ++ return 0; ++} ++ ++static struct platform_driver octeon_rng_driver = { ++ .driver = { ++ .name = "octeon_rng", ++ .owner = THIS_MODULE, ++ }, ++ .probe = octeon_rng_probe, ++ .remove = __exit_p(octeon_rng_remove), ++}; ++ ++static int __init octeon_rng_mod_init(void) ++{ ++ return platform_driver_register(&octeon_rng_driver); ++} ++ ++static void __exit octeon_rng_mod_exit(void) ++{ ++ platform_driver_unregister(&octeon_rng_driver); ++} ++ ++module_init(octeon_rng_mod_init); ++module_exit(octeon_rng_mod_exit); ++ ++MODULE_AUTHOR("David Daney"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/octeon/patches-2.6.30/017-platform_devices.patch b/target/linux/octeon/patches-2.6.30/017-platform_devices.patch new file mode 100644 index 0000000000..12c2ef181f --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/017-platform_devices.patch @@ -0,0 +1,371 @@ +From: David Daney +Date: Wed, 16 Sep 2009 21:54:18 +0000 (-0700) +Subject: MIPS: Octeon: Move some platform device registration to its own file. +X-Git-Tag: linux-2.6.32-rc1~29 +X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=936c111e;hp=e1302af3482d3955f5a6100160e595e792d5f1e4 + +MIPS: Octeon: Move some platform device registration to its own file. + +There is a bunch of platform device registration in +arch/mips/cavium-octeon/setup.c. We move it to its own file in +preparation for adding more platform devices. + +Signed-off-by: David Daney +Signed-off-by: Ralf Baechle +--- + +diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile +index d6903c3..1394362 100644 +--- a/arch/mips/cavium-octeon/Makefile ++++ b/arch/mips/cavium-octeon/Makefile +@@ -6,10 +6,10 @@ + # License. See the file "COPYING" in the main directory of this archive + # for more details. + # +-# Copyright (C) 2005-2008 Cavium Networks ++# Copyright (C) 2005-2009 Cavium Networks + # + +-obj-y := setup.o serial.o octeon-irq.o csrc-octeon.o ++obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o + obj-y += dma-octeon.o flash_setup.o + obj-y += octeon-memcpy.o + +diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c +new file mode 100644 +index 0000000..be711dd +--- /dev/null ++++ b/arch/mips/cavium-octeon/octeon-platform.c +@@ -0,0 +1,164 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2004-2009 Cavium Networks ++ * Copyright (C) 2008 Wind River Systems ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static struct octeon_cf_data octeon_cf_data; ++ ++static int __init octeon_cf_device_init(void) ++{ ++ union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; ++ unsigned long base_ptr, region_base, region_size; ++ struct platform_device *pd; ++ struct resource cf_resources[3]; ++ unsigned int num_resources; ++ int i; ++ int ret = 0; ++ ++ /* Setup octeon-cf platform device if present. */ ++ base_ptr = 0; ++ if (octeon_bootinfo->major_version == 1 ++ && octeon_bootinfo->minor_version >= 1) { ++ if (octeon_bootinfo->compact_flash_common_base_addr) ++ base_ptr = ++ octeon_bootinfo->compact_flash_common_base_addr; ++ } else { ++ base_ptr = 0x1d000800; ++ } ++ ++ if (!base_ptr) ++ return ret; ++ ++ /* Find CS0 region. */ ++ for (i = 0; i < 8; i++) { ++ mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i)); ++ region_base = mio_boot_reg_cfg.s.base << 16; ++ region_size = (mio_boot_reg_cfg.s.size + 1) << 16; ++ if (mio_boot_reg_cfg.s.en && base_ptr >= region_base ++ && base_ptr < region_base + region_size) ++ break; ++ } ++ if (i >= 7) { ++ /* i and i + 1 are CS0 and CS1, both must be less than 8. */ ++ goto out; ++ } ++ octeon_cf_data.base_region = i; ++ octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width; ++ octeon_cf_data.base_region_bias = base_ptr - region_base; ++ memset(cf_resources, 0, sizeof(cf_resources)); ++ num_resources = 0; ++ cf_resources[num_resources].flags = IORESOURCE_MEM; ++ cf_resources[num_resources].start = region_base; ++ cf_resources[num_resources].end = region_base + region_size - 1; ++ num_resources++; ++ ++ ++ if (!(base_ptr & 0xfffful)) { ++ /* ++ * Boot loader signals availability of DMA (true_ide ++ * mode) by setting low order bits of base_ptr to ++ * zero. ++ */ ++ ++ /* Asume that CS1 immediately follows. */ ++ mio_boot_reg_cfg.u64 = ++ cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1)); ++ region_base = mio_boot_reg_cfg.s.base << 16; ++ region_size = (mio_boot_reg_cfg.s.size + 1) << 16; ++ if (!mio_boot_reg_cfg.s.en) ++ goto out; ++ ++ cf_resources[num_resources].flags = IORESOURCE_MEM; ++ cf_resources[num_resources].start = region_base; ++ cf_resources[num_resources].end = region_base + region_size - 1; ++ num_resources++; ++ ++ octeon_cf_data.dma_engine = 0; ++ cf_resources[num_resources].flags = IORESOURCE_IRQ; ++ cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA; ++ cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA; ++ num_resources++; ++ } else { ++ octeon_cf_data.dma_engine = -1; ++ } ++ ++ pd = platform_device_alloc("pata_octeon_cf", -1); ++ if (!pd) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ pd->dev.platform_data = &octeon_cf_data; ++ ++ ret = platform_device_add_resources(pd, cf_resources, num_resources); ++ if (ret) ++ goto fail; ++ ++ ret = platform_device_add(pd); ++ if (ret) ++ goto fail; ++ ++ return ret; ++fail: ++ platform_device_put(pd); ++out: ++ return ret; ++} ++device_initcall(octeon_cf_device_init); ++ ++/* Octeon Random Number Generator. */ ++static int __init octeon_rng_device_init(void) ++{ ++ struct platform_device *pd; ++ int ret = 0; ++ ++ struct resource rng_resources[] = { ++ { ++ .flags = IORESOURCE_MEM, ++ .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), ++ .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf ++ }, { ++ .flags = IORESOURCE_MEM, ++ .start = cvmx_build_io_address(8, 0), ++ .end = cvmx_build_io_address(8, 0) + 0x7 ++ } ++ }; ++ ++ pd = platform_device_alloc("octeon_rng", -1); ++ if (!pd) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = platform_device_add_resources(pd, rng_resources, ++ ARRAY_SIZE(rng_resources)); ++ if (ret) ++ goto fail; ++ ++ ret = platform_device_add(pd); ++ if (ret) ++ goto fail; ++ ++ return ret; ++fail: ++ platform_device_put(pd); ++ ++out: ++ return ret; ++} ++device_initcall(octeon_rng_device_init); ++ ++MODULE_AUTHOR("David Daney "); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Platform driver for Octeon SOC"); +diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c +index 468a120..b321d3b 100644 +--- a/arch/mips/cavium-octeon/setup.c ++++ b/arch/mips/cavium-octeon/setup.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -33,7 +32,6 @@ + #include + + #include +-#include + + #ifdef CONFIG_CAVIUM_DECODE_RSL + extern void cvmx_interrupt_rsl_decode(void); +@@ -825,147 +823,3 @@ void prom_free_prom_memory(void) + CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB option is set */ + octeon_hal_setup_reserved32(); + } +- +-static struct octeon_cf_data octeon_cf_data; +- +-static int __init octeon_cf_device_init(void) +-{ +- union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; +- unsigned long base_ptr, region_base, region_size; +- struct platform_device *pd; +- struct resource cf_resources[3]; +- unsigned int num_resources; +- int i; +- int ret = 0; +- +- /* Setup octeon-cf platform device if present. */ +- base_ptr = 0; +- if (octeon_bootinfo->major_version == 1 +- && octeon_bootinfo->minor_version >= 1) { +- if (octeon_bootinfo->compact_flash_common_base_addr) +- base_ptr = +- octeon_bootinfo->compact_flash_common_base_addr; +- } else { +- base_ptr = 0x1d000800; +- } +- +- if (!base_ptr) +- return ret; +- +- /* Find CS0 region. */ +- for (i = 0; i < 8; i++) { +- mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i)); +- region_base = mio_boot_reg_cfg.s.base << 16; +- region_size = (mio_boot_reg_cfg.s.size + 1) << 16; +- if (mio_boot_reg_cfg.s.en && base_ptr >= region_base +- && base_ptr < region_base + region_size) +- break; +- } +- if (i >= 7) { +- /* i and i + 1 are CS0 and CS1, both must be less than 8. */ +- goto out; +- } +- octeon_cf_data.base_region = i; +- octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width; +- octeon_cf_data.base_region_bias = base_ptr - region_base; +- memset(cf_resources, 0, sizeof(cf_resources)); +- num_resources = 0; +- cf_resources[num_resources].flags = IORESOURCE_MEM; +- cf_resources[num_resources].start = region_base; +- cf_resources[num_resources].end = region_base + region_size - 1; +- num_resources++; +- +- +- if (!(base_ptr & 0xfffful)) { +- /* +- * Boot loader signals availability of DMA (true_ide +- * mode) by setting low order bits of base_ptr to +- * zero. +- */ +- +- /* Asume that CS1 immediately follows. */ +- mio_boot_reg_cfg.u64 = +- cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1)); +- region_base = mio_boot_reg_cfg.s.base << 16; +- region_size = (mio_boot_reg_cfg.s.size + 1) << 16; +- if (!mio_boot_reg_cfg.s.en) +- goto out; +- +- cf_resources[num_resources].flags = IORESOURCE_MEM; +- cf_resources[num_resources].start = region_base; +- cf_resources[num_resources].end = region_base + region_size - 1; +- num_resources++; +- +- octeon_cf_data.dma_engine = 0; +- cf_resources[num_resources].flags = IORESOURCE_IRQ; +- cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA; +- cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA; +- num_resources++; +- } else { +- octeon_cf_data.dma_engine = -1; +- } +- +- pd = platform_device_alloc("pata_octeon_cf", -1); +- if (!pd) { +- ret = -ENOMEM; +- goto out; +- } +- pd->dev.platform_data = &octeon_cf_data; +- +- ret = platform_device_add_resources(pd, cf_resources, num_resources); +- if (ret) +- goto fail; +- +- ret = platform_device_add(pd); +- if (ret) +- goto fail; +- +- return ret; +-fail: +- platform_device_put(pd); +-out: +- return ret; +-} +-device_initcall(octeon_cf_device_init); +- +-/* Octeon Random Number Generator. */ +-static int __init octeon_rng_device_init(void) +-{ +- struct platform_device *pd; +- int ret = 0; +- +- struct resource rng_resources[] = { +- { +- .flags = IORESOURCE_MEM, +- .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), +- .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf +- }, { +- .flags = IORESOURCE_MEM, +- .start = cvmx_build_io_address(8, 0), +- .end = cvmx_build_io_address(8, 0) + 0x7 +- } +- }; +- +- pd = platform_device_alloc("octeon_rng", -1); +- if (!pd) { +- ret = -ENOMEM; +- goto out; +- } +- +- ret = platform_device_add_resources(pd, rng_resources, +- ARRAY_SIZE(rng_resources)); +- if (ret) +- goto fail; +- +- ret = platform_device_add(pd); +- if (ret) +- goto fail; +- +- return ret; +-fail: +- platform_device_put(pd); +- +-out: +- return ret; +-} +-device_initcall(octeon_rng_device_init); diff --git a/target/linux/octeon/patches-2.6.30/018-dwc_otg.patch b/target/linux/octeon/patches-2.6.30/018-dwc_otg.patch new file mode 100644 index 0000000000..6f4a4d68ba --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/018-dwc_otg.patch @@ -0,0 +1,17496 @@ +Signed-off-by: David Daney +--- + arch/mips/cavium-octeon/octeon-platform.c | 105 ++ + arch/mips/include/asm/octeon/cvmx-usbcx-defs.h | 1199 ++++++++++++++++++++++++ + arch/mips/include/asm/octeon/cvmx-usbnx-defs.h | 760 +++++++++++++++ + 3 files changed, 2064 insertions(+), 0 deletions(-) + create mode 100644 arch/mips/include/asm/octeon/cvmx-usbcx-defs.h + create mode 100644 arch/mips/include/asm/octeon/cvmx-usbnx-defs.h + +diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c +index cfdb4c2..20698a6 100644 +--- a/arch/mips/cavium-octeon/octeon-platform.c ++++ b/arch/mips/cavium-octeon/octeon-platform.c +@@ -7,13 +7,19 @@ + * Copyright (C) 2008 Wind River Systems + */ + ++#include + #include + #include ++#include + #include + #include + ++#include ++ + #include + #include ++#include ++#include + + static struct octeon_cf_data octeon_cf_data; + +@@ -247,6 +253,105 @@ out: + } + device_initcall(octeon_mgmt_device_init); + ++/* Octeon USB. */ ++static int __init octeon_usb_device_init(void) ++{ ++ int p_rtype_ref_clk = 2; ++ int number_usb_ports; ++ int usb_port; ++ int ret = 0; ++ ++ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { ++ number_usb_ports = 0; ++ } else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { ++ number_usb_ports = 2; ++ /* CN52XX encodes this field differently */ ++ p_rtype_ref_clk = 1; ++ } else { ++ number_usb_ports = 1; ++ } ++ ++ for (usb_port = 0; usb_port < number_usb_ports; usb_port++) { ++ int divisor; ++ union cvmx_usbnx_clk_ctl usbn_clk_ctl; ++ struct platform_device *pdev; ++ struct resource usb_resource[2]; ++ ++ /* ++ * Divide the core clock down such that USB is as ++ * close as possible to 125Mhz. ++ */ ++ divisor = DIV_ROUND_UP(mips_hpt_frequency, 125000000); ++ /* Lower than 4 doesn't seem to work properly */ ++ if (divisor < 4) ++ divisor = 4; ++ ++ /* Fetch the value of the Register, and de-assert POR */ ++ usbn_clk_ctl.u64 = cvmx_read_csr(CVMX_USBNX_CLK_CTL(usb_port)); ++ usbn_clk_ctl.s.por = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ usbn_clk_ctl.cn31xx.p_rclk = 1; ++ usbn_clk_ctl.cn31xx.p_xenbn = 0; ++ } else { ++ if (cvmx_sysinfo_get()->board_type != ++ CVMX_BOARD_TYPE_BBGW_REF) ++ usbn_clk_ctl.cn56xx.p_rtype = p_rtype_ref_clk; ++ else ++ usbn_clk_ctl.cn56xx.p_rtype = 0; ++ } ++ usbn_clk_ctl.s.divide = divisor; ++ usbn_clk_ctl.s.divide2 = 0; ++ cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb_port), usbn_clk_ctl.u64); ++ ++ /* Wait for POR */ ++ udelay(850); ++ ++ usbn_clk_ctl.u64 = cvmx_read_csr(CVMX_USBNX_CLK_CTL(usb_port)); ++ usbn_clk_ctl.s.por = 0; ++ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { ++ usbn_clk_ctl.cn31xx.p_rclk = 1; ++ usbn_clk_ctl.cn31xx.p_xenbn = 0; ++ } else { ++ if (cvmx_sysinfo_get()->board_type != ++ CVMX_BOARD_TYPE_BBGW_REF) ++ usbn_clk_ctl.cn56xx.p_rtype = p_rtype_ref_clk; ++ else ++ usbn_clk_ctl.cn56xx.p_rtype = 0; ++ } ++ usbn_clk_ctl.s.prst = 1; ++ cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb_port), usbn_clk_ctl.u64); ++ ++ udelay(1); ++ ++ usbn_clk_ctl.s.hrst = 1; ++ cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb_port), usbn_clk_ctl.u64); ++ udelay(1); ++ ++ memset(usb_resource, 0, sizeof(usb_resource)); ++ usb_resource[0].start = ++ XKPHYS_TO_PHYS(CVMX_USBCX_GOTGCTL(usb_port)); ++ usb_resource[0].end = usb_resource[0].start + 0x10000; ++ usb_resource[0].flags = IORESOURCE_MEM; ++ ++ usb_resource[1].start = (usb_port == 0) ? ++ OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1; ++ usb_resource[1].end = usb_resource[1].start; ++ usb_resource[1].flags = IORESOURCE_IRQ; ++ ++ pdev = platform_device_register_simple("dwc_otg", ++ usb_port, ++ usb_resource, 2); ++ if (!pdev) { ++ pr_err("dwc_otg: Failed to allocate platform device " ++ "for USB%d\n", usb_port); ++ ret = -ENOMEM; ++ } ++ } ++ ++ return ret; ++} ++device_initcall(octeon_usb_device_init); ++ + MODULE_AUTHOR("David Daney "); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Platform driver for Octeon SOC"); +diff --git a/arch/mips/include/asm/octeon/cvmx-usbcx-defs.h b/arch/mips/include/asm/octeon/cvmx-usbcx-defs.h +new file mode 100644 +index 0000000..c1e078e +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-usbcx-defs.h +@@ -0,0 +1,1199 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_USBCX_DEFS_H__ ++#define __CVMX_USBCX_DEFS_H__ ++ ++#define CVMX_USBCX_DAINT(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000818ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DAINTMSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001000081Cull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DCFG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000800ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DCTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000804ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DIEPCTLX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000900ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DIEPINTX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000908ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DIEPMSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000810ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DIEPTSIZX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000910ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DOEPCTLX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000B00ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DOEPINTX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000B08ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DOEPMSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000814ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DOEPTSIZX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000B10ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DPTXFSIZX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000100ull + (((offset) & 7) * 4) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DSTS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000808ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DTKNQR1(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000820ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DTKNQR2(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000824ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DTKNQR3(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000830ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_DTKNQR4(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000834ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GAHBCFG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000008ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GHWCFG1(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000044ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GHWCFG2(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000048ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GHWCFG3(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001000004Cull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GHWCFG4(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000050ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GINTMSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000018ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GINTSTS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000014ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GNPTXFSIZ(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000028ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GNPTXSTS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001000002Cull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GOTGCTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000000ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GOTGINT(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000004ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GRSTCTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000010ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GRXFSIZ(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000024ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GRXSTSPD(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010040020ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GRXSTSPH(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000020ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GRXSTSRD(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001004001Cull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GRXSTSRH(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001000001Cull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GSNPSID(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000040ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_GUSBCFG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001000000Cull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HAINT(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000414ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HAINTMSK(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000418ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HCCHARX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000500ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HCFG(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000400ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HCINTMSKX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F001000050Cull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HCINTX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000508ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HCSPLTX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000504ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HCTSIZX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000510ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HFIR(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000404ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HFNUM(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000408ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HPRT(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000440ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HPTXFSIZ(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000100ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_HPTXSTS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000410ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_NPTXDFIFOX(offset, block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010001000ull + (((offset) & 7) * 4096) + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBCX_PCGCCTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0010000E00ull + (((block_id) & 1) * 0x100000000000ull)) ++ ++union cvmx_usbcx_daint { ++ uint32_t u32; ++ struct cvmx_usbcx_daint_s { ++ uint32_t outepint:16; ++ uint32_t inepint:16; ++ } s; ++ struct cvmx_usbcx_daint_s cn30xx; ++ struct cvmx_usbcx_daint_s cn31xx; ++ struct cvmx_usbcx_daint_s cn50xx; ++ struct cvmx_usbcx_daint_s cn52xx; ++ struct cvmx_usbcx_daint_s cn52xxp1; ++ struct cvmx_usbcx_daint_s cn56xx; ++ struct cvmx_usbcx_daint_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_daintmsk { ++ uint32_t u32; ++ struct cvmx_usbcx_daintmsk_s { ++ uint32_t outepmsk:16; ++ uint32_t inepmsk:16; ++ } s; ++ struct cvmx_usbcx_daintmsk_s cn30xx; ++ struct cvmx_usbcx_daintmsk_s cn31xx; ++ struct cvmx_usbcx_daintmsk_s cn50xx; ++ struct cvmx_usbcx_daintmsk_s cn52xx; ++ struct cvmx_usbcx_daintmsk_s cn52xxp1; ++ struct cvmx_usbcx_daintmsk_s cn56xx; ++ struct cvmx_usbcx_daintmsk_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dcfg { ++ uint32_t u32; ++ struct cvmx_usbcx_dcfg_s { ++ uint32_t reserved_23_31:9; ++ uint32_t epmiscnt:5; ++ uint32_t reserved_13_17:5; ++ uint32_t perfrint:2; ++ uint32_t devaddr:7; ++ uint32_t reserved_3_3:1; ++ uint32_t nzstsouthshk:1; ++ uint32_t devspd:2; ++ } s; ++ struct cvmx_usbcx_dcfg_s cn30xx; ++ struct cvmx_usbcx_dcfg_s cn31xx; ++ struct cvmx_usbcx_dcfg_s cn50xx; ++ struct cvmx_usbcx_dcfg_s cn52xx; ++ struct cvmx_usbcx_dcfg_s cn52xxp1; ++ struct cvmx_usbcx_dcfg_s cn56xx; ++ struct cvmx_usbcx_dcfg_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dctl { ++ uint32_t u32; ++ struct cvmx_usbcx_dctl_s { ++ uint32_t reserved_12_31:20; ++ uint32_t pwronprgdone:1; ++ uint32_t cgoutnak:1; ++ uint32_t sgoutnak:1; ++ uint32_t cgnpinnak:1; ++ uint32_t sgnpinnak:1; ++ uint32_t tstctl:3; ++ uint32_t goutnaksts:1; ++ uint32_t gnpinnaksts:1; ++ uint32_t sftdiscon:1; ++ uint32_t rmtwkupsig:1; ++ } s; ++ struct cvmx_usbcx_dctl_s cn30xx; ++ struct cvmx_usbcx_dctl_s cn31xx; ++ struct cvmx_usbcx_dctl_s cn50xx; ++ struct cvmx_usbcx_dctl_s cn52xx; ++ struct cvmx_usbcx_dctl_s cn52xxp1; ++ struct cvmx_usbcx_dctl_s cn56xx; ++ struct cvmx_usbcx_dctl_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_diepctlx { ++ uint32_t u32; ++ struct cvmx_usbcx_diepctlx_s { ++ uint32_t epena:1; ++ uint32_t epdis:1; ++ uint32_t setd1pid:1; ++ uint32_t setd0pid:1; ++ uint32_t snak:1; ++ uint32_t cnak:1; ++ uint32_t txfnum:4; ++ uint32_t stall:1; ++ uint32_t reserved_20_20:1; ++ uint32_t eptype:2; ++ uint32_t naksts:1; ++ uint32_t dpid:1; ++ uint32_t usbactep:1; ++ uint32_t nextep:4; ++ uint32_t mps:11; ++ } s; ++ struct cvmx_usbcx_diepctlx_s cn30xx; ++ struct cvmx_usbcx_diepctlx_s cn31xx; ++ struct cvmx_usbcx_diepctlx_s cn50xx; ++ struct cvmx_usbcx_diepctlx_s cn52xx; ++ struct cvmx_usbcx_diepctlx_s cn52xxp1; ++ struct cvmx_usbcx_diepctlx_s cn56xx; ++ struct cvmx_usbcx_diepctlx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_diepintx { ++ uint32_t u32; ++ struct cvmx_usbcx_diepintx_s { ++ uint32_t reserved_7_31:25; ++ uint32_t inepnakeff:1; ++ uint32_t intknepmis:1; ++ uint32_t intkntxfemp:1; ++ uint32_t timeout:1; ++ uint32_t ahberr:1; ++ uint32_t epdisbld:1; ++ uint32_t xfercompl:1; ++ } s; ++ struct cvmx_usbcx_diepintx_s cn30xx; ++ struct cvmx_usbcx_diepintx_s cn31xx; ++ struct cvmx_usbcx_diepintx_s cn50xx; ++ struct cvmx_usbcx_diepintx_s cn52xx; ++ struct cvmx_usbcx_diepintx_s cn52xxp1; ++ struct cvmx_usbcx_diepintx_s cn56xx; ++ struct cvmx_usbcx_diepintx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_diepmsk { ++ uint32_t u32; ++ struct cvmx_usbcx_diepmsk_s { ++ uint32_t reserved_7_31:25; ++ uint32_t inepnakeffmsk:1; ++ uint32_t intknepmismsk:1; ++ uint32_t intkntxfempmsk:1; ++ uint32_t timeoutmsk:1; ++ uint32_t ahberrmsk:1; ++ uint32_t epdisbldmsk:1; ++ uint32_t xfercomplmsk:1; ++ } s; ++ struct cvmx_usbcx_diepmsk_s cn30xx; ++ struct cvmx_usbcx_diepmsk_s cn31xx; ++ struct cvmx_usbcx_diepmsk_s cn50xx; ++ struct cvmx_usbcx_diepmsk_s cn52xx; ++ struct cvmx_usbcx_diepmsk_s cn52xxp1; ++ struct cvmx_usbcx_diepmsk_s cn56xx; ++ struct cvmx_usbcx_diepmsk_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dieptsizx { ++ uint32_t u32; ++ struct cvmx_usbcx_dieptsizx_s { ++ uint32_t reserved_31_31:1; ++ uint32_t mc:2; ++ uint32_t pktcnt:10; ++ uint32_t xfersize:19; ++ } s; ++ struct cvmx_usbcx_dieptsizx_s cn30xx; ++ struct cvmx_usbcx_dieptsizx_s cn31xx; ++ struct cvmx_usbcx_dieptsizx_s cn50xx; ++ struct cvmx_usbcx_dieptsizx_s cn52xx; ++ struct cvmx_usbcx_dieptsizx_s cn52xxp1; ++ struct cvmx_usbcx_dieptsizx_s cn56xx; ++ struct cvmx_usbcx_dieptsizx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_doepctlx { ++ uint32_t u32; ++ struct cvmx_usbcx_doepctlx_s { ++ uint32_t epena:1; ++ uint32_t epdis:1; ++ uint32_t setd1pid:1; ++ uint32_t setd0pid:1; ++ uint32_t snak:1; ++ uint32_t cnak:1; ++ uint32_t reserved_22_25:4; ++ uint32_t stall:1; ++ uint32_t snp:1; ++ uint32_t eptype:2; ++ uint32_t naksts:1; ++ uint32_t dpid:1; ++ uint32_t usbactep:1; ++ uint32_t reserved_11_14:4; ++ uint32_t mps:11; ++ } s; ++ struct cvmx_usbcx_doepctlx_s cn30xx; ++ struct cvmx_usbcx_doepctlx_s cn31xx; ++ struct cvmx_usbcx_doepctlx_s cn50xx; ++ struct cvmx_usbcx_doepctlx_s cn52xx; ++ struct cvmx_usbcx_doepctlx_s cn52xxp1; ++ struct cvmx_usbcx_doepctlx_s cn56xx; ++ struct cvmx_usbcx_doepctlx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_doepintx { ++ uint32_t u32; ++ struct cvmx_usbcx_doepintx_s { ++ uint32_t reserved_5_31:27; ++ uint32_t outtknepdis:1; ++ uint32_t setup:1; ++ uint32_t ahberr:1; ++ uint32_t epdisbld:1; ++ uint32_t xfercompl:1; ++ } s; ++ struct cvmx_usbcx_doepintx_s cn30xx; ++ struct cvmx_usbcx_doepintx_s cn31xx; ++ struct cvmx_usbcx_doepintx_s cn50xx; ++ struct cvmx_usbcx_doepintx_s cn52xx; ++ struct cvmx_usbcx_doepintx_s cn52xxp1; ++ struct cvmx_usbcx_doepintx_s cn56xx; ++ struct cvmx_usbcx_doepintx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_doepmsk { ++ uint32_t u32; ++ struct cvmx_usbcx_doepmsk_s { ++ uint32_t reserved_5_31:27; ++ uint32_t outtknepdismsk:1; ++ uint32_t setupmsk:1; ++ uint32_t ahberrmsk:1; ++ uint32_t epdisbldmsk:1; ++ uint32_t xfercomplmsk:1; ++ } s; ++ struct cvmx_usbcx_doepmsk_s cn30xx; ++ struct cvmx_usbcx_doepmsk_s cn31xx; ++ struct cvmx_usbcx_doepmsk_s cn50xx; ++ struct cvmx_usbcx_doepmsk_s cn52xx; ++ struct cvmx_usbcx_doepmsk_s cn52xxp1; ++ struct cvmx_usbcx_doepmsk_s cn56xx; ++ struct cvmx_usbcx_doepmsk_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_doeptsizx { ++ uint32_t u32; ++ struct cvmx_usbcx_doeptsizx_s { ++ uint32_t reserved_31_31:1; ++ uint32_t mc:2; ++ uint32_t pktcnt:10; ++ uint32_t xfersize:19; ++ } s; ++ struct cvmx_usbcx_doeptsizx_s cn30xx; ++ struct cvmx_usbcx_doeptsizx_s cn31xx; ++ struct cvmx_usbcx_doeptsizx_s cn50xx; ++ struct cvmx_usbcx_doeptsizx_s cn52xx; ++ struct cvmx_usbcx_doeptsizx_s cn52xxp1; ++ struct cvmx_usbcx_doeptsizx_s cn56xx; ++ struct cvmx_usbcx_doeptsizx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dptxfsizx { ++ uint32_t u32; ++ struct cvmx_usbcx_dptxfsizx_s { ++ uint32_t dptxfsize:16; ++ uint32_t dptxfstaddr:16; ++ } s; ++ struct cvmx_usbcx_dptxfsizx_s cn30xx; ++ struct cvmx_usbcx_dptxfsizx_s cn31xx; ++ struct cvmx_usbcx_dptxfsizx_s cn50xx; ++ struct cvmx_usbcx_dptxfsizx_s cn52xx; ++ struct cvmx_usbcx_dptxfsizx_s cn52xxp1; ++ struct cvmx_usbcx_dptxfsizx_s cn56xx; ++ struct cvmx_usbcx_dptxfsizx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dsts { ++ uint32_t u32; ++ struct cvmx_usbcx_dsts_s { ++ uint32_t reserved_22_31:10; ++ uint32_t soffn:14; ++ uint32_t reserved_4_7:4; ++ uint32_t errticerr:1; ++ uint32_t enumspd:2; ++ uint32_t suspsts:1; ++ } s; ++ struct cvmx_usbcx_dsts_s cn30xx; ++ struct cvmx_usbcx_dsts_s cn31xx; ++ struct cvmx_usbcx_dsts_s cn50xx; ++ struct cvmx_usbcx_dsts_s cn52xx; ++ struct cvmx_usbcx_dsts_s cn52xxp1; ++ struct cvmx_usbcx_dsts_s cn56xx; ++ struct cvmx_usbcx_dsts_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dtknqr1 { ++ uint32_t u32; ++ struct cvmx_usbcx_dtknqr1_s { ++ uint32_t eptkn:24; ++ uint32_t wrapbit:1; ++ uint32_t reserved_5_6:2; ++ uint32_t intknwptr:5; ++ } s; ++ struct cvmx_usbcx_dtknqr1_s cn30xx; ++ struct cvmx_usbcx_dtknqr1_s cn31xx; ++ struct cvmx_usbcx_dtknqr1_s cn50xx; ++ struct cvmx_usbcx_dtknqr1_s cn52xx; ++ struct cvmx_usbcx_dtknqr1_s cn52xxp1; ++ struct cvmx_usbcx_dtknqr1_s cn56xx; ++ struct cvmx_usbcx_dtknqr1_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dtknqr2 { ++ uint32_t u32; ++ struct cvmx_usbcx_dtknqr2_s { ++ uint32_t eptkn:32; ++ } s; ++ struct cvmx_usbcx_dtknqr2_s cn30xx; ++ struct cvmx_usbcx_dtknqr2_s cn31xx; ++ struct cvmx_usbcx_dtknqr2_s cn50xx; ++ struct cvmx_usbcx_dtknqr2_s cn52xx; ++ struct cvmx_usbcx_dtknqr2_s cn52xxp1; ++ struct cvmx_usbcx_dtknqr2_s cn56xx; ++ struct cvmx_usbcx_dtknqr2_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dtknqr3 { ++ uint32_t u32; ++ struct cvmx_usbcx_dtknqr3_s { ++ uint32_t eptkn:32; ++ } s; ++ struct cvmx_usbcx_dtknqr3_s cn30xx; ++ struct cvmx_usbcx_dtknqr3_s cn31xx; ++ struct cvmx_usbcx_dtknqr3_s cn50xx; ++ struct cvmx_usbcx_dtknqr3_s cn52xx; ++ struct cvmx_usbcx_dtknqr3_s cn52xxp1; ++ struct cvmx_usbcx_dtknqr3_s cn56xx; ++ struct cvmx_usbcx_dtknqr3_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_dtknqr4 { ++ uint32_t u32; ++ struct cvmx_usbcx_dtknqr4_s { ++ uint32_t eptkn:32; ++ } s; ++ struct cvmx_usbcx_dtknqr4_s cn30xx; ++ struct cvmx_usbcx_dtknqr4_s cn31xx; ++ struct cvmx_usbcx_dtknqr4_s cn50xx; ++ struct cvmx_usbcx_dtknqr4_s cn52xx; ++ struct cvmx_usbcx_dtknqr4_s cn52xxp1; ++ struct cvmx_usbcx_dtknqr4_s cn56xx; ++ struct cvmx_usbcx_dtknqr4_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gahbcfg { ++ uint32_t u32; ++ struct cvmx_usbcx_gahbcfg_s { ++ uint32_t reserved_9_31:23; ++ uint32_t ptxfemplvl:1; ++ uint32_t nptxfemplvl:1; ++ uint32_t reserved_6_6:1; ++ uint32_t dmaen:1; ++ uint32_t hbstlen:4; ++ uint32_t glblintrmsk:1; ++ } s; ++ struct cvmx_usbcx_gahbcfg_s cn30xx; ++ struct cvmx_usbcx_gahbcfg_s cn31xx; ++ struct cvmx_usbcx_gahbcfg_s cn50xx; ++ struct cvmx_usbcx_gahbcfg_s cn52xx; ++ struct cvmx_usbcx_gahbcfg_s cn52xxp1; ++ struct cvmx_usbcx_gahbcfg_s cn56xx; ++ struct cvmx_usbcx_gahbcfg_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_ghwcfg1 { ++ uint32_t u32; ++ struct cvmx_usbcx_ghwcfg1_s { ++ uint32_t epdir:32; ++ } s; ++ struct cvmx_usbcx_ghwcfg1_s cn30xx; ++ struct cvmx_usbcx_ghwcfg1_s cn31xx; ++ struct cvmx_usbcx_ghwcfg1_s cn50xx; ++ struct cvmx_usbcx_ghwcfg1_s cn52xx; ++ struct cvmx_usbcx_ghwcfg1_s cn52xxp1; ++ struct cvmx_usbcx_ghwcfg1_s cn56xx; ++ struct cvmx_usbcx_ghwcfg1_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_ghwcfg2 { ++ uint32_t u32; ++ struct cvmx_usbcx_ghwcfg2_s { ++ uint32_t reserved_31_31:1; ++ uint32_t tknqdepth:5; ++ uint32_t ptxqdepth:2; ++ uint32_t nptxqdepth:2; ++ uint32_t reserved_20_21:2; ++ uint32_t dynfifosizing:1; ++ uint32_t periosupport:1; ++ uint32_t numhstchnl:4; ++ uint32_t numdeveps:4; ++ uint32_t fsphytype:2; ++ uint32_t hsphytype:2; ++ uint32_t singpnt:1; ++ uint32_t otgarch:2; ++ uint32_t otgmode:3; ++ } s; ++ struct cvmx_usbcx_ghwcfg2_s cn30xx; ++ struct cvmx_usbcx_ghwcfg2_s cn31xx; ++ struct cvmx_usbcx_ghwcfg2_s cn50xx; ++ struct cvmx_usbcx_ghwcfg2_s cn52xx; ++ struct cvmx_usbcx_ghwcfg2_s cn52xxp1; ++ struct cvmx_usbcx_ghwcfg2_s cn56xx; ++ struct cvmx_usbcx_ghwcfg2_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_ghwcfg3 { ++ uint32_t u32; ++ struct cvmx_usbcx_ghwcfg3_s { ++ uint32_t dfifodepth:16; ++ uint32_t reserved_13_15:3; ++ uint32_t ahbphysync:1; ++ uint32_t rsttype:1; ++ uint32_t optfeature:1; ++ uint32_t vendor_control_interface_support:1; ++ uint32_t i2c_selection:1; ++ uint32_t otgen:1; ++ uint32_t pktsizewidth:3; ++ uint32_t xfersizewidth:4; ++ } s; ++ struct cvmx_usbcx_ghwcfg3_s cn30xx; ++ struct cvmx_usbcx_ghwcfg3_s cn31xx; ++ struct cvmx_usbcx_ghwcfg3_s cn50xx; ++ struct cvmx_usbcx_ghwcfg3_s cn52xx; ++ struct cvmx_usbcx_ghwcfg3_s cn52xxp1; ++ struct cvmx_usbcx_ghwcfg3_s cn56xx; ++ struct cvmx_usbcx_ghwcfg3_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_ghwcfg4 { ++ uint32_t u32; ++ struct cvmx_usbcx_ghwcfg4_s { ++ uint32_t reserved_30_31:2; ++ uint32_t numdevmodinend:4; ++ uint32_t endedtrfifo:1; ++ uint32_t sessendfltr:1; ++ uint32_t bvalidfltr:1; ++ uint32_t avalidfltr:1; ++ uint32_t vbusvalidfltr:1; ++ uint32_t iddgfltr:1; ++ uint32_t numctleps:4; ++ uint32_t phydatawidth:2; ++ uint32_t reserved_6_13:8; ++ uint32_t ahbfreq:1; ++ uint32_t enablepwropt:1; ++ uint32_t numdevperioeps:4; ++ } s; ++ struct cvmx_usbcx_ghwcfg4_cn30xx { ++ uint32_t reserved_25_31:7; ++ uint32_t sessendfltr:1; ++ uint32_t bvalidfltr:1; ++ uint32_t avalidfltr:1; ++ uint32_t vbusvalidfltr:1; ++ uint32_t iddgfltr:1; ++ uint32_t numctleps:4; ++ uint32_t phydatawidth:2; ++ uint32_t reserved_6_13:8; ++ uint32_t ahbfreq:1; ++ uint32_t enablepwropt:1; ++ uint32_t numdevperioeps:4; ++ } cn30xx; ++ struct cvmx_usbcx_ghwcfg4_cn30xx cn31xx; ++ struct cvmx_usbcx_ghwcfg4_s cn50xx; ++ struct cvmx_usbcx_ghwcfg4_s cn52xx; ++ struct cvmx_usbcx_ghwcfg4_s cn52xxp1; ++ struct cvmx_usbcx_ghwcfg4_s cn56xx; ++ struct cvmx_usbcx_ghwcfg4_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gintmsk { ++ uint32_t u32; ++ struct cvmx_usbcx_gintmsk_s { ++ uint32_t wkupintmsk:1; ++ uint32_t sessreqintmsk:1; ++ uint32_t disconnintmsk:1; ++ uint32_t conidstschngmsk:1; ++ uint32_t reserved_27_27:1; ++ uint32_t ptxfempmsk:1; ++ uint32_t hchintmsk:1; ++ uint32_t prtintmsk:1; ++ uint32_t reserved_23_23:1; ++ uint32_t fetsuspmsk:1; ++ uint32_t incomplpmsk:1; ++ uint32_t incompisoinmsk:1; ++ uint32_t oepintmsk:1; ++ uint32_t inepintmsk:1; ++ uint32_t epmismsk:1; ++ uint32_t reserved_16_16:1; ++ uint32_t eopfmsk:1; ++ uint32_t isooutdropmsk:1; ++ uint32_t enumdonemsk:1; ++ uint32_t usbrstmsk:1; ++ uint32_t usbsuspmsk:1; ++ uint32_t erlysuspmsk:1; ++ uint32_t i2cint:1; ++ uint32_t ulpickintmsk:1; ++ uint32_t goutnakeffmsk:1; ++ uint32_t ginnakeffmsk:1; ++ uint32_t nptxfempmsk:1; ++ uint32_t rxflvlmsk:1; ++ uint32_t sofmsk:1; ++ uint32_t otgintmsk:1; ++ uint32_t modemismsk:1; ++ uint32_t reserved_0_0:1; ++ } s; ++ struct cvmx_usbcx_gintmsk_s cn30xx; ++ struct cvmx_usbcx_gintmsk_s cn31xx; ++ struct cvmx_usbcx_gintmsk_s cn50xx; ++ struct cvmx_usbcx_gintmsk_s cn52xx; ++ struct cvmx_usbcx_gintmsk_s cn52xxp1; ++ struct cvmx_usbcx_gintmsk_s cn56xx; ++ struct cvmx_usbcx_gintmsk_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gintsts { ++ uint32_t u32; ++ struct cvmx_usbcx_gintsts_s { ++ uint32_t wkupint:1; ++ uint32_t sessreqint:1; ++ uint32_t disconnint:1; ++ uint32_t conidstschng:1; ++ uint32_t reserved_27_27:1; ++ uint32_t ptxfemp:1; ++ uint32_t hchint:1; ++ uint32_t prtint:1; ++ uint32_t reserved_23_23:1; ++ uint32_t fetsusp:1; ++ uint32_t incomplp:1; ++ uint32_t incompisoin:1; ++ uint32_t oepint:1; ++ uint32_t iepint:1; ++ uint32_t epmis:1; ++ uint32_t reserved_16_16:1; ++ uint32_t eopf:1; ++ uint32_t isooutdrop:1; ++ uint32_t enumdone:1; ++ uint32_t usbrst:1; ++ uint32_t usbsusp:1; ++ uint32_t erlysusp:1; ++ uint32_t i2cint:1; ++ uint32_t ulpickint:1; ++ uint32_t goutnakeff:1; ++ uint32_t ginnakeff:1; ++ uint32_t nptxfemp:1; ++ uint32_t rxflvl:1; ++ uint32_t sof:1; ++ uint32_t otgint:1; ++ uint32_t modemis:1; ++ uint32_t curmod:1; ++ } s; ++ struct cvmx_usbcx_gintsts_s cn30xx; ++ struct cvmx_usbcx_gintsts_s cn31xx; ++ struct cvmx_usbcx_gintsts_s cn50xx; ++ struct cvmx_usbcx_gintsts_s cn52xx; ++ struct cvmx_usbcx_gintsts_s cn52xxp1; ++ struct cvmx_usbcx_gintsts_s cn56xx; ++ struct cvmx_usbcx_gintsts_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gnptxfsiz { ++ uint32_t u32; ++ struct cvmx_usbcx_gnptxfsiz_s { ++ uint32_t nptxfdep:16; ++ uint32_t nptxfstaddr:16; ++ } s; ++ struct cvmx_usbcx_gnptxfsiz_s cn30xx; ++ struct cvmx_usbcx_gnptxfsiz_s cn31xx; ++ struct cvmx_usbcx_gnptxfsiz_s cn50xx; ++ struct cvmx_usbcx_gnptxfsiz_s cn52xx; ++ struct cvmx_usbcx_gnptxfsiz_s cn52xxp1; ++ struct cvmx_usbcx_gnptxfsiz_s cn56xx; ++ struct cvmx_usbcx_gnptxfsiz_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gnptxsts { ++ uint32_t u32; ++ struct cvmx_usbcx_gnptxsts_s { ++ uint32_t reserved_31_31:1; ++ uint32_t nptxqtop:7; ++ uint32_t nptxqspcavail:8; ++ uint32_t nptxfspcavail:16; ++ } s; ++ struct cvmx_usbcx_gnptxsts_s cn30xx; ++ struct cvmx_usbcx_gnptxsts_s cn31xx; ++ struct cvmx_usbcx_gnptxsts_s cn50xx; ++ struct cvmx_usbcx_gnptxsts_s cn52xx; ++ struct cvmx_usbcx_gnptxsts_s cn52xxp1; ++ struct cvmx_usbcx_gnptxsts_s cn56xx; ++ struct cvmx_usbcx_gnptxsts_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gotgctl { ++ uint32_t u32; ++ struct cvmx_usbcx_gotgctl_s { ++ uint32_t reserved_20_31:12; ++ uint32_t bsesvld:1; ++ uint32_t asesvld:1; ++ uint32_t dbnctime:1; ++ uint32_t conidsts:1; ++ uint32_t reserved_12_15:4; ++ uint32_t devhnpen:1; ++ uint32_t hstsethnpen:1; ++ uint32_t hnpreq:1; ++ uint32_t hstnegscs:1; ++ uint32_t reserved_2_7:6; ++ uint32_t sesreq:1; ++ uint32_t sesreqscs:1; ++ } s; ++ struct cvmx_usbcx_gotgctl_s cn30xx; ++ struct cvmx_usbcx_gotgctl_s cn31xx; ++ struct cvmx_usbcx_gotgctl_s cn50xx; ++ struct cvmx_usbcx_gotgctl_s cn52xx; ++ struct cvmx_usbcx_gotgctl_s cn52xxp1; ++ struct cvmx_usbcx_gotgctl_s cn56xx; ++ struct cvmx_usbcx_gotgctl_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gotgint { ++ uint32_t u32; ++ struct cvmx_usbcx_gotgint_s { ++ uint32_t reserved_20_31:12; ++ uint32_t dbncedone:1; ++ uint32_t adevtoutchg:1; ++ uint32_t hstnegdet:1; ++ uint32_t reserved_10_16:7; ++ uint32_t hstnegsucstschng:1; ++ uint32_t sesreqsucstschng:1; ++ uint32_t reserved_3_7:5; ++ uint32_t sesenddet:1; ++ uint32_t reserved_0_1:2; ++ } s; ++ struct cvmx_usbcx_gotgint_s cn30xx; ++ struct cvmx_usbcx_gotgint_s cn31xx; ++ struct cvmx_usbcx_gotgint_s cn50xx; ++ struct cvmx_usbcx_gotgint_s cn52xx; ++ struct cvmx_usbcx_gotgint_s cn52xxp1; ++ struct cvmx_usbcx_gotgint_s cn56xx; ++ struct cvmx_usbcx_gotgint_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_grstctl { ++ uint32_t u32; ++ struct cvmx_usbcx_grstctl_s { ++ uint32_t ahbidle:1; ++ uint32_t dmareq:1; ++ uint32_t reserved_11_29:19; ++ uint32_t txfnum:5; ++ uint32_t txfflsh:1; ++ uint32_t rxfflsh:1; ++ uint32_t intknqflsh:1; ++ uint32_t frmcntrrst:1; ++ uint32_t hsftrst:1; ++ uint32_t csftrst:1; ++ } s; ++ struct cvmx_usbcx_grstctl_s cn30xx; ++ struct cvmx_usbcx_grstctl_s cn31xx; ++ struct cvmx_usbcx_grstctl_s cn50xx; ++ struct cvmx_usbcx_grstctl_s cn52xx; ++ struct cvmx_usbcx_grstctl_s cn52xxp1; ++ struct cvmx_usbcx_grstctl_s cn56xx; ++ struct cvmx_usbcx_grstctl_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_grxfsiz { ++ uint32_t u32; ++ struct cvmx_usbcx_grxfsiz_s { ++ uint32_t reserved_16_31:16; ++ uint32_t rxfdep:16; ++ } s; ++ struct cvmx_usbcx_grxfsiz_s cn30xx; ++ struct cvmx_usbcx_grxfsiz_s cn31xx; ++ struct cvmx_usbcx_grxfsiz_s cn50xx; ++ struct cvmx_usbcx_grxfsiz_s cn52xx; ++ struct cvmx_usbcx_grxfsiz_s cn52xxp1; ++ struct cvmx_usbcx_grxfsiz_s cn56xx; ++ struct cvmx_usbcx_grxfsiz_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_grxstspd { ++ uint32_t u32; ++ struct cvmx_usbcx_grxstspd_s { ++ uint32_t reserved_25_31:7; ++ uint32_t fn:4; ++ uint32_t pktsts:4; ++ uint32_t dpid:2; ++ uint32_t bcnt:11; ++ uint32_t epnum:4; ++ } s; ++ struct cvmx_usbcx_grxstspd_s cn30xx; ++ struct cvmx_usbcx_grxstspd_s cn31xx; ++ struct cvmx_usbcx_grxstspd_s cn50xx; ++ struct cvmx_usbcx_grxstspd_s cn52xx; ++ struct cvmx_usbcx_grxstspd_s cn52xxp1; ++ struct cvmx_usbcx_grxstspd_s cn56xx; ++ struct cvmx_usbcx_grxstspd_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_grxstsph { ++ uint32_t u32; ++ struct cvmx_usbcx_grxstsph_s { ++ uint32_t reserved_21_31:11; ++ uint32_t pktsts:4; ++ uint32_t dpid:2; ++ uint32_t bcnt:11; ++ uint32_t chnum:4; ++ } s; ++ struct cvmx_usbcx_grxstsph_s cn30xx; ++ struct cvmx_usbcx_grxstsph_s cn31xx; ++ struct cvmx_usbcx_grxstsph_s cn50xx; ++ struct cvmx_usbcx_grxstsph_s cn52xx; ++ struct cvmx_usbcx_grxstsph_s cn52xxp1; ++ struct cvmx_usbcx_grxstsph_s cn56xx; ++ struct cvmx_usbcx_grxstsph_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_grxstsrd { ++ uint32_t u32; ++ struct cvmx_usbcx_grxstsrd_s { ++ uint32_t reserved_25_31:7; ++ uint32_t fn:4; ++ uint32_t pktsts:4; ++ uint32_t dpid:2; ++ uint32_t bcnt:11; ++ uint32_t epnum:4; ++ } s; ++ struct cvmx_usbcx_grxstsrd_s cn30xx; ++ struct cvmx_usbcx_grxstsrd_s cn31xx; ++ struct cvmx_usbcx_grxstsrd_s cn50xx; ++ struct cvmx_usbcx_grxstsrd_s cn52xx; ++ struct cvmx_usbcx_grxstsrd_s cn52xxp1; ++ struct cvmx_usbcx_grxstsrd_s cn56xx; ++ struct cvmx_usbcx_grxstsrd_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_grxstsrh { ++ uint32_t u32; ++ struct cvmx_usbcx_grxstsrh_s { ++ uint32_t reserved_21_31:11; ++ uint32_t pktsts:4; ++ uint32_t dpid:2; ++ uint32_t bcnt:11; ++ uint32_t chnum:4; ++ } s; ++ struct cvmx_usbcx_grxstsrh_s cn30xx; ++ struct cvmx_usbcx_grxstsrh_s cn31xx; ++ struct cvmx_usbcx_grxstsrh_s cn50xx; ++ struct cvmx_usbcx_grxstsrh_s cn52xx; ++ struct cvmx_usbcx_grxstsrh_s cn52xxp1; ++ struct cvmx_usbcx_grxstsrh_s cn56xx; ++ struct cvmx_usbcx_grxstsrh_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gsnpsid { ++ uint32_t u32; ++ struct cvmx_usbcx_gsnpsid_s { ++ uint32_t synopsysid:32; ++ } s; ++ struct cvmx_usbcx_gsnpsid_s cn30xx; ++ struct cvmx_usbcx_gsnpsid_s cn31xx; ++ struct cvmx_usbcx_gsnpsid_s cn50xx; ++ struct cvmx_usbcx_gsnpsid_s cn52xx; ++ struct cvmx_usbcx_gsnpsid_s cn52xxp1; ++ struct cvmx_usbcx_gsnpsid_s cn56xx; ++ struct cvmx_usbcx_gsnpsid_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_gusbcfg { ++ uint32_t u32; ++ struct cvmx_usbcx_gusbcfg_s { ++ uint32_t reserved_17_31:15; ++ uint32_t otgi2csel:1; ++ uint32_t phylpwrclksel:1; ++ uint32_t reserved_14_14:1; ++ uint32_t usbtrdtim:4; ++ uint32_t hnpcap:1; ++ uint32_t srpcap:1; ++ uint32_t ddrsel:1; ++ uint32_t physel:1; ++ uint32_t fsintf:1; ++ uint32_t ulpi_utmi_sel:1; ++ uint32_t phyif:1; ++ uint32_t toutcal:3; ++ } s; ++ struct cvmx_usbcx_gusbcfg_s cn30xx; ++ struct cvmx_usbcx_gusbcfg_s cn31xx; ++ struct cvmx_usbcx_gusbcfg_s cn50xx; ++ struct cvmx_usbcx_gusbcfg_s cn52xx; ++ struct cvmx_usbcx_gusbcfg_s cn52xxp1; ++ struct cvmx_usbcx_gusbcfg_s cn56xx; ++ struct cvmx_usbcx_gusbcfg_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_haint { ++ uint32_t u32; ++ struct cvmx_usbcx_haint_s { ++ uint32_t reserved_16_31:16; ++ uint32_t haint:16; ++ } s; ++ struct cvmx_usbcx_haint_s cn30xx; ++ struct cvmx_usbcx_haint_s cn31xx; ++ struct cvmx_usbcx_haint_s cn50xx; ++ struct cvmx_usbcx_haint_s cn52xx; ++ struct cvmx_usbcx_haint_s cn52xxp1; ++ struct cvmx_usbcx_haint_s cn56xx; ++ struct cvmx_usbcx_haint_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_haintmsk { ++ uint32_t u32; ++ struct cvmx_usbcx_haintmsk_s { ++ uint32_t reserved_16_31:16; ++ uint32_t haintmsk:16; ++ } s; ++ struct cvmx_usbcx_haintmsk_s cn30xx; ++ struct cvmx_usbcx_haintmsk_s cn31xx; ++ struct cvmx_usbcx_haintmsk_s cn50xx; ++ struct cvmx_usbcx_haintmsk_s cn52xx; ++ struct cvmx_usbcx_haintmsk_s cn52xxp1; ++ struct cvmx_usbcx_haintmsk_s cn56xx; ++ struct cvmx_usbcx_haintmsk_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hccharx { ++ uint32_t u32; ++ struct cvmx_usbcx_hccharx_s { ++ uint32_t chena:1; ++ uint32_t chdis:1; ++ uint32_t oddfrm:1; ++ uint32_t devaddr:7; ++ uint32_t ec:2; ++ uint32_t eptype:2; ++ uint32_t lspddev:1; ++ uint32_t reserved_16_16:1; ++ uint32_t epdir:1; ++ uint32_t epnum:4; ++ uint32_t mps:11; ++ } s; ++ struct cvmx_usbcx_hccharx_s cn30xx; ++ struct cvmx_usbcx_hccharx_s cn31xx; ++ struct cvmx_usbcx_hccharx_s cn50xx; ++ struct cvmx_usbcx_hccharx_s cn52xx; ++ struct cvmx_usbcx_hccharx_s cn52xxp1; ++ struct cvmx_usbcx_hccharx_s cn56xx; ++ struct cvmx_usbcx_hccharx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hcfg { ++ uint32_t u32; ++ struct cvmx_usbcx_hcfg_s { ++ uint32_t reserved_3_31:29; ++ uint32_t fslssupp:1; ++ uint32_t fslspclksel:2; ++ } s; ++ struct cvmx_usbcx_hcfg_s cn30xx; ++ struct cvmx_usbcx_hcfg_s cn31xx; ++ struct cvmx_usbcx_hcfg_s cn50xx; ++ struct cvmx_usbcx_hcfg_s cn52xx; ++ struct cvmx_usbcx_hcfg_s cn52xxp1; ++ struct cvmx_usbcx_hcfg_s cn56xx; ++ struct cvmx_usbcx_hcfg_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hcintx { ++ uint32_t u32; ++ struct cvmx_usbcx_hcintx_s { ++ uint32_t reserved_11_31:21; ++ uint32_t datatglerr:1; ++ uint32_t frmovrun:1; ++ uint32_t bblerr:1; ++ uint32_t xacterr:1; ++ uint32_t nyet:1; ++ uint32_t ack:1; ++ uint32_t nak:1; ++ uint32_t stall:1; ++ uint32_t ahberr:1; ++ uint32_t chhltd:1; ++ uint32_t xfercompl:1; ++ } s; ++ struct cvmx_usbcx_hcintx_s cn30xx; ++ struct cvmx_usbcx_hcintx_s cn31xx; ++ struct cvmx_usbcx_hcintx_s cn50xx; ++ struct cvmx_usbcx_hcintx_s cn52xx; ++ struct cvmx_usbcx_hcintx_s cn52xxp1; ++ struct cvmx_usbcx_hcintx_s cn56xx; ++ struct cvmx_usbcx_hcintx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hcintmskx { ++ uint32_t u32; ++ struct cvmx_usbcx_hcintmskx_s { ++ uint32_t reserved_11_31:21; ++ uint32_t datatglerrmsk:1; ++ uint32_t frmovrunmsk:1; ++ uint32_t bblerrmsk:1; ++ uint32_t xacterrmsk:1; ++ uint32_t nyetmsk:1; ++ uint32_t ackmsk:1; ++ uint32_t nakmsk:1; ++ uint32_t stallmsk:1; ++ uint32_t ahberrmsk:1; ++ uint32_t chhltdmsk:1; ++ uint32_t xfercomplmsk:1; ++ } s; ++ struct cvmx_usbcx_hcintmskx_s cn30xx; ++ struct cvmx_usbcx_hcintmskx_s cn31xx; ++ struct cvmx_usbcx_hcintmskx_s cn50xx; ++ struct cvmx_usbcx_hcintmskx_s cn52xx; ++ struct cvmx_usbcx_hcintmskx_s cn52xxp1; ++ struct cvmx_usbcx_hcintmskx_s cn56xx; ++ struct cvmx_usbcx_hcintmskx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hcspltx { ++ uint32_t u32; ++ struct cvmx_usbcx_hcspltx_s { ++ uint32_t spltena:1; ++ uint32_t reserved_17_30:14; ++ uint32_t compsplt:1; ++ uint32_t xactpos:2; ++ uint32_t hubaddr:7; ++ uint32_t prtaddr:7; ++ } s; ++ struct cvmx_usbcx_hcspltx_s cn30xx; ++ struct cvmx_usbcx_hcspltx_s cn31xx; ++ struct cvmx_usbcx_hcspltx_s cn50xx; ++ struct cvmx_usbcx_hcspltx_s cn52xx; ++ struct cvmx_usbcx_hcspltx_s cn52xxp1; ++ struct cvmx_usbcx_hcspltx_s cn56xx; ++ struct cvmx_usbcx_hcspltx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hctsizx { ++ uint32_t u32; ++ struct cvmx_usbcx_hctsizx_s { ++ uint32_t dopng:1; ++ uint32_t pid:2; ++ uint32_t pktcnt:10; ++ uint32_t xfersize:19; ++ } s; ++ struct cvmx_usbcx_hctsizx_s cn30xx; ++ struct cvmx_usbcx_hctsizx_s cn31xx; ++ struct cvmx_usbcx_hctsizx_s cn50xx; ++ struct cvmx_usbcx_hctsizx_s cn52xx; ++ struct cvmx_usbcx_hctsizx_s cn52xxp1; ++ struct cvmx_usbcx_hctsizx_s cn56xx; ++ struct cvmx_usbcx_hctsizx_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hfir { ++ uint32_t u32; ++ struct cvmx_usbcx_hfir_s { ++ uint32_t reserved_16_31:16; ++ uint32_t frint:16; ++ } s; ++ struct cvmx_usbcx_hfir_s cn30xx; ++ struct cvmx_usbcx_hfir_s cn31xx; ++ struct cvmx_usbcx_hfir_s cn50xx; ++ struct cvmx_usbcx_hfir_s cn52xx; ++ struct cvmx_usbcx_hfir_s cn52xxp1; ++ struct cvmx_usbcx_hfir_s cn56xx; ++ struct cvmx_usbcx_hfir_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hfnum { ++ uint32_t u32; ++ struct cvmx_usbcx_hfnum_s { ++ uint32_t frrem:16; ++ uint32_t frnum:16; ++ } s; ++ struct cvmx_usbcx_hfnum_s cn30xx; ++ struct cvmx_usbcx_hfnum_s cn31xx; ++ struct cvmx_usbcx_hfnum_s cn50xx; ++ struct cvmx_usbcx_hfnum_s cn52xx; ++ struct cvmx_usbcx_hfnum_s cn52xxp1; ++ struct cvmx_usbcx_hfnum_s cn56xx; ++ struct cvmx_usbcx_hfnum_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hprt { ++ uint32_t u32; ++ struct cvmx_usbcx_hprt_s { ++ uint32_t reserved_19_31:13; ++ uint32_t prtspd:2; ++ uint32_t prttstctl:4; ++ uint32_t prtpwr:1; ++ uint32_t prtlnsts:2; ++ uint32_t reserved_9_9:1; ++ uint32_t prtrst:1; ++ uint32_t prtsusp:1; ++ uint32_t prtres:1; ++ uint32_t prtovrcurrchng:1; ++ uint32_t prtovrcurract:1; ++ uint32_t prtenchng:1; ++ uint32_t prtena:1; ++ uint32_t prtconndet:1; ++ uint32_t prtconnsts:1; ++ } s; ++ struct cvmx_usbcx_hprt_s cn30xx; ++ struct cvmx_usbcx_hprt_s cn31xx; ++ struct cvmx_usbcx_hprt_s cn50xx; ++ struct cvmx_usbcx_hprt_s cn52xx; ++ struct cvmx_usbcx_hprt_s cn52xxp1; ++ struct cvmx_usbcx_hprt_s cn56xx; ++ struct cvmx_usbcx_hprt_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hptxfsiz { ++ uint32_t u32; ++ struct cvmx_usbcx_hptxfsiz_s { ++ uint32_t ptxfsize:16; ++ uint32_t ptxfstaddr:16; ++ } s; ++ struct cvmx_usbcx_hptxfsiz_s cn30xx; ++ struct cvmx_usbcx_hptxfsiz_s cn31xx; ++ struct cvmx_usbcx_hptxfsiz_s cn50xx; ++ struct cvmx_usbcx_hptxfsiz_s cn52xx; ++ struct cvmx_usbcx_hptxfsiz_s cn52xxp1; ++ struct cvmx_usbcx_hptxfsiz_s cn56xx; ++ struct cvmx_usbcx_hptxfsiz_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_hptxsts { ++ uint32_t u32; ++ struct cvmx_usbcx_hptxsts_s { ++ uint32_t ptxqtop:8; ++ uint32_t ptxqspcavail:8; ++ uint32_t ptxfspcavail:16; ++ } s; ++ struct cvmx_usbcx_hptxsts_s cn30xx; ++ struct cvmx_usbcx_hptxsts_s cn31xx; ++ struct cvmx_usbcx_hptxsts_s cn50xx; ++ struct cvmx_usbcx_hptxsts_s cn52xx; ++ struct cvmx_usbcx_hptxsts_s cn52xxp1; ++ struct cvmx_usbcx_hptxsts_s cn56xx; ++ struct cvmx_usbcx_hptxsts_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_nptxdfifox { ++ uint32_t u32; ++ struct cvmx_usbcx_nptxdfifox_s { ++ uint32_t data:32; ++ } s; ++ struct cvmx_usbcx_nptxdfifox_s cn30xx; ++ struct cvmx_usbcx_nptxdfifox_s cn31xx; ++ struct cvmx_usbcx_nptxdfifox_s cn50xx; ++ struct cvmx_usbcx_nptxdfifox_s cn52xx; ++ struct cvmx_usbcx_nptxdfifox_s cn52xxp1; ++ struct cvmx_usbcx_nptxdfifox_s cn56xx; ++ struct cvmx_usbcx_nptxdfifox_s cn56xxp1; ++}; ++ ++union cvmx_usbcx_pcgcctl { ++ uint32_t u32; ++ struct cvmx_usbcx_pcgcctl_s { ++ uint32_t reserved_5_31:27; ++ uint32_t physuspended:1; ++ uint32_t rstpdwnmodule:1; ++ uint32_t pwrclmp:1; ++ uint32_t gatehclk:1; ++ uint32_t stoppclk:1; ++ } s; ++ struct cvmx_usbcx_pcgcctl_s cn30xx; ++ struct cvmx_usbcx_pcgcctl_s cn31xx; ++ struct cvmx_usbcx_pcgcctl_s cn50xx; ++ struct cvmx_usbcx_pcgcctl_s cn52xx; ++ struct cvmx_usbcx_pcgcctl_s cn52xxp1; ++ struct cvmx_usbcx_pcgcctl_s cn56xx; ++ struct cvmx_usbcx_pcgcctl_s cn56xxp1; ++}; ++ ++#endif +diff --git a/arch/mips/include/asm/octeon/cvmx-usbnx-defs.h b/arch/mips/include/asm/octeon/cvmx-usbnx-defs.h +new file mode 100644 +index 0000000..90be974 +--- /dev/null ++++ b/arch/mips/include/asm/octeon/cvmx-usbnx-defs.h +@@ -0,0 +1,760 @@ ++/***********************license start*************** ++ * Author: Cavium Networks ++ * ++ * Contact: support@caviumnetworks.com ++ * This file is part of the OCTEON SDK ++ * ++ * Copyright (c) 2003-2008 Cavium Networks ++ * ++ * This file is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, Version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful, but ++ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or ++ * NONINFRINGEMENT. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this file; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * or visit http://www.gnu.org/licenses/. ++ * ++ * This file may also be available under a different license from Cavium. ++ * Contact Cavium Networks for more information ++ ***********************license end**************************************/ ++ ++#ifndef __CVMX_USBNX_DEFS_H__ ++#define __CVMX_USBNX_DEFS_H__ ++ ++#define CVMX_USBNX_BIST_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00011800680007F8ull + (((block_id) & 1) * 0x10000000ull)) ++#define CVMX_USBNX_CLK_CTL(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180068000010ull + (((block_id) & 1) * 0x10000000ull)) ++#define CVMX_USBNX_CTL_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000800ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN0(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000818ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN1(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000820ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN2(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000828ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN3(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000830ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN4(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000838ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN5(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000840ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN6(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000848ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_INB_CHN7(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000850ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN0(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000858ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN1(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000860ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN2(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000868ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN3(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000870ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN4(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000878ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN5(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000880ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN6(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000888ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA0_OUTB_CHN7(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000890ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_DMA_TEST(block_id) \ ++ CVMX_ADD_IO_SEG(0x00016F0000000808ull + (((block_id) & 1) * 0x100000000000ull)) ++#define CVMX_USBNX_INT_ENB(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180068000008ull + (((block_id) & 1) * 0x10000000ull)) ++#define CVMX_USBNX_INT_SUM(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180068000000ull + (((block_id) & 1) * 0x10000000ull)) ++#define CVMX_USBNX_USBP_CTL_STATUS(block_id) \ ++ CVMX_ADD_IO_SEG(0x0001180068000018ull + (((block_id) & 1) * 0x10000000ull)) ++ ++union cvmx_usbnx_bist_status { ++ uint64_t u64; ++ struct cvmx_usbnx_bist_status_s { ++ uint64_t reserved_7_63:57; ++ uint64_t u2nc_bis:1; ++ uint64_t u2nf_bis:1; ++ uint64_t e2hc_bis:1; ++ uint64_t n2uf_bis:1; ++ uint64_t usbc_bis:1; ++ uint64_t nif_bis:1; ++ uint64_t nof_bis:1; ++ } s; ++ struct cvmx_usbnx_bist_status_cn30xx { ++ uint64_t reserved_3_63:61; ++ uint64_t usbc_bis:1; ++ uint64_t nif_bis:1; ++ uint64_t nof_bis:1; ++ } cn30xx; ++ struct cvmx_usbnx_bist_status_cn30xx cn31xx; ++ struct cvmx_usbnx_bist_status_s cn50xx; ++ struct cvmx_usbnx_bist_status_s cn52xx; ++ struct cvmx_usbnx_bist_status_s cn52xxp1; ++ struct cvmx_usbnx_bist_status_s cn56xx; ++ struct cvmx_usbnx_bist_status_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_clk_ctl { ++ uint64_t u64; ++ struct cvmx_usbnx_clk_ctl_s { ++ uint64_t reserved_20_63:44; ++ uint64_t divide2:2; ++ uint64_t hclk_rst:1; ++ uint64_t p_x_on:1; ++ uint64_t reserved_14_15:2; ++ uint64_t p_com_on:1; ++ uint64_t p_c_sel:2; ++ uint64_t cdiv_byp:1; ++ uint64_t sd_mode:2; ++ uint64_t s_bist:1; ++ uint64_t por:1; ++ uint64_t enable:1; ++ uint64_t prst:1; ++ uint64_t hrst:1; ++ uint64_t divide:3; ++ } s; ++ struct cvmx_usbnx_clk_ctl_cn30xx { ++ uint64_t reserved_18_63:46; ++ uint64_t hclk_rst:1; ++ uint64_t p_x_on:1; ++ uint64_t p_rclk:1; ++ uint64_t p_xenbn:1; ++ uint64_t p_com_on:1; ++ uint64_t p_c_sel:2; ++ uint64_t cdiv_byp:1; ++ uint64_t sd_mode:2; ++ uint64_t s_bist:1; ++ uint64_t por:1; ++ uint64_t enable:1; ++ uint64_t prst:1; ++ uint64_t hrst:1; ++ uint64_t divide:3; ++ } cn30xx; ++ struct cvmx_usbnx_clk_ctl_cn30xx cn31xx; ++ struct cvmx_usbnx_clk_ctl_cn50xx { ++ uint64_t reserved_20_63:44; ++ uint64_t divide2:2; ++ uint64_t hclk_rst:1; ++ uint64_t reserved_16_16:1; ++ uint64_t p_rtype:2; ++ uint64_t p_com_on:1; ++ uint64_t p_c_sel:2; ++ uint64_t cdiv_byp:1; ++ uint64_t sd_mode:2; ++ uint64_t s_bist:1; ++ uint64_t por:1; ++ uint64_t enable:1; ++ uint64_t prst:1; ++ uint64_t hrst:1; ++ uint64_t divide:3; ++ } cn50xx; ++ struct cvmx_usbnx_clk_ctl_cn50xx cn52xx; ++ struct cvmx_usbnx_clk_ctl_cn50xx cn52xxp1; ++ struct cvmx_usbnx_clk_ctl_cn50xx cn56xx; ++ struct cvmx_usbnx_clk_ctl_cn50xx cn56xxp1; ++}; ++ ++union cvmx_usbnx_ctl_status { ++ uint64_t u64; ++ struct cvmx_usbnx_ctl_status_s { ++ uint64_t reserved_6_63:58; ++ uint64_t dma_0pag:1; ++ uint64_t dma_stt:1; ++ uint64_t dma_test:1; ++ uint64_t inv_a2:1; ++ uint64_t l2c_emod:2; ++ } s; ++ struct cvmx_usbnx_ctl_status_s cn30xx; ++ struct cvmx_usbnx_ctl_status_s cn31xx; ++ struct cvmx_usbnx_ctl_status_s cn50xx; ++ struct cvmx_usbnx_ctl_status_s cn52xx; ++ struct cvmx_usbnx_ctl_status_s cn52xxp1; ++ struct cvmx_usbnx_ctl_status_s cn56xx; ++ struct cvmx_usbnx_ctl_status_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn0 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn0_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn0_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn1 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn1_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn1_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn2 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn2_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn2_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn3 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn3_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn3_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn4 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn4_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn4_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn5 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn5_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn5_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn6 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn6_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn6_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_inb_chn7 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_inb_chn7_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn30xx; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn31xx; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn50xx; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn52xx; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn52xxp1; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn56xx; ++ struct cvmx_usbnx_dma0_inb_chn7_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn0 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn0_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn0_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn1 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn1_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn1_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn2 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn2_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn2_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn3 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn3_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn3_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn4 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn4_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn4_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn5 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn5_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn5_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn6 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn6_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn6_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma0_outb_chn7 { ++ uint64_t u64; ++ struct cvmx_usbnx_dma0_outb_chn7_s { ++ uint64_t reserved_36_63:28; ++ uint64_t addr:36; ++ } s; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn30xx; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn31xx; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn50xx; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn52xx; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn52xxp1; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn56xx; ++ struct cvmx_usbnx_dma0_outb_chn7_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_dma_test { ++ uint64_t u64; ++ struct cvmx_usbnx_dma_test_s { ++ uint64_t reserved_40_63:24; ++ uint64_t done:1; ++ uint64_t req:1; ++ uint64_t f_addr:18; ++ uint64_t count:11; ++ uint64_t channel:5; ++ uint64_t burst:4; ++ } s; ++ struct cvmx_usbnx_dma_test_s cn30xx; ++ struct cvmx_usbnx_dma_test_s cn31xx; ++ struct cvmx_usbnx_dma_test_s cn50xx; ++ struct cvmx_usbnx_dma_test_s cn52xx; ++ struct cvmx_usbnx_dma_test_s cn52xxp1; ++ struct cvmx_usbnx_dma_test_s cn56xx; ++ struct cvmx_usbnx_dma_test_s cn56xxp1; ++}; ++ ++union cvmx_usbnx_int_enb { ++ uint64_t u64; ++ struct cvmx_usbnx_int_enb_s { ++ uint64_t reserved_38_63:26; ++ uint64_t nd4o_dpf:1; ++ uint64_t nd4o_dpe:1; ++ uint64_t nd4o_rpf:1; ++ uint64_t nd4o_rpe:1; ++ uint64_t ltl_f_pf:1; ++ uint64_t ltl_f_pe:1; ++ uint64_t u2n_c_pe:1; ++ uint64_t u2n_c_pf:1; ++ uint64_t u2n_d_pf:1; ++ uint64_t u2n_d_pe:1; ++ uint64_t n2u_pe:1; ++ uint64_t n2u_pf:1; ++ uint64_t uod_pf:1; ++ uint64_t uod_pe:1; ++ uint64_t rq_q3_e:1; ++ uint64_t rq_q3_f:1; ++ uint64_t rq_q2_e:1; ++ uint64_t rq_q2_f:1; ++ uint64_t rg_fi_f:1; ++ uint64_t rg_fi_e:1; ++ uint64_t l2_fi_f:1; ++ uint64_t l2_fi_e:1; ++ uint64_t l2c_a_f:1; ++ uint64_t l2c_s_e:1; ++ uint64_t dcred_f:1; ++ uint64_t dcred_e:1; ++ uint64_t lt_pu_f:1; ++ uint64_t lt_po_e:1; ++ uint64_t nt_pu_f:1; ++ uint64_t nt_po_e:1; ++ uint64_t pt_pu_f:1; ++ uint64_t pt_po_e:1; ++ uint64_t lr_pu_f:1; ++ uint64_t lr_po_e:1; ++ uint64_t nr_pu_f:1; ++ uint64_t nr_po_e:1; ++ uint64_t pr_pu_f:1; ++ uint64_t pr_po_e:1; ++ } s; ++ struct cvmx_usbnx_int_enb_s cn30xx; ++ struct cvmx_usbnx_int_enb_s cn31xx; ++ struct cvmx_usbnx_int_enb_cn50xx { ++ uint64_t reserved_38_63:26; ++ uint64_t nd4o_dpf:1; ++ uint64_t nd4o_dpe:1; ++ uint64_t nd4o_rpf:1; ++ uint64_t nd4o_rpe:1; ++ uint64_t ltl_f_pf:1; ++ uint64_t ltl_f_pe:1; ++ uint64_t reserved_26_31:6; ++ uint64_t uod_pf:1; ++ uint64_t uod_pe:1; ++ uint64_t rq_q3_e:1; ++ uint64_t rq_q3_f:1; ++ uint64_t rq_q2_e:1; ++ uint64_t rq_q2_f:1; ++ uint64_t rg_fi_f:1; ++ uint64_t rg_fi_e:1; ++ uint64_t l2_fi_f:1; ++ uint64_t l2_fi_e:1; ++ uint64_t l2c_a_f:1; ++ uint64_t l2c_s_e:1; ++ uint64_t dcred_f:1; ++ uint64_t dcred_e:1; ++ uint64_t lt_pu_f:1; ++ uint64_t lt_po_e:1; ++ uint64_t nt_pu_f:1; ++ uint64_t nt_po_e:1; ++ uint64_t pt_pu_f:1; ++ uint64_t pt_po_e:1; ++ uint64_t lr_pu_f:1; ++ uint64_t lr_po_e:1; ++ uint64_t nr_pu_f:1; ++ uint64_t nr_po_e:1; ++ uint64_t pr_pu_f:1; ++ uint64_t pr_po_e:1; ++ } cn50xx; ++ struct cvmx_usbnx_int_enb_cn50xx cn52xx; ++ struct cvmx_usbnx_int_enb_cn50xx cn52xxp1; ++ struct cvmx_usbnx_int_enb_cn50xx cn56xx; ++ struct cvmx_usbnx_int_enb_cn50xx cn56xxp1; ++}; ++ ++union cvmx_usbnx_int_sum { ++ uint64_t u64; ++ struct cvmx_usbnx_int_sum_s { ++ uint64_t reserved_38_63:26; ++ uint64_t nd4o_dpf:1; ++ uint64_t nd4o_dpe:1; ++ uint64_t nd4o_rpf:1; ++ uint64_t nd4o_rpe:1; ++ uint64_t ltl_f_pf:1; ++ uint64_t ltl_f_pe:1; ++ uint64_t u2n_c_pe:1; ++ uint64_t u2n_c_pf:1; ++ uint64_t u2n_d_pf:1; ++ uint64_t u2n_d_pe:1; ++ uint64_t n2u_pe:1; ++ uint64_t n2u_pf:1; ++ uint64_t uod_pf:1; ++ uint64_t uod_pe:1; ++ uint64_t rq_q3_e:1; ++ uint64_t rq_q3_f:1; ++ uint64_t rq_q2_e:1; ++ uint64_t rq_q2_f:1; ++ uint64_t rg_fi_f:1; ++ uint64_t rg_fi_e:1; ++ uint64_t lt_fi_f:1; ++ uint64_t lt_fi_e:1; ++ uint64_t l2c_a_f:1; ++ uint64_t l2c_s_e:1; ++ uint64_t dcred_f:1; ++ uint64_t dcred_e:1; ++ uint64_t lt_pu_f:1; ++ uint64_t lt_po_e:1; ++ uint64_t nt_pu_f:1; ++ uint64_t nt_po_e:1; ++ uint64_t pt_pu_f:1; ++ uint64_t pt_po_e:1; ++ uint64_t lr_pu_f:1; ++ uint64_t lr_po_e:1; ++ uint64_t nr_pu_f:1; ++ uint64_t nr_po_e:1; ++ uint64_t pr_pu_f:1; ++ uint64_t pr_po_e:1; ++ } s; ++ struct cvmx_usbnx_int_sum_s cn30xx; ++ struct cvmx_usbnx_int_sum_s cn31xx; ++ struct cvmx_usbnx_int_sum_cn50xx { ++ uint64_t reserved_38_63:26; ++ uint64_t nd4o_dpf:1; ++ uint64_t nd4o_dpe:1; ++ uint64_t nd4o_rpf:1; ++ uint64_t nd4o_rpe:1; ++ uint64_t ltl_f_pf:1; ++ uint64_t ltl_f_pe:1; ++ uint64_t reserved_26_31:6; ++ uint64_t uod_pf:1; ++ uint64_t uod_pe:1; ++ uint64_t rq_q3_e:1; ++ uint64_t rq_q3_f:1; ++ uint64_t rq_q2_e:1; ++ uint64_t rq_q2_f:1; ++ uint64_t rg_fi_f:1; ++ uint64_t rg_fi_e:1; ++ uint64_t lt_fi_f:1; ++ uint64_t lt_fi_e:1; ++ uint64_t l2c_a_f:1; ++ uint64_t l2c_s_e:1; ++ uint64_t dcred_f:1; ++ uint64_t dcred_e:1; ++ uint64_t lt_pu_f:1; ++ uint64_t lt_po_e:1; ++ uint64_t nt_pu_f:1; ++ uint64_t nt_po_e:1; ++ uint64_t pt_pu_f:1; ++ uint64_t pt_po_e:1; ++ uint64_t lr_pu_f:1; ++ uint64_t lr_po_e:1; ++ uint64_t nr_pu_f:1; ++ uint64_t nr_po_e:1; ++ uint64_t pr_pu_f:1; ++ uint64_t pr_po_e:1; ++ } cn50xx; ++ struct cvmx_usbnx_int_sum_cn50xx cn52xx; ++ struct cvmx_usbnx_int_sum_cn50xx cn52xxp1; ++ struct cvmx_usbnx_int_sum_cn50xx cn56xx; ++ struct cvmx_usbnx_int_sum_cn50xx cn56xxp1; ++}; ++ ++union cvmx_usbnx_usbp_ctl_status { ++ uint64_t u64; ++ struct cvmx_usbnx_usbp_ctl_status_s { ++ uint64_t txrisetune:1; ++ uint64_t txvreftune:4; ++ uint64_t txfslstune:4; ++ uint64_t txhsxvtune:2; ++ uint64_t sqrxtune:3; ++ uint64_t compdistune:3; ++ uint64_t otgtune:3; ++ uint64_t otgdisable:1; ++ uint64_t portreset:1; ++ uint64_t drvvbus:1; ++ uint64_t lsbist:1; ++ uint64_t fsbist:1; ++ uint64_t hsbist:1; ++ uint64_t bist_done:1; ++ uint64_t bist_err:1; ++ uint64_t tdata_out:4; ++ uint64_t siddq:1; ++ uint64_t txpreemphasistune:1; ++ uint64_t dma_bmode:1; ++ uint64_t usbc_end:1; ++ uint64_t usbp_bist:1; ++ uint64_t tclk:1; ++ uint64_t dp_pulld:1; ++ uint64_t dm_pulld:1; ++ uint64_t hst_mode:1; ++ uint64_t tuning:4; ++ uint64_t tx_bs_enh:1; ++ uint64_t tx_bs_en:1; ++ uint64_t loop_enb:1; ++ uint64_t vtest_enb:1; ++ uint64_t bist_enb:1; ++ uint64_t tdata_sel:1; ++ uint64_t taddr_in:4; ++ uint64_t tdata_in:8; ++ uint64_t ate_reset:1; ++ } s; ++ struct cvmx_usbnx_usbp_ctl_status_cn30xx { ++ uint64_t reserved_38_63:26; ++ uint64_t bist_done:1; ++ uint64_t bist_err:1; ++ uint64_t tdata_out:4; ++ uint64_t reserved_30_31:2; ++ uint64_t dma_bmode:1; ++ uint64_t usbc_end:1; ++ uint64_t usbp_bist:1; ++ uint64_t tclk:1; ++ uint64_t dp_pulld:1; ++ uint64_t dm_pulld:1; ++ uint64_t hst_mode:1; ++ uint64_t tuning:4; ++ uint64_t tx_bs_enh:1; ++ uint64_t tx_bs_en:1; ++ uint64_t loop_enb:1; ++ uint64_t vtest_enb:1; ++ uint64_t bist_enb:1; ++ uint64_t tdata_sel:1; ++ uint64_t taddr_in:4; ++ uint64_t tdata_in:8; ++ uint64_t ate_reset:1; ++ } cn30xx; ++ struct cvmx_usbnx_usbp_ctl_status_cn30xx cn31xx; ++ struct cvmx_usbnx_usbp_ctl_status_cn50xx { ++ uint64_t txrisetune:1; ++ uint64_t txvreftune:4; ++ uint64_t txfslstune:4; ++ uint64_t txhsxvtune:2; ++ uint64_t sqrxtune:3; ++ uint64_t compdistune:3; ++ uint64_t otgtune:3; ++ uint64_t otgdisable:1; ++ uint64_t portreset:1; ++ uint64_t drvvbus:1; ++ uint64_t lsbist:1; ++ uint64_t fsbist:1; ++ uint64_t hsbist:1; ++ uint64_t bist_done:1; ++ uint64_t bist_err:1; ++ uint64_t tdata_out:4; ++ uint64_t reserved_31_31:1; ++ uint64_t txpreemphasistune:1; ++ uint64_t dma_bmode:1; ++ uint64_t usbc_end:1; ++ uint64_t usbp_bist:1; ++ uint64_t tclk:1; ++ uint64_t dp_pulld:1; ++ uint64_t dm_pulld:1; ++ uint64_t hst_mode:1; ++ uint64_t reserved_19_22:4; ++ uint64_t tx_bs_enh:1; ++ uint64_t tx_bs_en:1; ++ uint64_t loop_enb:1; ++ uint64_t vtest_enb:1; ++ uint64_t bist_enb:1; ++ uint64_t tdata_sel:1; ++ uint64_t taddr_in:4; ++ uint64_t tdata_in:8; ++ uint64_t ate_reset:1; ++ } cn50xx; ++ struct cvmx_usbnx_usbp_ctl_status_cn50xx cn52xx; ++ struct cvmx_usbnx_usbp_ctl_status_cn50xx cn52xxp1; ++ struct cvmx_usbnx_usbp_ctl_status_cn56xx { ++ uint64_t txrisetune:1; ++ uint64_t txvreftune:4; ++ uint64_t txfslstune:4; ++ uint64_t txhsxvtune:2; ++ uint64_t sqrxtune:3; ++ uint64_t compdistune:3; ++ uint64_t otgtune:3; ++ uint64_t otgdisable:1; ++ uint64_t portreset:1; ++ uint64_t drvvbus:1; ++ uint64_t lsbist:1; ++ uint64_t fsbist:1; ++ uint64_t hsbist:1; ++ uint64_t bist_done:1; ++ uint64_t bist_err:1; ++ uint64_t tdata_out:4; ++ uint64_t siddq:1; ++ uint64_t txpreemphasistune:1; ++ uint64_t dma_bmode:1; ++ uint64_t usbc_end:1; ++ uint64_t usbp_bist:1; ++ uint64_t tclk:1; ++ uint64_t dp_pulld:1; ++ uint64_t dm_pulld:1; ++ uint64_t hst_mode:1; ++ uint64_t reserved_19_22:4; ++ uint64_t tx_bs_enh:1; ++ uint64_t tx_bs_en:1; ++ uint64_t loop_enb:1; ++ uint64_t vtest_enb:1; ++ uint64_t bist_enb:1; ++ uint64_t tdata_sel:1; ++ uint64_t taddr_in:4; ++ uint64_t tdata_in:8; ++ uint64_t ate_reset:1; ++ } cn56xx; ++ struct cvmx_usbnx_usbp_ctl_status_cn50xx cn56xxp1; ++}; ++ ++#endif +-- +1.6.0.6 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-usb" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.htmlSigned-off-by: David Daney +--- + drivers/usb/host/Kconfig | 8 + + drivers/usb/host/Makefile | 1 + + drivers/usb/host/dwc_otg/Kbuild | 16 + + drivers/usb/host/dwc_otg/dwc_otg_attr.c | 854 ++++++++ + drivers/usb/host/dwc_otg/dwc_otg_attr.h | 63 + + drivers/usb/host/dwc_otg/dwc_otg_cil.c | 2887 ++++++++++++++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_cil.h | 866 ++++++++ + drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 689 ++++++ + drivers/usb/host/dwc_otg/dwc_otg_driver.h | 63 + + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 2878 +++++++++++++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 661 ++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 1890 +++++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 695 +++++++ + drivers/usb/host/dwc_otg/dwc_otg_octeon.c | 1078 ++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_plat.h | 236 +++ + drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2355 +++++++++++++++++++++ + 16 files changed, 15240 insertions(+), 0 deletions(-) + create mode 100644 drivers/usb/host/dwc_otg/Kbuild + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_octeon.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_plat.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h + +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 9b43b22..342dc54 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -381,3 +381,11 @@ config USB_HWA_HCD + + To compile this driver a module, choose M here: the module + will be called "hwa-hc". ++ ++config USB_DWC_OTG ++ tristate "Cavium Octeon USB" ++ depends on USB && CPU_CAVIUM_OCTEON ++ ---help--- ++ The Cavium Octeon on-chip USB controller. To compile this ++ driver as a module, choose M here: the module will be called ++ "dwc_otg". +diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile +index f58b249..76faf12 100644 +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -15,6 +15,7 @@ endif + xhci-objs := xhci-hcd.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o + + obj-$(CONFIG_USB_WHCI_HCD) += whci/ ++obj-$(CONFIG_USB_DWC_OTG) += dwc_otg/ + + obj-$(CONFIG_PCI) += pci-quirks.o + +diff --git a/drivers/usb/host/dwc_otg/Kbuild b/drivers/usb/host/dwc_otg/Kbuild +new file mode 100644 +index 0000000..cb32638 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/Kbuild +@@ -0,0 +1,16 @@ ++# ++# Makefile for DWC_otg Highspeed USB controller driver ++# ++ ++# Use one of the following flags to compile the software in host-only or ++# device-only mode. ++#EXTRA_CFLAGS += -DDWC_HOST_ONLY ++#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY ++ ++EXTRA_CFLAGS += -DDWC_HOST_ONLY ++obj-$(CONFIG_USB_DWC_OTG) += dwc_otg.o ++ ++dwc_otg-y := dwc_otg_octeon.o dwc_otg_attr.o ++dwc_otg-y += dwc_otg_cil.o dwc_otg_cil_intr.o ++dwc_otg-y += dwc_otg_hcd.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o ++ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +new file mode 100644 +index 0000000..d854a79 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +@@ -0,0 +1,854 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/* ++ * ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. The Linux driver attributes ++ * feature will be used to provide the Linux Diagnostic ++ * Interface. These attributes are accessed through sysfs. ++ */ ++ ++/** @page "Linux Module Attributes" ++ * ++ * The Linux module attributes feature is used to provide the Linux ++ * Diagnostic Interface. These attributes are accessed through sysfs. ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. ++ ++ The following table shows the attributes. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
Name Description Access
mode Returns the current mode: 0 for device mode, 1 for host mode Read
hnpcapable Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
srpcapable Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
hnp Initiates the Host Negotiation Protocol. Read returns the status. Read/Write
srp Initiates the Session Request Protocol. Read returns the status. Read/Write
buspower Gets or sets the Power State of the bus (0 - Off or 1 - On) Read/Write
bussuspend Suspends the USB bus. Read/Write
busconnected Gets the connection status of the bus Read
gotgctl Gets or sets the Core Control Status Register. Read/Write
gusbcfg Gets or sets the Core USB Configuration Register Read/Write
grxfsiz Gets or sets the Receive FIFO Size Register Read/Write
gnptxfsiz Gets or sets the non-periodic Transmit Size Register Read/Write
gpvndctl Gets or sets the PHY Vendor Control Register Read/Write
ggpio Gets the value in the lower 16-bits of the General Purpose IO Register ++ or sets the upper 16 bits. Read/Write
guid Gets or sets the value of the User ID Register Read/Write
gsnpsid Gets the value of the Synopsys ID Regester Read
devspeed Gets or sets the device speed setting in the DCFG register Read/Write
enumspeed Gets the device enumeration Speed. Read
hptxfsiz Gets the value of the Host Periodic Transmit FIFO Read
hprt0 Gets or sets the value in the Host Port Control and Status Register Read/Write
regoffset Sets the register offset for the next Register Access Read/Write
regvalue Gets or sets the value of the register at the offset in the regoffset attribute. Read/Write
remote_wakeup On read, shows the status of Remote Wakeup. On write, initiates a remote ++ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote ++ Wakeup signalling bit in the Device Control Register is set for 1 ++ milli-second. Read/Write
regdump Dumps the contents of core registers. Read
hcddump Dumps the current HCD state. Read
hcd_frrem Shows the average value of the Frame Remaining ++ field in the Host Frame Number/Frame Remaining register when an SOF interrupt ++ occurs. This can be used to determine the average interrupt latency. Also ++ shows the average Frame Remaining value for start_transfer and the "a" and ++ "b" sample points. The "a" and "b" sample points may be used during debugging ++ bto determine how long it takes to execute a section of the HCD code. Read
rd_reg_test Displays the time required to read the GNPTXFSIZ register many times ++ (the output shows the number of times the register is read). ++ Read
wr_reg_test Displays the time required to write the GNPTXFSIZ register many times ++ (the output shows the number of times the register is written). ++ Read
++ ++ Example usage: ++ To get the current mode: ++ cat /sys/devices/lm0/mode ++ ++ To power down the USB: ++ echo 0 > /sys/devices/lm0/buspower ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* permission constants */ ++ ++#include ++ ++#include "dwc_otg_plat.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_driver.h" ++#ifndef DWC_HOST_ONLY ++#include "dwc_otg_pcd.h" ++#endif ++#include "dwc_otg_hcd.h" ++ ++/* ++ * MACROs for defining sysfs attribute ++ */ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, _addr_, \ ++ _mask_, _shift_, _string_) \ ++ static ssize_t _otg_attr_name_##_show (struct device *_dev, \ ++ struct device_attribute *attr, \ ++ char *buf) \ ++ { \ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; \ ++ uint32_t val; \ ++ val = dwc_read_reg32(_addr_); \ ++ val = (val & (_mask_)) >> _shift_; \ ++ return sprintf(buf, "%s = 0x%x\n", _string_, val); \ ++ } ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_, _addr_, \ ++ _mask_, _shift_, _string_) \ ++ static ssize_t _otg_attr_name_##_store (struct device *_dev, \ ++ struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++ { \ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ uint32_t clear = set; \ ++ clear = ((~clear) << _shift_) & _mask_; \ ++ set = (set << _shift_) & _mask_; \ ++ dev_dbg(_dev, \ ++ "Storing Address=%p Set=0x%08x Clear=0x%08x\n", \ ++ _addr_, set, clear); \ ++ dwc_modify_reg32(_addr_, clear, set); \ ++ return count; \ ++ } ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_, _addr_, \ ++ _mask_, _shift_, _string_) \ ++ DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, _addr_, \ ++ _mask_, _shift_, _string_) \ ++ DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_, _addr_, \ ++ _mask_, _shift_, _string_) \ ++ DEVICE_ATTR(_otg_attr_name_, 0644, _otg_attr_name_##_show, \ ++ _otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_, _addr_, \ ++ _mask_, _shift_, _string_) \ ++ DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, \ ++ _addr_, _mask_, _shift_, _string_) \ ++ DEVICE_ATTR(_otg_attr_name_, 0444, _otg_attr_name_##_show, NULL); ++ ++/* ++ * MACROs for defining sysfs attribute for 32-bit registers ++ */ ++#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \ ++ static ssize_t _otg_attr_name_##_show(struct device *_dev, \ ++ struct device_attribute *attr, \ ++ char *buf) \ ++ { \ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; \ ++ uint32_t val; \ ++ val = dwc_read_reg32(_addr_); \ ++ return sprintf(buf, "%s = 0x%08x\n", _string_, val); \ ++ } ++ ++#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_, _addr_, _string_) \ ++ static ssize_t _otg_attr_name_##_store(struct device *_dev, \ ++ struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++ { \ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ dev_dbg(_dev, "Storing Address=%p Val=0x%08x\n", _addr_, val); \ ++ dwc_write_reg32(_addr_, val); \ ++ return count; \ ++ } ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_, _addr_, _string_) \ ++ DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \ ++ DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_, _addr_, _string_) \ ++ DEVICE_ATTR(_otg_attr_name_, 0644, _otg_attr_name_##_show, \ ++ _otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_, _addr_, _string_) \ ++ DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \ ++ DEVICE_ATTR(_otg_attr_name_, 0444, _otg_attr_name_##_show, NULL); ++ ++/** ++ * Show the register offset of the Register Access. ++ */ ++static ssize_t regoffset_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", ++ otg_dev->reg_offset); ++} ++ ++/** ++ * Set the register offset for the next Register Access Read/Write ++ */ ++static ssize_t regoffset_store(struct device *_dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t offset = simple_strtoul(buf, NULL, 16); ++ ++ if (offset < SZ_256K) ++ otg_dev->reg_offset = offset; ++ else ++ dev_err(_dev, "invalid offset\n"); ++ ++ return count; ++} ++ ++DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); ++ ++/** ++ * Show the value of the register at the offset in the reg_offset ++ * attribute. ++ */ ++static ssize_t regvalue_show(struct device *_dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t val; ++ uint32_t *addr; ++ ++ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->reg_offset + ++ (uint8_t *) otg_dev->base); ++ ++ val = dwc_read_reg32(addr); ++ return snprintf(buf, ++ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, ++ "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset, ++ val); ++ } else { ++ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset); ++ return sprintf(buf, "invalid offset\n"); ++ } ++} ++ ++/** ++ * Store the value in the register at the offset in the reg_offset ++ * attribute. ++ * ++ */ ++static ssize_t regvalue_store(struct device *_dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t *addr; ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->reg_offset + ++ (uint8_t *) otg_dev->base); ++ ++ dwc_write_reg32(addr, val); ++ } else { ++ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", ++ otg_dev->reg_offset); ++ } ++ return count; ++} ++ ++DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); ++ ++/* ++ * Attributes ++ */ ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, ++ &(otg_dev->core_if->core_global_regs->gotgctl), ++ (1 << 20), 20, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ (1 << 9), 9, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ (1 << 8), 8, "Mode"); ++#if 0 ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower, &(otg_dev->core_if->core_global_regs->gotgctl), (1<<8), 8, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend, &(otg_dev->core_if->core_global_regs->gotgctl), (1<<8), 8, "Mode"); ++#endif ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, otg_dev->core_if->host_if->hprt0, ++ 0x01, 0, "Bus Connected"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, ++ &(otg_dev->core_if->core_global_regs->gotgctl), ++ "GOTGCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ "GUSBCFG"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, ++ &(otg_dev->core_if->core_global_regs->grxfsiz), ++ "GRXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, ++ &(otg_dev->core_if->core_global_regs->gnptxfsiz), ++ "GNPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, ++ &(otg_dev->core_if->core_global_regs->gpvndctl), ++ "GPVNDCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio, ++ &(otg_dev->core_if->core_global_regs->ggpio), ++ "GGPIO"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), ++ "GUID"); ++DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, ++ &(otg_dev->core_if->core_global_regs->gsnpsid), ++ "GSNPSID"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, ++ &(otg_dev->core_if->dev_if->dev_global_regs-> ++ dcfg), 0x3, 0, "Device Speed"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, ++ &(otg_dev->core_if->dev_if->dev_global_regs-> ++ dsts), 0x6, 1, "Device Enumeration Speed"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, ++ &(otg_dev->core_if->core_global_regs->hptxfsiz), ++ "HPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); ++ ++/** ++ * @todo Add code to initiate the HNP. ++ */ ++/** ++ * Show the HNP status bit ++ */ ++static ssize_t hnp_show(struct device *_dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ union gotgctl_data val; ++ val.d32 = ++ dwc_read_reg32(&(otg_dev->core_if->core_global_regs->gotgctl)); ++ return sprintf(buf, "HstNegScs = 0x%x\n", val.b.hstnegscs); ++} ++ ++/** ++ * Set the HNP Request bit ++ */ ++static ssize_t hnp_store(struct device *_dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ uint32_t *addr = ++ (uint32_t *) &(otg_dev->core_if->core_global_regs->gotgctl); ++ union gotgctl_data mem; ++ mem.d32 = dwc_read_reg32(addr); ++ mem.b.hnpreq = in; ++ dev_dbg(_dev, "Storing Address=%p Data=0x%08x\n", addr, mem.d32); ++ dwc_write_reg32(addr, mem.d32); ++ return count; ++} ++ ++DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); ++ ++/** ++ * @todo Add code to initiate the SRP. ++ */ ++/** ++ * Show the SRP status bit ++ */ ++static ssize_t srp_show(struct device *_dev, struct device_attribute *attr, ++ char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ union gotgctl_data val; ++ val.d32 = ++ dwc_read_reg32(&(otg_dev->core_if->core_global_regs->gotgctl)); ++ return sprintf(buf, "SesReqScs = 0x%x\n", val.b.sesreqscs); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif ++} ++ ++/** ++ * Set the SRP Request bit ++ */ ++static ssize_t srp_store(struct device *_dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ dwc_otg_pcd_initiate_srp(otg_dev->pcd); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(srp, 0644, srp_show, srp_store); ++ ++/** ++ * @todo Need to do more for power on/off? ++ */ ++/** ++ * Show the Bus Power status ++ */ ++static ssize_t buspower_show(struct device *_dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ union hprt0_data val; ++ val.d32 = dwc_read_reg32(otg_dev->core_if->host_if->hprt0); ++ return sprintf(buf, "Bus Power = 0x%x\n", val.b.prtpwr); ++} ++ ++/** ++ * Set the Bus Power status ++ */ ++static ssize_t buspower_store(struct device *_dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t on = simple_strtoul(buf, NULL, 16); ++ uint32_t *addr = (uint32_t *) otg_dev->core_if->host_if->hprt0; ++ union hprt0_data mem; ++ ++ mem.d32 = dwc_read_reg32(addr); ++ mem.b.prtpwr = on; ++ ++ dwc_write_reg32(addr, mem.d32); ++ ++ return count; ++} ++ ++DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); ++ ++/** ++ * @todo Need to do more for suspend? ++ */ ++/** ++ * Show the Bus Suspend status ++ */ ++static ssize_t bussuspend_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ union hprt0_data val; ++ val.d32 = dwc_read_reg32(otg_dev->core_if->host_if->hprt0); ++ return sprintf(buf, "Bus Suspend = 0x%x\n", val.b.prtsusp); ++} ++ ++/** ++ * Set the Bus Suspend status ++ */ ++static ssize_t bussuspend_store(struct device *_dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ uint32_t *addr = (uint32_t *) otg_dev->core_if->host_if->hprt0; ++ union hprt0_data mem; ++ mem.d32 = dwc_read_reg32(addr); ++ mem.b.prtsusp = in; ++ dev_dbg(_dev, "Storing Address=%p Data=0x%08x\n", addr, mem.d32); ++ dwc_write_reg32(addr, mem.d32); ++ return count; ++} ++ ++DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); ++ ++/** ++ * Show the status of Remote Wakeup. ++ */ ++static ssize_t remote_wakeup_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ union dctl_data val; ++ val.d32 = ++ dwc_read_reg32(&otg_dev->core_if->dev_if->dev_global_regs->dctl); ++ return sprintf(buf, "Remote Wakeup = %d Enabled = %d\n", ++ val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif ++} ++ ++/** ++ * Initiate a remote wakeup of the host. The Device control register ++ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable ++ * flag is set. ++ * ++ */ ++static ssize_t remote_wakeup_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ if (val & 1) ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1); ++ else ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, ++ remote_wakeup_store); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t regdump_show(struct device *_dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ ++ dwc_otg_dump_global_registers(otg_dev->core_if); ++ if (dwc_otg_is_host_mode(otg_dev->core_if)) ++ dwc_otg_dump_host_registers(otg_dev->core_if); ++ else ++ dwc_otg_dump_dev_registers(otg_dev->core_if); ++ ++ return sprintf(buf, "Register Dump\n"); ++} ++ ++DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); ++ ++/** ++ * Dump the current hcd state. ++ */ ++static ssize_t hcddump_show(struct device *_dev, struct device_attribute *attr, ++ char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ dwc_otg_hcd_dump_state(otg_dev->hcd); ++#endif ++ return sprintf(buf, "HCD Dump\n"); ++} ++ ++DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ */ ++static ssize_t hcd_frrem_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ dwc_otg_hcd_dump_frrem(otg_dev->hcd); ++#endif ++ return sprintf(buf, "HCD Dump Frame Remaining\n"); ++} ++ ++DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); ++ ++/** ++ * Displays the time required to read the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is read). ++ */ ++#define RW_REG_COUNT 10000000 ++#define MSEC_PER_JIFFIE (1000/HZ) ++static ssize_t rd_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int i; ++ int time; ++ int start_jiffies; ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ ++ pr_info("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) ++ dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz); ++ ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); ++ ++/** ++ * Displays the time required to write the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is written). ++ */ ++static ssize_t wr_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int i; ++ int time; ++ int start_jiffies; ++ struct dwc_otg_device *otg_dev = _dev->platform_data; ++ uint32_t reg_val; ++ ++ pr_info("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ reg_val = ++ dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) ++ dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz, ++ reg_val); ++ ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); ++ ++/* ++ * Create the device files ++ */ ++void dwc_otg_attr_create(struct device *dev) ++{ ++ int error; ++ error = device_create_file(dev, &dev_attr_regoffset); ++ error |= device_create_file(dev, &dev_attr_regvalue); ++ error |= device_create_file(dev, &dev_attr_mode); ++ error |= device_create_file(dev, &dev_attr_hnpcapable); ++ error |= device_create_file(dev, &dev_attr_srpcapable); ++ error |= device_create_file(dev, &dev_attr_hnp); ++ error |= device_create_file(dev, &dev_attr_srp); ++ error |= device_create_file(dev, &dev_attr_buspower); ++ error |= device_create_file(dev, &dev_attr_bussuspend); ++ error |= device_create_file(dev, &dev_attr_busconnected); ++ error |= device_create_file(dev, &dev_attr_gotgctl); ++ error |= device_create_file(dev, &dev_attr_gusbcfg); ++ error |= device_create_file(dev, &dev_attr_grxfsiz); ++ error |= device_create_file(dev, &dev_attr_gnptxfsiz); ++ error |= device_create_file(dev, &dev_attr_gpvndctl); ++ error |= device_create_file(dev, &dev_attr_ggpio); ++ error |= device_create_file(dev, &dev_attr_guid); ++ error |= device_create_file(dev, &dev_attr_gsnpsid); ++ error |= device_create_file(dev, &dev_attr_devspeed); ++ error |= device_create_file(dev, &dev_attr_enumspeed); ++ error |= device_create_file(dev, &dev_attr_hptxfsiz); ++ error |= device_create_file(dev, &dev_attr_hprt0); ++ error |= device_create_file(dev, &dev_attr_remote_wakeup); ++ error |= device_create_file(dev, &dev_attr_regdump); ++ error |= device_create_file(dev, &dev_attr_hcddump); ++ error |= device_create_file(dev, &dev_attr_hcd_frrem); ++ error |= device_create_file(dev, &dev_attr_rd_reg_test); ++ error |= device_create_file(dev, &dev_attr_wr_reg_test); ++ if (error) ++ pr_err("DWC_OTG: Creating some device files failed\n"); ++} ++ ++/* ++ * Remove the device files ++ */ ++void dwc_otg_attr_remove(struct device *dev) ++{ ++ device_remove_file(dev, &dev_attr_regoffset); ++ device_remove_file(dev, &dev_attr_regvalue); ++ device_remove_file(dev, &dev_attr_mode); ++ device_remove_file(dev, &dev_attr_hnpcapable); ++ device_remove_file(dev, &dev_attr_srpcapable); ++ device_remove_file(dev, &dev_attr_hnp); ++ device_remove_file(dev, &dev_attr_srp); ++ device_remove_file(dev, &dev_attr_buspower); ++ device_remove_file(dev, &dev_attr_bussuspend); ++ device_remove_file(dev, &dev_attr_busconnected); ++ device_remove_file(dev, &dev_attr_gotgctl); ++ device_remove_file(dev, &dev_attr_gusbcfg); ++ device_remove_file(dev, &dev_attr_grxfsiz); ++ device_remove_file(dev, &dev_attr_gnptxfsiz); ++ device_remove_file(dev, &dev_attr_gpvndctl); ++ device_remove_file(dev, &dev_attr_ggpio); ++ device_remove_file(dev, &dev_attr_guid); ++ device_remove_file(dev, &dev_attr_gsnpsid); ++ device_remove_file(dev, &dev_attr_devspeed); ++ device_remove_file(dev, &dev_attr_enumspeed); ++ device_remove_file(dev, &dev_attr_hptxfsiz); ++ device_remove_file(dev, &dev_attr_hprt0); ++ device_remove_file(dev, &dev_attr_remote_wakeup); ++ device_remove_file(dev, &dev_attr_regdump); ++ device_remove_file(dev, &dev_attr_hcddump); ++ device_remove_file(dev, &dev_attr_hcd_frrem); ++ device_remove_file(dev, &dev_attr_rd_reg_test); ++ device_remove_file(dev, &dev_attr_wr_reg_test); ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h +new file mode 100644 +index 0000000..925524f +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h +@@ -0,0 +1,63 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_ATTR_H__) ++#define __DWC_OTG_ATTR_H__ ++ ++/* ++ * This file contains the interface to the Linux device attributes. ++ */ ++extern struct device_attribute dev_attr_regoffset; ++extern struct device_attribute dev_attr_regvalue; ++ ++extern struct device_attribute dev_attr_mode; ++extern struct device_attribute dev_attr_hnpcapable; ++extern struct device_attribute dev_attr_srpcapable; ++extern struct device_attribute dev_attr_hnp; ++extern struct device_attribute dev_attr_srp; ++extern struct device_attribute dev_attr_buspower; ++extern struct device_attribute dev_attr_bussuspend; ++extern struct device_attribute dev_attr_busconnected; ++extern struct device_attribute dev_attr_gotgctl; ++extern struct device_attribute dev_attr_gusbcfg; ++extern struct device_attribute dev_attr_grxfsiz; ++extern struct device_attribute dev_attr_gnptxfsiz; ++extern struct device_attribute dev_attr_gpvndctl; ++extern struct device_attribute dev_attr_ggpio; ++extern struct device_attribute dev_attr_guid; ++extern struct device_attribute dev_attr_gsnpsid; ++extern struct device_attribute dev_attr_devspeed; ++extern struct device_attribute dev_attr_enumspeed; ++extern struct device_attribute dev_attr_hptxfsiz; ++extern struct device_attribute dev_attr_hprt0; ++ ++void dwc_otg_attr_create(struct device *dev); ++void dwc_otg_attr_remove(struct device *dev); ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c +new file mode 100644 +index 0000000..86153ba +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c +@@ -0,0 +1,2887 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/* ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * The CIL manages the memory map for the core so that the HCD and PCD ++ * don't have to do this separately. It also handles basic tasks like ++ * reading/writing the registers and data FIFOs in the controller. ++ * Some of the data access functions provide encapsulation of several ++ * operations required to perform a task, such as writing multiple ++ * registers to start a transfer. Finally, the CIL performs basic ++ * services that are not specific to either the host or device modes ++ * of operation. These services include management of the OTG Host ++ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A ++ * Diagnostic API is also provided to allow testing of the controller ++ * hardware. ++ * ++ * The Core Interface Layer has the following requirements: ++ * - Provides basic controller operations. ++ * - Minimal use of OS services. ++ * - The OS services used will be abstracted by using inline functions ++ * or macros. ++ * ++ */ ++#include ++#ifdef DEBUG ++#include ++#endif ++ ++#include "dwc_otg_plat.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++ ++/** ++ * This function is called to initialize the DWC_otg CSR data ++ * structures. The register addresses in the device and host ++ * structures are initialized from the base address supplied by the ++ * caller. The calling function must make the OS calls to get the ++ * base address of the DWC_otg controller registers. The core_params ++ * argument holds the parameters that specify how the core should be ++ * configured. ++ * ++ * @reg_base_addr: Base address of DWC_otg core registers ++ * @core_params: Pointer to the core configuration parameters ++ * ++ */ ++struct dwc_otg_core_if *dwc_otg_cil_init(const uint32_t *reg_base_addr, ++ struct dwc_otg_core_params *core_params) ++{ ++ struct dwc_otg_core_if *core_if = 0; ++ struct dwc_otg_dev_if *dev_if = 0; ++ struct dwc_otg_host_if *host_if = 0; ++ uint8_t *reg_base = (uint8_t *) reg_base_addr; ++ int i = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p,%p)\n", __func__, reg_base_addr, ++ core_params); ++ ++ core_if = kmalloc(sizeof(struct dwc_otg_core_if), GFP_KERNEL); ++ if (core_if == 0) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of struct dwc_otg_core_if failed\n"); ++ return 0; ++ } ++ memset(core_if, 0, sizeof(struct dwc_otg_core_if)); ++ ++ core_if->core_params = core_params; ++ core_if->core_global_regs = ++ (struct dwc_otg_core_global_regs *)reg_base; ++ /* ++ * Allocate the Device Mode structures. ++ */ ++ dev_if = kmalloc(sizeof(struct dwc_otg_dev_if), GFP_KERNEL); ++ if (dev_if == 0) { ++ DWC_DEBUGPL(DBG_CIL, "Allocation of struct dwc_otg_dev_if " ++ "failed\n"); ++ kfree(core_if); ++ return 0; ++ } ++ ++ dev_if->dev_global_regs = ++ (struct dwc_otg_dev_global_regs *) (reg_base + ++ DWC_DEV_GLOBAL_REG_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dev_if->in_ep_regs[i] = (struct dwc_otg_dev_in_ep_regs *) ++ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ ++ dev_if->out_ep_regs[i] = (struct dwc_otg_dev_out_ep_regs *) ++ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", ++ i, &dev_if->in_ep_regs[i]->diepctl); ++ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", ++ i, &dev_if->out_ep_regs[i]->doepctl); ++ } ++ dev_if->speed = 0; /* unknown */ ++ dev_if->num_eps = MAX_EPS_CHANNELS; ++ dev_if->num_perio_eps = 0; ++ ++ core_if->dev_if = dev_if; ++ /* ++ * Allocate the Host Mode structures. ++ */ ++ host_if = kmalloc(sizeof(struct dwc_otg_host_if), GFP_KERNEL); ++ if (host_if == 0) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of struct dwc_otg_host_if failed\n"); ++ kfree(dev_if); ++ kfree(core_if); ++ return 0; ++ } ++ ++ host_if->host_global_regs = (struct dwc_otg_host_global_regs *) ++ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET); ++ host_if->hprt0 = ++ (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ host_if->hc_regs[i] = (struct dwc_otg_hc_regs *) ++ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET + ++ (i * DWC_OTG_CHAN_REGS_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", ++ i, &host_if->hc_regs[i]->hcchar); ++ } ++ host_if->num_host_channels = MAX_EPS_CHANNELS; ++ core_if->host_if = host_if; ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ core_if->data_fifo[i] = ++ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET + ++ (i * DWC_OTG_DATA_FIFO_SIZE)); ++ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=%p\n", ++ i, core_if->data_fifo[i]); ++ } ++ ++ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); ++ ++ /* ++ * Store the contents of the hardware configuration registers here for ++ * easy access later. ++ */ ++ core_if->hwcfg1.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->ghwcfg1); ++ core_if->hwcfg2.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->ghwcfg2); ++ core_if->hwcfg3.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->ghwcfg3); ++ core_if->hwcfg4.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->ghwcfg4); ++ ++ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); ++ ++ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); ++ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); ++ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); ++ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", ++ core_if->hwcfg2.b.num_host_chan); ++ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.nonperio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.host_perio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.dev_token_q_depth); ++ ++ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", ++ core_if->hwcfg3.b.dfifo_depth); ++ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", ++ core_if->hwcfg3.b.xfer_size_cntr_width); ++ ++ /* ++ * Set the SRP sucess bit for FS-I2c ++ */ ++ core_if->srp_success = 0; ++ core_if->srp_timer_started = 0; ++ ++ return core_if; ++} ++ ++/** ++ * This function frees the structures allocated by dwc_otg_cil_init(). ++ * ++ * @core_if: The core interface pointer returned from ++ * dwc_otg_cil_init(). ++ * ++ */ ++void dwc_otg_cil_remove(struct dwc_otg_core_if *core_if) ++{ ++ /* Disable all interrupts */ ++ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 1, 0); ++ dwc_write_reg32(&core_if->core_global_regs->gintmsk, 0); ++ ++ kfree(core_if->dev_if); ++ kfree(core_if->host_if); ++ ++ kfree(core_if); ++} ++ ++/** ++ * This function enables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++extern void dwc_otg_enable_global_interrupts(struct dwc_otg_core_if *core_if) ++{ ++ union gahbcfg_data ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ ++ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); ++} ++ ++/** ++ * This function disables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++extern void dwc_otg_disable_global_interrupts(struct dwc_otg_core_if *core_if) ++{ ++ union gahbcfg_data ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ ++ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++} ++ ++/** ++ * This function initializes the commmon interrupts, used in both ++ * device and host modes. ++ * ++ * @core_if: Programming view of the DWC_otg controller ++ * ++ */ ++static void dwc_otg_enable_common_interrupts(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = ++ core_if->core_global_regs; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ /* Clear any pending OTG Interrupts */ ++ dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF); ++ /* Clear any pending interrupts */ ++ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); ++ /* ++ * Enable the interrupts in the GINTMSK. ++ */ ++ intr_mask.b.modemismatch = 1; ++ intr_mask.b.otgintr = 1; ++ if (!core_if->dma_enable) ++ intr_mask.b.rxstsqlvl = 1; ++ ++ intr_mask.b.conidstschng = 1; ++ intr_mask.b.wkupintr = 1; ++ intr_mask.b.disconnect = 1; ++ intr_mask.b.usbsuspend = 1; ++ intr_mask.b.sessreqintr = 1; ++ dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32); ++} ++ ++/** ++ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY ++ * type. ++ */ ++static void init_fslspclksel(struct dwc_otg_core_if *core_if) ++{ ++ uint32_t val; ++ union hcfg_data hcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = DWC_HCFG_48_MHZ; ++ } else { ++ /* High speed PHY running at full speed or high speed */ ++ val = DWC_HCFG_30_60_MHZ; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); ++ hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.fslspclksel = val; ++ dwc_write_reg32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/** ++ * Initializes the DevSpd field of the DCFG register depending on the PHY type ++ * and the enumeration speed of the device. ++ */ ++static void init_devspd(struct dwc_otg_core_if *core_if) ++{ ++ uint32_t val; ++ union dcfg_data dcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = 0x3; ++ } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ /* High speed PHY running at full speed */ ++ val = 0x1; ++ } else { ++ /* High speed PHY running at high speed */ ++ val = 0x0; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); ++ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers and ++ * prepares the core for device mode or host mode operation. ++ * ++ * @core_if: Programming view of the DWC_otg controller ++ * ++ */ ++void dwc_otg_core_init(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ struct dwc_otg_dev_if *dev_if = core_if->dev_if; ++ int i = 0; ++ union gahbcfg_data ahbcfg = {.d32 = 0 }; ++ union gusbcfg_data usbcfg = {.d32 = 0 }; ++ union gi2cctl_data i2cctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p)\n", core_if); ++ ++ /* Common Initialization */ ++ ++ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ ++ /* Program the ULPI External VBUS bit if needed */ ++ usbcfg.b.ulpi_ext_vbus_drv = ++ (core_if->core_params->phy_ulpi_ext_vbus == ++ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0; ++ ++ /* Set external TS Dline pulsing */ ++ usbcfg.b.term_sel_dl_pulse = ++ (core_if->core_params->ts_dline == 1) ? 1 : 0; ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset the Controller */ ++ dwc_otg_core_reset(core_if); ++ ++ /* Initialize parameters from Hardware configuration registers. */ ++ dev_if->num_eps = core_if->hwcfg2.b.num_dev_ep; ++ dev_if->num_perio_eps = core_if->hwcfg4.b.num_dev_perio_in_ep; ++ ++ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", ++ core_if->hwcfg4.b.num_dev_perio_in_ep); ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ dev_if->perio_tx_fifo_size[i] = ++ dwc_read_reg32(&global_regs->dptxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->perio_tx_fifo_size[i]); ++ } ++ ++ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; ++ core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz); ++ core_if->nperio_tx_fifo_size = ++ dwc_read_reg32(&global_regs->gnptxfsiz) >> 16; ++ ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n", ++ core_if->nperio_tx_fifo_size); ++ ++ /* This programming sequence needs to happen in FS mode before any other ++ * programming occurs */ ++ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) && ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* If FS mode with FS PHY */ ++ ++ /* core_init() is now called on every switch so only call the ++ * following for the first time through. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); ++ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.b.physel = 1; ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset after a PHY select */ ++ dwc_otg_core_reset(core_if); ++ } ++ ++ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also ++ * do this on HNP Dev/Host mode switches (done in dev_init and ++ * host_init). */ ++ if (dwc_otg_is_host_mode(core_if)) ++ init_fslspclksel(core_if); ++ else ++ init_devspd(core_if); ++ ++ if (core_if->core_params->i2c_enable) { ++ DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); ++ /* Program GUSBCFG.OtgUtmifsSel to I2C */ ++ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.b.otgutmifssel = 1; ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Program GI2CCTL.I2CEn */ ++ i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl); ++ i2cctl.b.i2cdevaddr = 1; ++ i2cctl.b.i2cen = 0; ++ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); ++ i2cctl.b.i2cen = 1; ++ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); ++ } ++ ++ } ++ /* endif speed == DWC_SPEED_PARAM_FULL */ ++ else { ++ /* High speed PHY. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ /* HS PHY parameters. These parameters are preserved ++ * during soft reset so only program the first time. Do ++ * a soft reset immediately after setting phyif. */ ++ usbcfg.b.ulpi_utmi_sel = ++ (core_if->core_params->phy_type == ++ DWC_PHY_TYPE_PARAM_ULPI); ++ if (usbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ usbcfg.b.phyif = 0; ++ usbcfg.b.ddrsel = ++ core_if->core_params->phy_ulpi_ddr; ++ } else { ++ /* UTMI+ interface */ ++ if (core_if->core_params->phy_utmi_width == 16) ++ usbcfg.b.phyif = 1; ++ else ++ usbcfg.b.phyif = 0; ++ } ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset after setting the PHY parameters */ ++ dwc_otg_core_reset(core_if); ++ } ++ } ++ ++ if ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) { ++ DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); ++ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 1; ++ usbcfg.b.ulpi_clk_sus_m = 1; ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ } else { ++ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 0; ++ usbcfg.b.ulpi_clk_sus_m = 0; ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ } ++ ++ /* Program the GAHBCFG Register. */ ++ switch (core_if->hwcfg2.b.architecture) { ++ ++ case DWC_SLAVE_ONLY_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n"); ++ ahbcfg.b.nptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ core_if->dma_enable = 0; ++ break; ++ ++ case DWC_EXT_DMA_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n"); ++ ahbcfg.b.hburstlen = core_if->core_params->dma_burst_size; ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ break; ++ ++ case DWC_INT_DMA_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); ++ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR; ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ break; ++ ++ } ++ ahbcfg.b.dmaenable = core_if->dma_enable; ++ dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32); ++ ++ /* ++ * Program the GUSBCFG register. ++ */ ++ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ ++ switch (core_if->hwcfg2.b.op_mode) { ++ case DWC_MODE_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = (core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_SRP_ONLY_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case DWC_MODE_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case DWC_MODE_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ } ++ ++ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Enable common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Do device or host intialization based on mode during PCD ++ * and HCD initialization */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "Host Mode\n"); ++ core_if->op_state = A_HOST; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "Device Mode\n"); ++ core_if->op_state = B_PERIPHERAL; ++#ifdef DWC_DEVICE_ONLY ++ dwc_otg_core_dev_init(core_if); ++#endif ++ } ++} ++ ++/** ++ * This function enables the Device mode interrupts. ++ * ++ * @core_if: Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_device_interrupts(struct dwc_otg_core_if *core_if) ++{ ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ dwc_write_reg32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Enable interrupts */ ++ intr_mask.b.usbreset = 1; ++ intr_mask.b.enumdone = 1; ++ intr_mask.b.epmismatch = 1; ++ intr_mask.b.inepintr = 1; ++ intr_mask.b.outepintr = 1; ++ intr_mask.b.erlysuspend = 1; ++ ++#ifdef USE_PERIODIC_EP ++ /** @todo NGS: Should this be a module parameter? */ ++ intr_mask.b.isooutdrop = 1; ++ intr_mask.b.eopframe = 1; ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++#endif ++ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ++ dwc_read_reg32(&global_regs->gintmsk)); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * device mode. ++ * ++ * @core_if: Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_dev_init(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ struct dwc_otg_dev_if *dev_if = core_if->dev_if; ++ struct dwc_otg_core_params *params = core_if->core_params; ++ union dcfg_data dcfg = {.d32 = 0 }; ++ union grstctl_data resetctl = {.d32 = 0 }; ++ int i; ++ uint32_t rx_fifo_size; ++ union fifosize_data nptxfifosize; ++#ifdef USE_PERIODIC_EP ++ union fifosize_data ptxfifosize; ++#endif ++ ++ /* Restart the Phy Clock */ ++ dwc_write_reg32(core_if->pcgcctl, 0); ++ ++ /* Device configuration register */ ++ init_devspd(core_if); ++ dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; ++ dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->dev_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->dev_nperio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->grxfsiz)); ++ rx_fifo_size = params->dev_rx_fifo_size; ++ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->grxfsiz)); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ ++#ifdef USE_PERIODIC_EP ++ /**@todo NGS: Fix Periodic FIFO Sizing! */ ++ /* ++ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_perio_tx_fifo_size array and the FIFO size registers in ++ * the dptxfsiz array run from 0 to 14. ++ */ ++ /** @todo Finish debug of this */ ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ for (i = 0; i < dev_if->num_perio_eps; i++) { ++ ptxfifosize.b.depth = params->dev_perio_tx_fifo_size[i]; ++ DWC_DEBUGPL(DBG_CIL, "initial dptxfsiz[%d]=%08x\n", i, ++ dwc_read_reg32(&global_regs->dptxfsiz[i])); ++ dwc_write_reg32(&global_regs->dptxfsiz[i], ++ ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new dptxfsiz[%d]=%08x\n", i, ++ dwc_read_reg32(&global_regs->dptxfsiz[i])); ++ ptxfifosize.b.startaddr += ptxfifosize.b.depth; ++ } ++#endif ++ } ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Flush the Learning Queue. */ ++ resetctl.b.intknqflsh = 1; ++ dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ /* Clear all pending Device Interrupts */ ++ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0); ++ dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0); ++ dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); ++ dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0); ++ ++ for (i = 0; i < dev_if->num_eps; i++) { ++ union depctl_data depctl; ++ depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } else { ++ depctl.d32 = 0; ++ } ++ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ ++ depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); ++ if (depctl.b.epena) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } else { ++ depctl.d32 = 0; ++ } ++ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ ++ dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0); ++ dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0); ++ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0); ++ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0); ++ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF); ++ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF); ++ } ++ ++ dwc_otg_enable_device_interrupts(core_if); ++} ++ ++/** ++ * This function enables the Host mode interrupts. ++ * ++ * @core_if: Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_host_interrupts(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ dwc_write_reg32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts. */ ++ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* ++ * Enable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ intr_mask.b.sofintr = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ ++ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++} ++ ++/** ++ * This function disables the Host Mode interrupts. ++ * ++ * @core_if: Programming view of DWC_otg controller ++ */ ++void dwc_otg_disable_host_interrupts(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); ++ ++ /* ++ * Disable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ intr_mask.b.sofintr = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ intr_mask.b.ptxfempty = 1; ++ intr_mask.b.nptxfempty = 1; ++ ++ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0); ++} ++ ++/** ++ * The FIFOs are established based on a default percentage of the ++ * total FIFO depth. This function converts the percentage into the ++ * proper setting. ++ * ++ */ ++static inline uint32_t fifo_percentage(uint16_t total_fifo_size, ++ int32_t percentage) ++{ ++ /* 16-byte aligned */ ++ return ((total_fifo_size * percentage) / 100) & (-1 << 3); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * host mode. ++ * ++ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the ++ * request queues. Host channels are reset to ensure that they are ready for ++ * performing transfers. ++ * ++ * @core_if: Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_host_init(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ struct dwc_otg_host_if *host_if = core_if->host_if; ++ struct dwc_otg_core_params *params = core_if->core_params; ++ union hprt0_data hprt0 = {.d32 = 0 }; ++ union fifosize_data nptxfifosize; ++ union fifosize_data ptxfifosize; ++ int i; ++ union hcchar_data hcchar; ++ union hcfg_data hcfg; ++ struct dwc_otg_hc_regs *hc_regs; ++ int num_channels; ++ union gotgctl_data gotgctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); ++ ++ /* Restart the Phy Clock */ ++ dwc_write_reg32(core_if->pcgcctl, 0); ++ ++ /* Initialize Host Configuration Register */ ++ init_fslspclksel(core_if); ++ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg); ++ hcfg.b.fslssupp = 1; ++ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->host_nperio_tx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", ++ params->host_perio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->grxfsiz)); ++ dwc_write_reg32(&global_regs->grxfsiz, ++ fifo_percentage(core_if->total_fifo_size, ++ dwc_param_host_rx_fifo_size_percentage)); ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->grxfsiz)); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ nptxfifosize.b.depth = ++ fifo_percentage(core_if->total_fifo_size, ++ dwc_param_host_nperio_tx_fifo_size_percentage); ++ nptxfifosize.b.startaddr = ++ dwc_read_reg32(&global_regs->grxfsiz); ++ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ ++ /* Periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->hptxfsiz)); ++ ptxfifosize.b.depth = ++ core_if->total_fifo_size - ++ dwc_read_reg32(&global_regs->grxfsiz) - ++ nptxfifosize.b.depth; ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", ++ dwc_read_reg32(&global_regs->hptxfsiz)); ++ } ++ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); ++ ++ /* Make sure the FIFOs are flushed. */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Flush out any leftover queued requests. */ ++ num_channels = core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ } ++ ++ /* Halt all channels to put them into a known state. */ ++ for (i = 0; i < num_channels; i++) { ++ int count = 0; ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i); ++ do { ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (++count > 1000) { ++ DWC_ERROR ++ ("%s: Unable to clear halt on channel %d\n", ++ __func__, i); ++ break; ++ } ++ } while (hcchar.b.chen); ++ } ++ ++ /* Turn on the vbus power. */ ++ DWC_PRINT("Init: Port Power? op_state=%d\n", core_if->op_state); ++ if (core_if->op_state == A_HOST) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ dwc_write_reg32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ dwc_otg_enable_host_interrupts(core_if); ++} ++ ++/** ++ * Prepares a host channel for transferring packets to/from a specific ++ * endpoint. The HCCHARn register is set up with the characteristics specified ++ * in hc. Host channel interrupts that may need to be serviced while this ++ * transfer is in progress are enabled. ++ * ++ * @core_if: Programming view of DWC_otg controller ++ * @hc: Information needed to initialize the host channel ++ */ ++void dwc_otg_hc_init(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) ++{ ++ uint32_t intr_enable; ++ union hcintmsk_data hc_intr_mask; ++ union gintmsk_data gintmsk = {.d32 = 0 }; ++ union hcchar_data hcchar; ++ union hcsplt_data hcsplt; ++ ++ uint8_t hc_num = hc->hc_num; ++ struct dwc_otg_host_if *host_if = core_if->host_if; ++ struct dwc_otg_hc_regs *hc_regs = host_if->hc_regs[hc_num]; ++ ++ /* Clear old interrupt conditions for this host channel. */ ++ hc_intr_mask.d32 = 0xFFFFFFFF; ++ hc_intr_mask.b.reserved = 0; ++ dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32); ++ ++ /* Enable channel interrupts required for this transfer. */ ++ hc_intr_mask.d32 = 0; ++ hc_intr_mask.b.chhltd = 1; ++ if (core_if->dma_enable) { ++ hc_intr_mask.b.ahberr = 1; ++ if (hc->error_state && !hc->do_split && ++ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hc_intr_mask.b.ack = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) ++ hc_intr_mask.b.nak = 1; ++ } ++ } ++ } else { ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } else { ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.nyet = 1; ++ if (hc->do_ping) ++ hc_intr_mask.b.ack = 1; ++ } ++ ++ if (hc->do_split) { ++ hc_intr_mask.b.nak = 1; ++ if (hc->complete_split) ++ hc_intr_mask.b.nyet = 1; ++ else ++ hc_intr_mask.b.ack = 1; ++ } ++ ++ if (hc->error_state) ++ hc_intr_mask.b.ack = 1; ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ ++ if (hc->ep_is_in) ++ hc_intr_mask.b.bblerr = 1; ++ if (hc->error_state) ++ hc_intr_mask.b.ack = 1; ++ if (hc->do_split) { ++ if (hc->complete_split) ++ hc_intr_mask.b.nyet = 1; ++ else ++ hc_intr_mask.b.ack = 1; ++ } ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ hc_intr_mask.b.ack = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.bblerr = 1; ++ } ++ break; ++ } ++ } ++ dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32); ++ ++ /* Enable the top level host channel interrupt. */ ++ intr_enable = (1 << hc_num); ++ dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable); ++ ++ /* Make sure host channel interrupts are enabled. */ ++ gintmsk.b.hcintr = 1; ++ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); ++ ++ /* ++ * Program the HCCHARn register with the endpoint characteristics for ++ * the current transfer. ++ */ ++ hcchar.d32 = 0; ++ hcchar.b.devaddr = hc->dev_addr; ++ hcchar.b.epnum = hc->ep_num; ++ hcchar.b.epdir = hc->ep_is_in; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.eptype = hc->ep_type; ++ hcchar.b.mps = hc->max_packet; ++ ++ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); ++ DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); ++ DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); ++ DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); ++ DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); ++ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); ++ ++ /* ++ * Program the HCSPLIT register for SPLITs ++ */ ++ hcsplt.d32 = 0; ++ if (hc->do_split) { ++ DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ++ hc->hc_num, ++ hc->complete_split ? "CSPLIT" : "SSPLIT"); ++ hcsplt.b.compsplt = hc->complete_split; ++ hcsplt.b.xactpos = hc->xact_pos; ++ hcsplt.b.hubaddr = hc->hub_addr; ++ hcsplt.b.prtaddr = hc->port_addr; ++ DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", ++ hc->complete_split); ++ DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); ++ DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); ++ DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); ++ DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); ++ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); ++ } ++ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); ++ ++} ++ ++/** ++ * Attempts to halt a host channel. This function should only be called in ++ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under ++ * normal circumstances in DMA mode, the controller halts the channel when the ++ * transfer is complete or a condition occurs that requires application ++ * intervention. ++ * ++ * In slave mode, checks for a free request queue entry, then sets the Channel ++ * Enable and Channel Disable bits of the Host Channel Characteristics ++ * register of the specified channel to intiate the halt. If there is no free ++ * request queue entry, sets only the Channel Disable bit of the HCCHARn ++ * register to flush requests for this channel. In the latter case, sets a ++ * flag to indicate that the host channel needs to be halted when a request ++ * queue slot is open. ++ * ++ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the ++ * HCCHARn register. The controller ensures there is space in the request ++ * queue before submitting the halt request. ++ * ++ * Some time may elapse before the core flushes any posted requests for this ++ * host channel and halts. The Channel Halted interrupt handler completes the ++ * deactivation of the host channel. ++ * ++ * @core_if: Controller register interface. ++ * @hc: Host channel to halt. ++ * @halt_status: Reason for halting the channel. ++ */ ++void dwc_otg_hc_halt(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc, enum dwc_otg_halt_status halt_status) ++{ ++ union gnptxsts_data nptxsts; ++ union hptxsts_data hptxsts; ++ union hcchar_data hcchar; ++ struct dwc_otg_hc_regs *hc_regs; ++ struct dwc_otg_core_global_regs *global_regs; ++ struct dwc_otg_host_global_regs *host_global_regs; ++ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ global_regs = core_if->core_global_regs; ++ host_global_regs = core_if->host_if->host_global_regs; ++ ++ WARN_ON(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ ++ if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ /* ++ * Disable all channel interrupts except Ch Halted. The QTD ++ * and QH state associated with this transfer has been cleared ++ * (in the case of URB_DEQUEUE), so the channel needs to be ++ * shut down carefully to prevent crashes. ++ */ ++ union hcintmsk_data hcintmsk; ++ hcintmsk.d32 = 0; ++ hcintmsk.b.chhltd = 1; ++ dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32); ++ ++ /* ++ * Make sure no other interrupts besides halt are currently ++ * pending. Handling another interrupt could cause a crash due ++ * to the QTD and QH state. ++ */ ++ dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32); ++ ++ /* ++ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR ++ * even if the channel was already halted for some other ++ * reason. ++ */ ++ hc->halt_status = halt_status; ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chen == 0) { ++ /* ++ * The channel is either already halted or it hasn't ++ * started yet. In DMA mode, the transfer may halt if ++ * it finishes normally or a condition occurs that ++ * requires driver intervention. Don't want to halt ++ * the channel again. In either Slave or DMA mode, ++ * it's possible that the transfer has been assigned ++ * to a channel, but not started yet when an URB is ++ * dequeued. Don't want to halt a channel that hasn't ++ * started yet. ++ */ ++ return; ++ } ++ } ++ ++ if (hc->halt_pending) { ++ /* ++ * A halt has already been issued for this channel. This might ++ * happen when a transfer is aborted by a higher level in ++ * the stack. ++ */ ++#ifdef DEBUG ++ DWC_PRINT ++ ("*** %s: Channel %d, hc->halt_pending already set ***\n", ++ __func__, hc->hc_num); ++ ++/* dwc_otg_dump_global_registers(core_if); */ ++/* dwc_otg_dump_host_registers(core_if); */ ++#endif ++ return; ++ } ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ ++ if (!core_if->dma_enable) { ++ /* Check for space in the request queue to issue the halt. */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ if (nptxsts.b.nptxqspcavail == 0) ++ hcchar.b.chen = 0; ++ } else { ++ hptxsts.d32 = ++ dwc_read_reg32(&host_global_regs->hptxsts); ++ if ((hptxsts.b.ptxqspcavail == 0) ++ || (core_if->queuing_high_bandwidth)) { ++ hcchar.b.chen = 0; ++ } ++ } ++ } ++ ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->halt_status = halt_status; ++ ++ if (hcchar.b.chen) { ++ hc->halt_pending = 1; ++ hc->halt_on_queue = 0; ++ } else { ++ hc->halt_on_queue = 1; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); ++ DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); ++ ++ return; ++} ++ ++/** ++ * Clears the transfer state for a host channel. This function is normally ++ * called after a transfer is done and the host channel is being released. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @hc: Identifies the host channel to clean up. ++ */ ++void dwc_otg_hc_cleanup(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) ++{ ++ struct dwc_otg_hc_regs *hc_regs; ++ ++ hc->xfer_started = 0; ++ ++ /* ++ * Clear channel interrupt enables and any unhandled channel interrupt ++ * conditions. ++ */ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ dwc_write_reg32(&hc_regs->hcintmsk, 0); ++ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF); ++ ++#ifdef DEBUG ++ del_timer(&core_if->hc_xfer_timer[hc->hc_num]); ++ { ++ union hcchar_data hcchar; ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++ } ++#endif ++} ++ ++/** ++ * Sets the channel property that indicates in which frame a periodic transfer ++ * should occur. This is always set to the _next_ frame. This function has no ++ * effect on non-periodic transfers. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @hc: Identifies the host channel to set up and its properties. ++ * @hcchar: Current value of the HCCHAR register for the specified host ++ * channel. ++ */ ++static inline void hc_set_even_odd_frame(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc, ++ union hcchar_data *hcchar) ++{ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ union hfnum_data hfnum; ++ hfnum.d32 = ++ dwc_read_reg32(&core_if->host_if->host_global_regs->hfnum); ++ /* 1 if _next_ frame is odd, 0 if it's even */ ++ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; ++#ifdef DEBUG ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split ++ && !hc->complete_split) { ++ switch (hfnum.b.frnum & 0x7) { ++ case 7: ++ core_if->hfnum_7_samples++; ++ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; ++ break; ++ case 0: ++ core_if->hfnum_0_samples++; ++ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; ++ break; ++ default: ++ core_if->hfnum_other_samples++; ++ core_if->hfnum_other_frrem_accum += ++ hfnum.b.frrem; ++ break; ++ } ++ } ++#endif ++ } ++} ++ ++#ifdef DEBUG ++static void hc_xfer_timeout(unsigned long _ptr) ++{ ++ struct hc_xfer_info *xfer_info = (struct hc_xfer_info *) _ptr; ++ int hc_num = xfer_info->hc->hc_num; ++ DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); ++ DWC_WARN(" start_hcchar_val 0x%08x\n", ++ xfer_info->core_if->start_hcchar_val[hc_num]); ++} ++#endif ++ ++/** ++ * This function does the setup for a data transfer for a host channel and ++ * starts the transfer. May be called in either Slave mode or DMA mode. In ++ * Slave mode, the caller must ensure that there is sufficient space in the ++ * request queue and Tx Data FIFO. ++ * ++ * For an OUT transfer in Slave mode, it loads a data packet into the ++ * appropriate FIFO. If necessary, additional data packets will be loaded in ++ * the Host ISR. ++ * ++ * For an IN transfer in Slave mode, a data packet is requested. The data ++ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, ++ * additional data packets are requested in the Host ISR. ++ * ++ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ ++ * register along with a packet count of 1 and the channel is enabled. This ++ * causes a single PING transaction to occur. Other fields in HCTSIZ are ++ * simply set to 0 since no data transfer occurs in this case. ++ * ++ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with ++ * all the information required to perform the subsequent data transfer. In ++ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the ++ * controller performs the entire PING protocol, then starts the data ++ * transfer. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @hc: Information needed to initialize the host channel. The xfer_len ++ * value may be reduced to accommodate the max widths of the XferSize and ++ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed ++ * to reflect the final xfer_len value. ++ */ ++void dwc_otg_hc_start_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc) ++{ ++ union hcchar_data hcchar; ++ union hctsiz_data hctsiz; ++ uint16_t num_packets; ++ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; ++ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; ++ struct dwc_otg_hc_regs *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) { ++ if (!core_if->dma_enable) { ++ dwc_otg_hc_do_ping(core_if, hc); ++ hc->xfer_started = 1; ++ return; ++ } else { ++ hctsiz.b.dopng = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ num_packets = 1; ++ ++ if (hc->complete_split && !hc->ep_is_in) { ++ /* For CSPLIT OUT Transfer, set the size to 0 so the ++ * core doesn't expect any data written to the FIFO */ ++ hc->xfer_len = 0; ++ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { ++ hc->xfer_len = hc->max_packet; ++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { ++ hc->xfer_len = 188; ++ } ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } else { ++ /* ++ * Ensure that the transfer length and packet count will fit ++ * in the widths allocated for them in the HCTSIZn register. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure the transfer size is no larger than one ++ * (micro)frame's worth of data. (A check was done ++ * when the periodic transfer was accepted to ensure ++ * that a (micro)frame's worth of data can be ++ * programmed into a channel.) ++ */ ++ uint32_t max_periodic_len = ++ hc->multi_count * hc->max_packet; ++ if (hc->xfer_len > max_periodic_len) ++ hc->xfer_len = max_periodic_len; ++ } else if (hc->xfer_len > max_hc_xfer_size) { ++ /* ++ * Make sure that xfer_len is a multiple of ++ * max packet size. ++ */ ++ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; ++ } ++ ++ if (hc->xfer_len > 0) { ++ num_packets = ++ (hc->xfer_len + hc->max_packet - ++ 1) / hc->max_packet; ++ if (num_packets > max_hc_pkt_count) { ++ num_packets = max_hc_pkt_count; ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ ++ if (hc->ep_is_in) { ++ /* ++ * Always program an integral # of max packets ++ * for IN transfers. ++ */ ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure that the multi_count field matches the ++ * actual transfer length. ++ */ ++ hc->multi_count = num_packets; ++ ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* Set up the initial PID for the transfer. */ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ if (hc->ep_is_in) { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = ++ DWC_OTG_HC_PID_DATA0; ++ } else if (hc->multi_count == 2) { ++ hc->data_pid_start = ++ DWC_OTG_HC_PID_DATA1; ++ } else { ++ hc->data_pid_start = ++ DWC_OTG_HC_PID_DATA2; ++ } ++ } else { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = ++ DWC_OTG_HC_PID_DATA0; ++ } else { ++ hc->data_pid_start = ++ DWC_OTG_HC_PID_MDATA; ++ } ++ } ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } ++ } ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } ++ ++ hc->start_pkt_count = num_packets; ++ hctsiz.b.pktcnt = num_packets; ++ hctsiz.b.pid = hc->data_pid_start; ++ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ ++ if (core_if->dma_enable) { ++#ifdef CONFIG_CPU_CAVIUM_OCTEON ++ /* Octeon uses external DMA */ ++ const uint64_t USBN_DMA0_OUTB_CHN0 = ++ CVMX_USBNX_DMA0_OUTB_CHN0(core_if->usb_num); ++ wmb(); ++ cvmx_write_csr(USBN_DMA0_OUTB_CHN0 + hc->hc_num * 8, ++ (unsigned long)hc->xfer_buff); ++ cvmx_read_csr(USBN_DMA0_OUTB_CHN0 + hc->hc_num * 8); ++ DWC_DEBUGPL(DBG_HCDV, ++ "OUT: hc->hc_num = %d, hc->xfer_buff = %p\n", ++ hc->hc_num, hc->xfer_buff); ++#else ++ dwc_write_reg32(&hc_regs->hcdma, ++ (uint32_t) (long)hc->xfer_buff); ++#endif /* CONFIG_CPU_CAVIUM_OCTEON */ ++ } ++ ++ /* Start the split */ ++ if (hc->do_split) { ++ union hcsplt_data hcsplt; ++ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); ++ hcsplt.b.spltena = 1; ++ dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32); ++ } ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ } ++#ifdef DEBUG ++ /* Start a timer for this transfer. */ ++ core_if->hc_xfer_timer[hc->hc_num].function = hc_xfer_timeout; ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ core_if->hc_xfer_timer[hc->hc_num].data = ++ (unsigned long)(&core_if->hc_xfer_info[hc->hc_num]); ++ core_if->hc_xfer_timer[hc->hc_num].expires = jiffies + (HZ * 10); ++ add_timer(&core_if->hc_xfer_timer[hc->hc_num]); ++#endif ++} ++ ++/** ++ * This function continues a data transfer that was started by previous call ++ * to dwc_otg_hc_start_transfer. The caller must ensure there is ++ * sufficient space in the request queue and Tx Data FIFO. This function ++ * should only be called in Slave mode. In DMA mode, the controller acts ++ * autonomously to complete transfers programmed to a host channel. ++ * ++ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO ++ * if there is any data remaining to be queued. For an IN transfer, another ++ * data packet is always requested. For the SETUP phase of a control transfer, ++ * this function does nothing. ++ * ++ * Returns 1 if a new request is queued, 0 if no more requests are required ++ * for this transfer. ++ */ ++int dwc_otg_hc_continue_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc) ++{ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ if (hc->do_split) { ++ /* SPLITs always queue just once per channel */ ++ return 0; ++ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ /* SETUPs are queued only once since they can't be NAKed. */ ++ return 0; ++ } else if (hc->ep_is_in) { ++ /* ++ * Always queue another request for other IN transfers. If ++ * back-to-back INs are issued and NAKs are received for both, ++ * the driver may still be processing the first NAK when the ++ * second NAK is received. When the interrupt handler clears ++ * the NAK interrupt for the first NAK, the second NAK will ++ * not be seen. So we can't depend on the NAK interrupt ++ * handler to requeue a NAKed request. Instead, IN requests ++ * are issued each time this function is called. When the ++ * transfer completes, the extra requests for the channel will ++ * be flushed. ++ */ ++ union hcchar_data hcchar; ++ struct dwc_otg_hc_regs *hc_regs = ++ core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", ++ hcchar.d32); ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ hc->requests++; ++ return 1; ++ } else { ++ /* OUT transfers. */ ++ if (hc->xfer_count < hc->xfer_len) { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ union hcchar_data hcchar; ++ struct dwc_otg_hc_regs *hc_regs; ++ hc_regs = ++ core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ } ++ ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ hc->requests++; ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++} ++ ++/** ++ * Starts a PING transfer. This function should only be called in Slave mode. ++ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. ++ */ ++void dwc_otg_hc_do_ping(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) ++{ ++ union hcchar_data hcchar; ++ union hctsiz_data hctsiz; ++ struct dwc_otg_hc_regs *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ hctsiz.d32 = 0; ++ hctsiz.b.dopng = 1; ++ hctsiz.b.pktcnt = 1; ++ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++} ++ ++/* ++ * This function writes a packet into the Tx FIFO associated with the Host ++ * Channel. For a channel associated with a non-periodic EP, the non-periodic ++ * Tx FIFO is written. For a channel associated with a periodic EP, the ++ * periodic Tx FIFO is written. This function should only be called in Slave ++ * mode. ++ * ++ * Upon return the xfer_buff and xfer_count fields in hc are incremented by ++ * then number of bytes written to the Tx FIFO. ++ */ ++void dwc_otg_hc_write_packet(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) ++{ ++ uint32_t i; ++ uint32_t remaining_count; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ ++ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); ++ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; ++ ++ remaining_count = hc->xfer_len - hc->xfer_count; ++ if (remaining_count > hc->max_packet) ++ byte_count = hc->max_packet; ++ else ++ byte_count = remaining_count; ++ ++ dword_count = (byte_count + 3) / 4; ++ ++ if ((((unsigned long)data_buff) & 0x3) == 0) { ++ /* xfer_buff is DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) ++ dwc_write_reg32(data_fifo, *data_buff); ++ } else { ++ /* xfer_buff is not DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) ++ dwc_write_reg32(data_fifo, get_unaligned(data_buff)); ++ } ++ ++ hc->xfer_count += byte_count; ++ hc->xfer_buff += byte_count; ++} ++ ++/** ++ * Gets the current USB frame number. This is the frame number from the last ++ * SOF packet. ++ */ ++uint32_t dwc_otg_get_frame_number(struct dwc_otg_core_if *core_if) ++{ ++ union dsts_data dsts; ++ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /* read current frame/microfreme number from DSTS register */ ++ return dsts.b.soffn; ++} ++ ++/** ++ * This function reads a setup packet from the Rx FIFO into the destination ++ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) ++ * Interrupt routine when a SETUP packet has been received in Slave mode. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @dest: Destination buffer for packet data. ++ */ ++void dwc_otg_read_setup_packet(struct dwc_otg_core_if *core_if, uint32_t *dest) ++{ ++ /* Get the 8 bytes of a setup transaction data */ ++ ++ /* Pop 2 DWORDS off the receive data FIFO into memory */ ++ dest[0] = dwc_read_reg32(core_if->data_fifo[0]); ++ dest[1] = dwc_read_reg32(core_if->data_fifo[0]); ++} ++ ++/** ++ * This function enables EP0 OUT to receive SETUP packets and configures EP0 ++ * IN for transmitting packets. It is normally called when the ++ * "Enumeration Done" interrupt occurs. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP0 data. ++ */ ++void dwc_otg_ep0_activate(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) ++{ ++ struct dwc_otg_dev_if *dev_if = core_if->dev_if; ++ union dsts_data dsts; ++ union depctl_data diepctl; ++ union depctl_data doepctl; ++ union dctl_data dctl = {.d32 = 0 }; ++ ++ /* Read the Device Status and Endpoint 0 Control registers */ ++ dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts); ++ diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); ++ doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl); ++ ++ /* Set the MPS of the IN EP based on the enumeration speed */ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_64; ++ break; ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_8; ++ break; ++ } ++ ++ dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Enable OUT EP for receive */ ++ doepctl.b.epena = 1; ++ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++ dctl.b.cgnpinnak = 1; ++ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", ++ dwc_read_reg32(&dev_if->dev_global_regs->dctl)); ++} ++ ++/** ++ * This function activates an EP. The Device EP control register for ++ * the EP is configured as defined in the ep structure. Note: This ++ * function is not used for EP0. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP to activate. ++ */ ++void dwc_otg_ep_activate(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) ++{ ++ struct dwc_otg_dev_if *dev_if = core_if->dev_if; ++ union depctl_data depctl; ++ uint32_t *addr; ++ union daint_data daintmsk = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ /* If the EP is already active don't change the EP Control ++ * register. */ ++ depctl.d32 = dwc_read_reg32(addr); ++ if (!depctl.b.usbactep) { ++ depctl.b.mps = ep->maxpacket; ++ depctl.b.eptype = ep->type; ++ depctl.b.txfnum = ep->tx_fifo_num; ++ ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) ++ depctl.b.setd0pid = 1; ++ ++ depctl.b.usbactep = 1; ++ ++ dwc_write_reg32(addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", dwc_read_reg32(addr)); ++ } ++ ++ /* Enable the Interrupt for this EP */ ++ dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk, 0, daintmsk.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", ++ dwc_read_reg32(&dev_if->dev_global_regs->daintmsk)); ++ return; ++} ++ ++/** ++ * This function deactivates an EP. This is done by clearing the USB Active ++ * EP bit in the Device EP control register. Note: This function is not used ++ * for EP0. EP0 cannot be deactivated. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP to deactivate. ++ */ ++void dwc_otg_ep_deactivate(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) ++{ ++ union depctl_data depctl = {.d32 = 0 }; ++ uint32_t *addr; ++ union daint_data daintmsk = {.d32 = 0 }; ++ ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ depctl.b.usbactep = 0; ++ dwc_write_reg32(addr, depctl.d32); ++ ++ /* Disable the Interrupt for this EP */ ++ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32, 0); ++ ++ return; ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP to start the transfer on. ++ */ ++void dwc_otg_ep_start_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep) ++{ ++ /* ++ * @todo Refactor this funciton to check the transfer size ++ * count value does not execed the number bits in the Transfer ++ * count register. ++ */ ++ union depctl_data depctl; ++ union deptsiz_data deptsiz; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ ++#ifdef CHECK_PACKET_COUNTER_WIDTH ++ const uint32_t MAX_XFER_SIZE = core_if->core_params->max_transfer_size; ++ const uint32_t MAX_PKT_COUNT = core_if->core_params->max_packet_count; ++ uint32_t num_packets; ++ uint32_t transfer_len; ++ struct dwc_otg_dev_out_ep_regs *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ struct dwc_otg_dev_in_ep_regs *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ union gnptxsts_data txstatus; ++ ++ int lvl = SET_DEBUG_LEVEL(DBG_PCD); ++ ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); ++ ++ transfer_len = ep->xfer_len - ep->xfer_count; ++ if (transfer_len > MAX_XFER_SIZE) ++ transfer_len = MAX_XFER_SIZE; ++ ++ if (transfer_len == 0) { ++ num_packets = 1; ++ /* OUT EP to recieve Zero-length packet set transfer ++ * size to maxpacket size. */ ++ if (!ep->is_in) ++ transfer_len = ep->maxpacket; ++ } else { ++ num_packets = ++ (transfer_len + ep->maxpacket - 1) / ep->maxpacket; ++ if (num_packets > MAX_PKT_COUNT) ++ num_packets = MAX_PKT_COUNT; ++ } ++ DWC_DEBUGPL(DBG_PCD, "transfer_len=%d #pckt=%d\n", transfer_len, ++ num_packets); ++ ++ deptsiz.b.xfersize = transfer_len; ++ deptsiz.b.pktcnt = num_packets; ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); ++ } else { /* OUT endpoint */ ++ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ txstatus.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ if (txstatus.b.nptxqspcavail == 0) { ++ DWC_DEBUGPL(DBG_ANY, "TX Queue Full (0x%0x)\n", ++ txstatus.d32); ++ return; ++ } ++ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ dwc_write_reg32(&in_regs->diepctl, depctl.d32); ++ /* ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (core_if->dma_enable) { ++ dwc_write_reg32(&in_regs->diepdma, ++ (uint32_t) ep->xfer_buff); ++ } else { ++ intr_mask.b.nptxfempty = 1; ++ dwc_modify_reg32(&core_if->core_global_regs->gintsts, ++ intr_mask.d32, 0); ++ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ } else { /* OUT endpoint */ ++ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ dwc_write_reg32(&out_regs->doepctl, depctl.d32); ++ if (core_if->dma_enable) { ++ dwc_write_reg32(&out_regs->doepdma, ++ (uint32_t) ep->xfer_buff); ++ } ++ } ++ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", ++ dwc_read_reg32(&out_regs->doepctl), ++ dwc_read_reg32(&out_regs->doeptsiz)); ++ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", ++ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> ++ daintmsk), ++ dwc_read_reg32(&core_if->core_global_regs->gintmsk)); ++ ++ SET_DEBUG_LEVEL(lvl); ++#endif ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ struct dwc_otg_dev_in_ep_regs *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ union gnptxsts_data txstatus; ++ ++ txstatus.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ if (txstatus.b.nptxqspcavail == 0) { ++#ifdef DEBUG ++ DWC_PRINT("TX Queue Full (0x%0x)\n", txstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); ++ deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); ++ ++ /* Zero Length Packet? */ ++ if (ep->xfer_len == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ++ ep->maxpacket; ++ } ++ ++ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ dwc_write_reg32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ /* ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * the data will be written into the fifo by the ISR. ++ */ ++ intr_mask.b.nptxfempty = 1; ++ dwc_modify_reg32(&core_if->core_global_regs->gintsts, ++ intr_mask.d32, 0); ++ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ dwc_write_reg32(&in_regs->diepctl, depctl.d32); ++ ++ depctl.d32 = ++ dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); ++ depctl.b.nextep = ep->num; ++ dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, ++ depctl.d32); ++ ++ } else { ++ /* OUT endpoint */ ++ struct dwc_otg_dev_out_ep_regs *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); ++ deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); ++ ++ /* Program the transfer size and packet count as follows: ++ * ++ * pktcnt = N ++ * xfersize = N * maxpacket ++ */ ++ if (ep->xfer_len == 0) { ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ++ ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ } ++ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", ++ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ dwc_write_reg32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * @todo NGS: dpid is read-only. Use setd0pid ++ * or setd1pid. ++ */ ++ depctl.b.dpid = ep->even_odd_frame; ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ dwc_write_reg32(&out_regs->doepctl, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", ++ dwc_read_reg32(&out_regs->doepctl), ++ dwc_read_reg32(&out_regs->doeptsiz)); ++ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", ++ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> ++ daintmsk), ++ dwc_read_reg32(&core_if->core_global_regs-> ++ gintmsk)); ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for EP0 and starts ++ * the transfer. For an IN transfer, the packets will be loaded into ++ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are ++ * unloaded from the Rx FIFO in the ISR. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP0 data. ++ */ ++void dwc_otg_ep0_start_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep) ++{ ++ union depctl_data depctl; ++ union deptsiz0_data deptsiz; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p total_len=%d\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, ++ ep->total_len); ++ ep->total_len = ep->xfer_len; ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ struct dwc_otg_dev_in_ep_regs *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ union gnptxsts_data tx_status = {.d32 = 0 }; ++ ++ tx_status.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ if (tx_status.b.nptxqspcavail == 0) { ++#ifdef DEBUG ++ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); ++ DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", ++ dwc_read_reg32(&in_regs->diepctl)); ++ DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", ++ deptsiz.d32, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ DWC_PRINT("TX Queue or FIFO Full (0x%0x)\n", ++ tx_status.d32); ++#endif ++ ++ return; ++ } ++ ++ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); ++ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); ++ ++ /* Zero Length Packet? */ ++ if (ep->xfer_len == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ if (ep->xfer_len > ep->maxpacket) { ++ ep->xfer_len = ep->maxpacket; ++ deptsiz.b.xfersize = ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = ep->xfer_len; ++ } ++ deptsiz.b.pktcnt = 1; ++ ++ } ++ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ dwc_write_reg32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ dwc_write_reg32(&in_regs->diepctl, depctl.d32); ++ ++ /* ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ /* First clear it from GINTSTS */ ++ intr_mask.b.nptxfempty = 1; ++ dwc_modify_reg32(&core_if->core_global_regs->gintsts, ++ intr_mask.d32, 0); ++ ++ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ ++ } else { /* OUT endpoint */ ++ struct dwc_otg_dev_out_ep_regs *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); ++ deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count as follows: ++ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) ++ * pktcnt = N */ ++ if (ep->xfer_len == 0) { ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ++ ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ } ++ ++ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", ++ ep->xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ dwc_write_reg32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ dwc_write_reg32(&(out_regs->doepctl), depctl.d32); ++ } ++} ++ ++/** ++ * This function continues control IN transfers started by ++ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a ++ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one ++ * bit for the packet count. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP0 data. ++ */ ++void dwc_otg_ep0_continue_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep) ++{ ++ union depctl_data depctl; ++ union deptsiz0_data deptsiz; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ ++ if (ep->is_in == 1) { ++ struct dwc_otg_dev_in_ep_regs *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ union gnptxsts_data tx_status = {.d32 = 0 }; ++ ++ tx_status.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ /* ++ * @todo Should there be check for room in the Tx ++ * Status Queue. If not remove the code above this comment. ++ */ ++ ++ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); ++ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); ++ ++ /* ++ * Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ deptsiz.b.pktcnt = 1; ++ ep->xfer_len += deptsiz.b.xfersize; ++ ++ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ dwc_write_reg32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ dwc_write_reg32(&in_regs->diepctl, depctl.d32); ++ ++ /* ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ /* First clear it from GINTSTS */ ++ intr_mask.b.nptxfempty = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, ++ intr_mask.d32); ++ ++ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ ++ } ++ ++} ++ ++#ifdef DEBUG ++void dump_msg(const u8 *buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ start = 0; ++ while (length > 0) { ++ num = min(length, 16u); ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ sprintf(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_PRINT("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 *buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function writes a packet into the Tx FIFO associated with the ++ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For ++ * periodic EPs the periodic Tx FIFO associated with the EP is written ++ * with all packets for the next micro-frame. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP to write packet for. ++ * @_dma: Indicates if DMA is being used. ++ */ ++void dwc_otg_ep_write_packet(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep, ++ int _dma) ++{ ++ /** ++ * The buffer is padded to DWORD on a per packet basis in ++ * slave/dma mode if the MPS is not DWORD aligned. The last ++ * packet, if short, is also padded to a multiple of DWORD. ++ * ++ * ep->xfer_buff always starts DWORD aligned in memory and is a ++ * multiple of DWORD in length ++ * ++ * ep->xfer_len can be any number of bytes ++ * ++ * ep->xfer_count is a multiple of ep->maxpacket until the last ++ * packet ++ * ++ * FIFO access is DWORD */ ++ ++ uint32_t i; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ uint32_t *fifo; ++ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; ++ ++ if (ep->xfer_count >= ep->xfer_len) { ++ DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); ++ return; ++ } ++ ++ /* Find the byte length of the packet either short packet or MPS */ ++ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) ++ byte_count = ep->xfer_len - ep->xfer_count; ++ else ++ byte_count = ep->maxpacket; ++ ++ /* Find the DWORD length, padded by extra bytes as neccessary if MPS ++ * is not a multiple of DWORD */ ++ dword_count = (byte_count + 3) / 4; ++ ++#ifdef VERBOSE ++ dump_msg(ep->xfer_buff, byte_count); ++#endif ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ /* ++ *@todo NGS Where are the Periodic Tx FIFO addresses ++ * intialized? What should this be? ++ */ ++ fifo = core_if->data_fifo[ep->tx_fifo_num]; ++ else ++ fifo = core_if->data_fifo[ep->num]; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", ++ fifo, data_buff, *data_buff, byte_count); ++ ++ if (!_dma) { ++ for (i = 0; i < dword_count; i++, data_buff++) ++ dwc_write_reg32(fifo, *data_buff); ++ } ++ ++ ep->xfer_count += byte_count; ++ ep->xfer_buff += byte_count; ++} ++ ++/** ++ * Set the EP STALL. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP to set the stall on. ++ */ ++void dwc_otg_ep_set_stall(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) ++{ ++ union depctl_data depctl; ++ uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = ++ &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ depctl.d32 = dwc_read_reg32(depctl_addr); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) ++ depctl.b.epdis = 1; ++ depctl.b.stall = 1; ++ dwc_write_reg32(depctl_addr, depctl.d32); ++ ++ } else { ++ depctl_addr = ++ &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ depctl.d32 = dwc_read_reg32(depctl_addr); ++ ++ /* set the stall bit */ ++ depctl.b.stall = 1; ++ dwc_write_reg32(depctl_addr, depctl.d32); ++ } ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); ++ return; ++} ++ ++/** ++ * Clear the EP STALL. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @ep: The EP to clear stall from. ++ */ ++void dwc_otg_ep_clear_stall(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) ++{ ++ union depctl_data depctl; ++ uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = ++ &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ } else { ++ depctl_addr = ++ &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ } ++ ++ depctl.d32 = dwc_read_reg32(depctl_addr); ++ ++ /* clear the stall bits */ ++ depctl.b.stall = 0; ++ ++ /* ++ * USB Spec 9.4.5: For endpoints using data toggle, regardless ++ * of whether an endpoint has the Halt feature set, a ++ * ClearFeature(ENDPOINT_HALT) request always results in the ++ * data toggle being reinitialized to DATA0. ++ */ ++ if (ep->type == DWC_OTG_EP_TYPE_INTR || ++ ep->type == DWC_OTG_EP_TYPE_BULK) { ++ depctl.b.setd0pid = 1; /* DATA0 */ ++ } ++ ++ dwc_write_reg32(depctl_addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); ++ return; ++} ++ ++/** ++ * This function reads a packet from the Rx FIFO into the destination ++ * buffer. To read SETUP data use dwc_otg_read_setup_packet. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @dest: Destination buffer for the packet. ++ * @bytes: Number of bytes to copy to the destination. ++ */ ++void dwc_otg_read_packet(struct dwc_otg_core_if *core_if, ++ uint8_t *dest, uint16_t bytes) ++{ ++ int i; ++ int word_count = (bytes + 3) / 4; ++ ++ uint32_t *fifo = core_if->data_fifo[0]; ++ uint32_t *data_buff = (uint32_t *) dest; ++ ++ /** ++ * @todo Account for the case where dest is not dword aligned. This ++ * requires reading data from the FIFO into a uint32_t temp buffer, ++ * then moving it into the data buffer. ++ */ ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, ++ core_if, dest, bytes); ++ ++ for (i = 0; i < word_count; i++, data_buff++) ++ *data_buff = dwc_read_reg32(fifo); ++ return; ++} ++ ++/** ++ * This functions reads the device registers and prints them ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_dev_registers(struct dwc_otg_core_if *core_if) ++{ ++ int i; ++ uint32_t *addr; ++ ++ DWC_PRINT("Device Global Registers\n"); ++ addr = &core_if->dev_if->dev_global_regs->dcfg; ++ DWC_PRINT("DCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dctl; ++ DWC_PRINT("DCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dsts; ++ DWC_PRINT("DSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->diepmsk; ++ DWC_PRINT("DIEPMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->doepmsk; ++ DWC_PRINT("DOEPMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daint; ++ DWC_PRINT("DAINT @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dtknqr1; ++ DWC_PRINT("DTKNQR1 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr2; ++ DWC_PRINT("DTKNQR2 @%p : 0x%08X\n", ++ addr, dwc_read_reg32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbusdis; ++ DWC_PRINT("DVBUSID @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; ++ DWC_PRINT("DVBUSPULSE @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ ++ if (core_if->hwcfg2.b.dev_token_q_depth > 14) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr3; ++ DWC_PRINT("DTKNQR3 @%p : 0x%08X\n", ++ addr, dwc_read_reg32(addr)); ++ } ++ ++ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4; ++ DWC_PRINT("DTKNQR4 @%p : 0x%08X\n", ++ addr, dwc_read_reg32(addr)); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_eps; i++) { ++ DWC_PRINT("Device IN EP %d Registers\n", i); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; ++ DWC_PRINT("DIEPCTL @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepint; ++ DWC_PRINT("DIEPINT @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; ++ DWC_PRINT("DIETSIZ @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; ++ DWC_PRINT("DIEPDMA @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ ++ DWC_PRINT("Device OUT EP %d Registers\n", i); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; ++ DWC_PRINT("DOEPCTL @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepfn; ++ DWC_PRINT("DOEPFN @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepint; ++ DWC_PRINT("DOEPINT @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; ++ DWC_PRINT("DOETSIZ @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; ++ DWC_PRINT("DOEPDMA @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ } ++ return; ++} ++ ++/** ++ * This function reads the host registers and prints them ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_host_registers(struct dwc_otg_core_if *core_if) ++{ ++ int i; ++ uint32_t *addr; ++ ++ DWC_PRINT("Host Global Registers\n"); ++ addr = &core_if->host_if->host_global_regs->hcfg; ++ DWC_PRINT("HCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfir; ++ DWC_PRINT("HFIR @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfnum; ++ DWC_PRINT("HFNUM @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->host_if->host_global_regs->hptxsts; ++ DWC_PRINT("HPTXSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->host_if->host_global_regs->haint; ++ DWC_PRINT("HAINT @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->host_if->host_global_regs->haintmsk; ++ DWC_PRINT("HAINTMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = core_if->host_if->hprt0; ++ DWC_PRINT("HPRT0 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_PRINT("Host Channel %d Specific Registers\n", i); ++ addr = &core_if->host_if->hc_regs[i]->hcchar; ++ DWC_PRINT("HCCHAR @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcsplt; ++ DWC_PRINT("HCSPLT @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcint; ++ DWC_PRINT("HCINT @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcintmsk; ++ DWC_PRINT("HCINTMSK @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hctsiz; ++ DWC_PRINT("HCTSIZ @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcdma; ++ DWC_PRINT("HCDMA @%p : 0x%08X\n", addr, ++ dwc_read_reg32(addr)); ++ ++ } ++ return; ++} ++ ++/** ++ * This function reads the core global registers and prints them ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_global_registers(struct dwc_otg_core_if *core_if) ++{ ++ int i; ++ uint32_t *addr; ++ ++ DWC_PRINT("Core Global Registers\n"); ++ addr = &core_if->core_global_regs->gotgctl; ++ DWC_PRINT("GOTGCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gotgint; ++ DWC_PRINT("GOTGINT @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gahbcfg; ++ DWC_PRINT("GAHBCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gusbcfg; ++ DWC_PRINT("GUSBCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->grstctl; ++ DWC_PRINT("GRSTCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gintsts; ++ DWC_PRINT("GINTSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gintmsk; ++ DWC_PRINT("GINTMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->grxstsr; ++ DWC_PRINT("GRXSTSR @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->grxfsiz; ++ DWC_PRINT("GRXFSIZ @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gnptxfsiz; ++ DWC_PRINT("GNPTXFSIZ @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gnptxsts; ++ DWC_PRINT("GNPTXSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gi2cctl; ++ DWC_PRINT("GI2CCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gpvndctl; ++ DWC_PRINT("GPVNDCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->ggpio; ++ DWC_PRINT("GGPIO @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->guid; ++ DWC_PRINT("GUID @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->gsnpsid; ++ DWC_PRINT("GSNPSID @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg1; ++ DWC_PRINT("GHWCFG1 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg2; ++ DWC_PRINT("GHWCFG2 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg3; ++ DWC_PRINT("GHWCFG3 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg4; ++ DWC_PRINT("GHWCFG4 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ addr = &core_if->core_global_regs->hptxfsiz; ++ DWC_PRINT("HPTXFSIZ @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ addr = &core_if->core_global_regs->dptxfsiz[i]; ++ DWC_PRINT("DPTXFSIZ[%d] @%p : 0x%08X\n", i, addr, ++ dwc_read_reg32(addr)); ++ } ++ ++} ++ ++/** ++ * Flush a Tx FIFO. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @_num: Tx FIFO to flush. ++ */ ++extern void dwc_otg_flush_tx_fifo(struct dwc_otg_core_if *core_if, const int _num) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ union grstctl_data greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", _num); ++ ++ greset.b.txfflsh = 1; ++ greset.b.txfnum = _num; ++ dwc_write_reg32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", ++ __func__, greset.d32, ++ dwc_read_reg32(&global_regs->gnptxsts)); ++ break; ++ } ++ ++ } while (greset.b.txfflsh == 1); ++ /* Wait for 3 PHY Clocks */ ++ udelay(1); ++} ++ ++/** ++ * Flush Rx FIFO. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++extern void dwc_otg_flush_rx_fifo(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ union grstctl_data greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); ++ /* ++ * ++ */ ++ greset.b.rxfflsh = 1; ++ dwc_write_reg32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ break; ++ } ++ } while (greset.b.rxfflsh == 1); ++ /* Wait for 3 PHY Clocks */ ++ udelay(1); ++} ++ ++/** ++ * Do core a soft reset of the core. Be careful with this because it ++ * resets all the internal state machines of the core. ++ */ ++void dwc_otg_core_reset(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ union grstctl_data greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s\n", __func__); ++ /* Wait for AHB master IDLE state. */ ++ do { ++ udelay(10); ++ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ if (++count > 100000) { ++ DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ return; ++ } ++ } while (greset.b.ahbidle == 0); ++ ++ /* Core Soft Reset */ ++ count = 0; ++ greset.b.csftrst = 1; ++ dwc_write_reg32(&global_regs->grstctl, greset.d32); ++ do { ++ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", ++ __func__, greset.d32); ++ break; ++ } ++ } while (greset.b.csftrst == 1); ++ /* Wait for 3 PHY Clocks */ ++ mdelay(100); ++} ++ ++/** ++ * Register HCD callbacks. The callbacks are used to start and stop ++ * the HCD for interrupt processing. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @_cb: the HCD callback structure. ++ * @_p: pointer to be passed to callback function (usb_hcd*). ++ */ ++extern void dwc_otg_cil_register_hcd_callbacks(struct dwc_otg_core_if *core_if, ++ struct dwc_otg_cil_callbacks *_cb, ++ void *_p) ++{ ++ core_if->hcd_cb = _cb; ++ _cb->p = _p; ++} ++ ++/** ++ * Register PCD callbacks. The callbacks are used to start and stop ++ * the PCD for interrupt processing. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ * @_cb: the PCD callback structure. ++ * @_p: pointer to be passed to callback function (pcd*). ++ */ ++extern void dwc_otg_cil_register_pcd_callbacks(struct dwc_otg_core_if *core_if, ++ struct dwc_otg_cil_callbacks *_cb, ++ void *_p) ++{ ++ core_if->pcd_cb = _cb; ++ _cb->p = _p; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h +new file mode 100644 +index 0000000..36ef561 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h +@@ -0,0 +1,866 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_CIL_H__) ++#define __DWC_CIL_H__ ++ ++#include "dwc_otg_plat.h" ++#include "dwc_otg_regs.h" ++#ifdef DEBUG ++#include "linux/timer.h" ++#endif ++ ++/* ++ * This file contains the interface to the Core Interface Layer. ++ */ ++ ++/** ++ * The dwc_ep structure represents the state of a single ++ * endpoint when acting in device mode. It contains the data items ++ * needed for an endpoint to be activated and transfer packets. ++ */ ++struct dwc_ep { ++ /** EP number used for register address lookup */ ++ uint8_t num; ++ /** EP direction 0 = OUT */ ++ unsigned is_in:1; ++ /** EP active. */ ++ unsigned active:1; ++ ++ /* ++ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use ++ * non-periodic Tx FIFO ++ */ ++ unsigned tx_fifo_num:4; ++ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ ++ unsigned type:2; ++#define DWC_OTG_EP_TYPE_CONTROL 0 ++#define DWC_OTG_EP_TYPE_ISOC 1 ++#define DWC_OTG_EP_TYPE_BULK 2 ++#define DWC_OTG_EP_TYPE_INTR 3 ++ ++ /** DATA start PID for INTR and BULK EP */ ++ unsigned data_pid_start:1; ++ /** Frame (even/odd) for ISOC EP */ ++ unsigned even_odd_frame:1; ++ /** Max Packet bytes */ ++ unsigned maxpacket:11; ++ ++ /** @name Transfer state */ ++ /** @{ */ ++ ++ /** ++ * Pointer to the beginning of the transfer buffer -- do not modify ++ * during transfer. ++ */ ++ ++ uint32_t dma_addr; ++ ++ uint8_t *start_xfer_buff; ++ /** pointer to the transfer buffer */ ++ uint8_t *xfer_buff; ++ /** Number of bytes to transfer */ ++ unsigned xfer_len:19; ++ /** Number of bytes transferred. */ ++ unsigned xfer_count:19; ++ /** Sent ZLP */ ++ unsigned sent_zlp:1; ++ /** Total len for control transfer */ ++ unsigned total_len:19; ++ ++ /** @} */ ++}; ++ ++/* ++ * Reasons for halting a host channel. ++ */ ++enum dwc_otg_halt_status { ++ DWC_OTG_HC_XFER_NO_HALT_STATUS, ++ DWC_OTG_HC_XFER_COMPLETE, ++ DWC_OTG_HC_XFER_URB_COMPLETE, ++ DWC_OTG_HC_XFER_ACK, ++ DWC_OTG_HC_XFER_NAK, ++ DWC_OTG_HC_XFER_NYET, ++ DWC_OTG_HC_XFER_STALL, ++ DWC_OTG_HC_XFER_XACT_ERR, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN, ++ DWC_OTG_HC_XFER_BABBLE_ERR, ++ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR, ++ DWC_OTG_HC_XFER_AHB_ERR, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, ++ DWC_OTG_HC_XFER_URB_DEQUEUE ++}; ++ ++/** ++ * Host channel descriptor. This structure represents the state of a single ++ * host channel when acting in host mode. It contains the data items needed to ++ * transfer packets to an endpoint via a host channel. ++ */ ++struct dwc_hc { ++ /** Host channel number used for register address lookup */ ++ uint8_t hc_num; ++ ++ /** Device to access */ ++ unsigned dev_addr:7; ++ ++ /** EP to access */ ++ unsigned ep_num:4; ++ ++ /** EP direction. 0: OUT, 1: IN */ ++ unsigned ep_is_in:1; ++ ++ /** ++ * EP speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ unsigned speed:2; ++#define DWC_OTG_EP_SPEED_LOW 0 ++#define DWC_OTG_EP_SPEED_FULL 1 ++#define DWC_OTG_EP_SPEED_HIGH 2 ++ ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - DWC_OTG_EP_TYPE_CONTROL: 0 ++ * - DWC_OTG_EP_TYPE_ISOC: 1 ++ * - DWC_OTG_EP_TYPE_BULK: 2 ++ * - DWC_OTG_EP_TYPE_INTR: 3 ++ */ ++ unsigned ep_type:2; ++ ++ /** Max packet size in bytes */ ++ unsigned max_packet:11; ++ ++ /** ++ * PID for initial transaction. ++ * 0: DATA0,
++ * 1: DATA2,
++ * 2: DATA1,
++ * 3: MDATA (non-Control EP), ++ * SETUP (Control EP) ++ */ ++ unsigned data_pid_start:2; ++#define DWC_OTG_HC_PID_DATA0 0 ++#define DWC_OTG_HC_PID_DATA2 1 ++#define DWC_OTG_HC_PID_DATA1 2 ++#define DWC_OTG_HC_PID_MDATA 3 ++#define DWC_OTG_HC_PID_SETUP 3 ++ ++ /** Number of periodic transactions per (micro)frame */ ++ unsigned multi_count:2; ++ ++ /** @name Transfer State */ ++ /** @{ */ ++ ++ /** Pointer to the current transfer buffer position. */ ++ uint8_t *xfer_buff; ++ /** Total number of bytes to transfer. */ ++ uint32_t xfer_len; ++ /** Number of bytes transferred so far. */ ++ uint32_t xfer_count; ++ /** Packet count at start of transfer.*/ ++ uint16_t start_pkt_count; ++ ++ /** ++ * Flag to indicate whether the transfer has been started. Set to 1 if ++ * it has been started, 0 otherwise. ++ */ ++ uint8_t xfer_started; ++ ++ /** ++ * Set to 1 to indicate that a PING request should be issued on this ++ * channel. If 0, process normally. ++ */ ++ uint8_t do_ping; ++ ++ /** ++ * Set to 1 to indicate that the error count for this transaction is ++ * non-zero. Set to 0 if the error count is 0. ++ */ ++ uint8_t error_state; ++ ++ /** ++ * Set to 1 to indicate that this channel should be halted the next ++ * time a request is queued for the channel. This is necessary in ++ * slave mode if no request queue space is available when an attempt ++ * is made to halt the channel. ++ */ ++ uint8_t halt_on_queue; ++ ++ /** ++ * Set to 1 if the host channel has been halted, but the core is not ++ * finished flushing queued requests. Otherwise 0. ++ */ ++ uint8_t halt_pending; ++ ++ /** ++ * Reason for halting the host channel. ++ */ ++ enum dwc_otg_halt_status halt_status; ++ ++ /* ++ * Split settings for the host channel ++ */ ++ uint8_t do_split; /**< Enable split for the channel */ ++ uint8_t complete_split; /**< Enable complete split */ ++ uint8_t hub_addr; /**< Address of high speed hub */ ++ ++ uint8_t port_addr; /**< Port of the low/full speed device */ ++ /** Split transaction position ++ * One of the following values: ++ * - DWC_HCSPLIT_XACTPOS_MID ++ * - DWC_HCSPLIT_XACTPOS_BEGIN ++ * - DWC_HCSPLIT_XACTPOS_END ++ * - DWC_HCSPLIT_XACTPOS_ALL */ ++ uint8_t xact_pos; ++ ++ /** Set when the host channel does a short read. */ ++ uint8_t short_read; ++ ++ /** ++ * Number of requests issued for this channel since it was assigned to ++ * the current transfer (not counting PINGs). ++ */ ++ uint8_t requests; ++ ++ /** ++ * Queue Head for the transfer being processed by this channel. ++ */ ++ struct dwc_otg_qh *qh; ++ ++ /** @} */ ++ ++ /** Entry in list of host channels. */ ++ struct list_head hc_list_entry; ++}; ++ ++/** ++ * The following parameters may be specified when starting the module. These ++ * parameters define how the DWC_otg controller should be configured. ++ * Parameter values are passed to the CIL initialization function ++ * dwc_otg_cil_init. ++ */ ++struct dwc_otg_core_params { ++ int32_t opt; ++#define dwc_param_opt_default 1 ++ ++ /* ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++ int32_t otg_cap; ++#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0 ++#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1 ++#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 ++#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ++ ++ /* ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++ int32_t dma_enable; ++#define dwc_param_dma_enable_default 1 ++ ++ /* ++ * The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++ int32_t dma_burst_size; /* Translate this to GAHBCFG values */ ++#define dwc_param_dma_burst_size_default 32 ++ ++ /* ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++ int32_t speed; ++#define dwc_param_speed_default 0 ++#define DWC_SPEED_PARAM_HIGH 0 ++#define DWC_SPEED_PARAM_FULL 1 ++ ++ /** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++ int32_t host_support_fs_ls_low_power; ++#define dwc_param_host_support_fs_ls_low_power_default 0 ++ ++ /** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++ int32_t host_ls_low_power_phy_clk; ++#define dwc_param_host_ls_low_power_phy_clk_default 0 ++#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 ++#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 ++ ++ /** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++ int32_t enable_dynamic_fifo; ++#define dwc_param_enable_dynamic_fifo_default 1 ++ ++ /** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++ int32_t data_fifo_size; ++#define dwc_param_data_fifo_size_default 8192 ++ ++ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++ int32_t dev_rx_fifo_size; ++#define dwc_param_dev_rx_fifo_size_default 1064 ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t dev_nperio_tx_fifo_size; ++#define dwc_param_dev_nperio_tx_fifo_size_default 1024 ++ ++ /** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++#define dwc_param_dev_perio_tx_fifo_size_default 256 ++ ++ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_rx_fifo_size; ++#define dwc_param_host_rx_fifo_size_default 1024 ++#define dwc_param_host_rx_fifo_size_percentage 30 ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_nperio_tx_fifo_size; ++#define dwc_param_host_nperio_tx_fifo_size_default 1024 ++#define dwc_param_host_nperio_tx_fifo_size_percentage 40 ++ ++ /* ++ * Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_perio_tx_fifo_size; ++#define dwc_param_host_perio_tx_fifo_size_default 1024 ++#define dwc_param_host_perio_tx_fifo_size_percentage 30 ++ ++ /* ++ * The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++ int32_t max_transfer_size; ++#define dwc_param_max_transfer_size_default 65535 ++ ++ /* ++ * The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++ int32_t max_packet_count; ++#define dwc_param_max_packet_count_default 511 ++ ++ /* ++ * The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++ int32_t host_channels; ++#define dwc_param_host_channels_default 12 ++ ++ /* ++ * The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++ int32_t dev_endpoints; ++#define dwc_param_dev_endpoints_default 6 ++ ++ /* ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++ int32_t phy_type; ++#define DWC_PHY_TYPE_PARAM_FS 0 ++#define DWC_PHY_TYPE_PARAM_UTMI 1 ++#define DWC_PHY_TYPE_PARAM_ULPI 2 ++#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI ++ ++ /* ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++ int32_t phy_utmi_width; ++#define dwc_param_phy_utmi_width_default 16 ++ ++ /* ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++ int32_t phy_ulpi_ddr; ++#define dwc_param_phy_ulpi_ddr_default 0 ++ ++ /* ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++ int32_t phy_ulpi_ext_vbus; ++#define DWC_PHY_ULPI_INTERNAL_VBUS 0 ++#define DWC_PHY_ULPI_EXTERNAL_VBUS 1 ++#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS ++ ++ /* ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++ int32_t i2c_enable; ++#define dwc_param_i2c_enable_default 0 ++ ++ int32_t ulpi_fs_ls; ++#define dwc_param_ulpi_fs_ls_default 0 ++ ++ int32_t ts_dline; ++#define dwc_param_ts_dline_default 0 ++ ++}; ++ ++/** ++ * The FIFOs are established based on a default percentage of the total ++ * FIFO depth. This check insures that the defaults are reasonable. ++ */ ++#if (((dwc_param_host_rx_fifo_size_percentage) \ ++ +(dwc_param_host_nperio_tx_fifo_size_percentage) \ ++ +(dwc_param_host_perio_tx_fifo_size_percentage)) > 100) ++#error Invalid FIFO allocation ++#endif ++ ++#ifdef DEBUG ++struct dwc_otg_core_if; ++struct hc_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ struct dwc_hc *hc; ++}; ++#endif ++ ++/* ++ * The dwc_otg_core_if structure contains information ++ * needed to manage the DWC_otg controller acting in either host or ++ * device mode. It represents the programming view of the controller ++ * as a whole. ++ */ ++struct dwc_otg_core_if { ++ /** USB block index number for Octeon's that support multiple */ ++ int usb_num; ++ ++ /** Parameters that define how the core should be configured.*/ ++ struct dwc_otg_core_params *core_params; ++ ++ /** Core Global registers starting at offset 000h. */ ++ struct dwc_otg_core_global_regs *core_global_regs; ++ ++ /** Device-specific information */ ++ struct dwc_otg_dev_if *dev_if; ++ /** Host-specific information */ ++ struct dwc_otg_host_if *host_if; ++ ++ /* ++ * Set to 1 if the core PHY interface bits in USBCFG have been ++ * initialized. ++ */ ++ uint8_t phy_init_done; ++ ++ /* ++ * SRP Success flag, set by srp success interrupt in FS I2C mode ++ */ ++ uint8_t srp_success; ++ uint8_t srp_timer_started; ++ ++ /* Common configuration information */ ++ /** Power and Clock Gating Control Register */ ++ uint32_t *pcgcctl; ++#define DWC_OTG_PCGCCTL_OFFSET 0xE00 ++ ++ /** Push/pop addresses for endpoints or host channels.*/ ++ uint32_t *data_fifo[MAX_EPS_CHANNELS]; ++#define DWC_OTG_DATA_FIFO_OFFSET 0x1000 ++#define DWC_OTG_DATA_FIFO_SIZE 0x1000 ++ ++ /** Total RAM for FIFOs (Bytes) */ ++ uint16_t total_fifo_size; ++ /** Size of Rx FIFO (Bytes) */ ++ uint16_t rx_fifo_size; ++ /** Size of Non-periodic Tx FIFO (Bytes) */ ++ uint16_t nperio_tx_fifo_size; ++ ++ /** 1 if DMA is enabled, 0 otherwise. */ ++ uint8_t dma_enable; ++ ++ /** Set to 1 if multiple packets of a high-bandwidth transfer is in ++ * process of being queued */ ++ uint8_t queuing_high_bandwidth; ++ ++ /** Hardware Configuration -- stored here for convenience.*/ ++ union hwcfg1_data hwcfg1; ++ union hwcfg2_data hwcfg2; ++ union hwcfg3_data hwcfg3; ++ union hwcfg4_data hwcfg4; ++ ++ /* ++ * The operational State, during transations ++ * (a_host>>a_peripherial and b_device=>b_host) this may not ++ * match the core but allows the software to determine ++ * transitions. ++ */ ++ uint8_t op_state; ++ ++ /* ++ * Set to 1 if the HCD needs to be restarted on a session request ++ * interrupt. This is required if no connector ID status change has ++ * occurred since the HCD was last disconnected. ++ */ ++ uint8_t restart_hcd_on_session_req; ++ ++ /** HCD callbacks */ ++ /** A-Device is a_host */ ++#define A_HOST (1) ++ /** A-Device is a_suspend */ ++#define A_SUSPEND (2) ++ /** A-Device is a_peripherial */ ++#define A_PERIPHERAL (3) ++ /** B-Device is operating as a Peripheral. */ ++#define B_PERIPHERAL (4) ++ /** B-Device is operating as a Host. */ ++#define B_HOST (5) ++ ++ /** HCD callbacks */ ++ struct dwc_otg_cil_callbacks *hcd_cb; ++ /** PCD callbacks */ ++ struct dwc_otg_cil_callbacks *pcd_cb; ++ ++#ifdef DEBUG ++ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; ++ ++ struct hc_xfer_info hc_xfer_info[MAX_EPS_CHANNELS]; ++ struct timer_list hc_xfer_timer[MAX_EPS_CHANNELS]; ++ ++ uint32_t hfnum_7_samples; ++ uint64_t hfnum_7_frrem_accum; ++ uint32_t hfnum_0_samples; ++ uint64_t hfnum_0_frrem_accum; ++ uint32_t hfnum_other_samples; ++ uint64_t hfnum_other_frrem_accum; ++#endif ++ ++}; ++ ++/* ++ * The following functions support initialization of the CIL driver component ++ * and the DWC_otg controller. ++ */ ++extern struct dwc_otg_core_if *dwc_otg_cil_init(const uint32_t *reg_base_addr, ++ struct dwc_otg_core_params * ++ _core_params); ++extern void dwc_otg_cil_remove(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_core_init(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_core_host_init(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_core_dev_init(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_enable_global_interrupts(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_disable_global_interrupts(struct dwc_otg_core_if *core_if); ++ ++/* Device CIL Functions ++ * The following functions support managing the DWC_otg controller in device ++ * mode. ++ */ ++ ++extern void dwc_otg_wakeup(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_read_setup_packet(struct dwc_otg_core_if *core_if, ++ uint32_t *dest); ++extern uint32_t dwc_otg_get_frame_number(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_ep0_activate(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep_activate(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep_deactivate(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep_start_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep0_start_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep0_continue_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep_write_packet(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep, int _dma); ++extern void dwc_otg_ep_set_stall(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_ep_clear_stall(struct dwc_otg_core_if *core_if, ++ struct dwc_ep *ep); ++extern void dwc_otg_enable_device_interrupts(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_dump_dev_registers(struct dwc_otg_core_if *core_if); ++ ++/* Host CIL Functions ++ * The following functions support managing the DWC_otg controller in host ++ * mode. ++ */ ++ ++extern void dwc_otg_hc_init(struct dwc_otg_core_if *core_if, struct dwc_hc *hc); ++extern void dwc_otg_hc_halt(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc, ++ enum dwc_otg_halt_status halt_status); ++extern void dwc_otg_hc_cleanup(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc); ++extern void dwc_otg_hc_start_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc); ++extern int dwc_otg_hc_continue_transfer(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc); ++extern void dwc_otg_hc_do_ping(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc); ++extern void dwc_otg_hc_write_packet(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc); ++extern void dwc_otg_enable_host_interrupts(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_disable_host_interrupts(struct dwc_otg_core_if *core_if); ++ ++/** ++ * This function Reads HPRT0 in preparation to modify. It keeps the ++ * WC bits 0 so that if they are read as 1, they won't clear when you ++ * write it back ++ */ ++static inline uint32_t dwc_otg_read_hprt0(struct dwc_otg_core_if *core_if) ++{ ++ union hprt0_data hprt0; ++ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.b.prtena = 0; ++ hprt0.b.prtconndet = 0; ++ hprt0.b.prtenchng = 0; ++ hprt0.b.prtovrcurrchng = 0; ++ return hprt0.d32; ++} ++ ++extern void dwc_otg_dump_host_registers(struct dwc_otg_core_if *core_if); ++ ++/* Common CIL Functions ++ * The following functions support managing the DWC_otg controller in either ++ * device or host mode. ++ */ ++ ++ ++extern void dwc_otg_read_packet(struct dwc_otg_core_if *core_if, ++ uint8_t *dest, uint16_t bytes); ++ ++extern void dwc_otg_dump_global_registers(struct dwc_otg_core_if *core_if); ++ ++extern void dwc_otg_flush_tx_fifo(struct dwc_otg_core_if *core_if, ++ const int _num); ++extern void dwc_otg_flush_rx_fifo(struct dwc_otg_core_if *core_if); ++extern void dwc_otg_core_reset(struct dwc_otg_core_if *core_if); ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_core_intr(struct dwc_otg_core_if *core_if) ++{ ++ return dwc_read_reg32(&core_if->core_global_regs->gintsts) & ++ dwc_read_reg32(&core_if->core_global_regs->gintmsk); ++} ++ ++/** ++ * This function returns the OTG Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_otg_intr(struct dwc_otg_core_if *core_if) ++{ ++ return dwc_read_reg32(&core_if->core_global_regs->gotgint); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the IN endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(struct dwc_otg_core_if * ++ core_if) ++{ ++ uint32_t v; ++ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & ++ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); ++ return v & 0xffff; ++ ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the OUT endpoint interrupt bits. ++ */ ++static inline uint32_t ++dwc_otg_read_dev_all_out_ep_intr(struct dwc_otg_core_if *core_if) ++{ ++ uint32_t v; ++ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & ++ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); ++ return (v & 0xffff0000) >> 16; ++} ++ ++/** ++ * This function returns the Device IN EP Interrupt register ++ */ ++static inline uint32_t ++dwc_otg_read_dev_in_ep_intr(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) ++{ ++ struct dwc_otg_dev_if *dev_if = core_if->dev_if; ++ uint32_t v; ++ v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & ++ dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); ++ return v; ++} ++ ++/** ++ * This function returns the Device OUT EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_out_ep_intr(struct dwc_otg_core_if * ++ core_if, struct dwc_ep *ep) ++{ ++ struct dwc_otg_dev_if *dev_if = core_if->dev_if; ++ uint32_t v; ++ v = dwc_read_reg32(&dev_if->out_ep_regs[ep->num]->doepint) & ++ dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); ++ return v; ++} ++ ++/** ++ * This function returns the Host All Channel Interrupt register ++ */ ++static inline uint32_t ++dwc_otg_read_host_all_channels_intr(struct dwc_otg_core_if *core_if) ++{ ++ return dwc_read_reg32(&core_if->host_if->host_global_regs->haint); ++} ++ ++static inline uint32_t ++dwc_otg_read_host_channel_intr(struct dwc_otg_core_if *core_if, ++ struct dwc_hc *hc) ++{ ++ return dwc_read_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcint); ++} ++ ++/** ++ * This function returns the mode of the operation, host or device. ++ * ++ * Returns 0 - Device Mode, 1 - Host Mode ++ */ ++static inline uint32_t dwc_otg_mode(struct dwc_otg_core_if *core_if) ++{ ++ return dwc_read_reg32(&core_if->core_global_regs->gintsts) & 0x1; ++} ++ ++static inline uint8_t dwc_otg_is_device_mode(struct dwc_otg_core_if *core_if) ++{ ++ return dwc_otg_mode(core_if) != DWC_HOST_MODE; ++} ++ ++static inline uint8_t dwc_otg_is_host_mode(struct dwc_otg_core_if *core_if) ++{ ++ return dwc_otg_mode(core_if) == DWC_HOST_MODE; ++} ++ ++extern int32_t dwc_otg_handle_common_intr(struct dwc_otg_core_if *core_if); ++ ++/* ++ * DWC_otg CIL callback structure. This structure allows the HCD and ++ * PCD to register functions used for starting and stopping the PCD ++ * and HCD for role change on for a DRD. ++ */ ++struct dwc_otg_cil_callbacks { ++ /* Start function for role change */ ++ int (*start) (void *p); ++ /* Stop Function for role change */ ++ int (*stop) (void *p); ++ /* Disconnect Function for role change */ ++ int (*disconnect) (void *p); ++ /* Resume/Remote wakeup Function */ ++ int (*resume_wakeup) (void *p); ++ /* Suspend function */ ++ int (*suspend) (void *p); ++ /* Session Start (SRP) */ ++ int (*session_start) (void *p); ++ /* Pointer passed to start() and stop() */ ++ void *p; ++}; ++ ++extern void dwc_otg_cil_register_pcd_callbacks(struct dwc_otg_core_if *core_if, ++ struct dwc_otg_cil_callbacks *cb, ++ void *p); ++extern void dwc_otg_cil_register_hcd_callbacks(struct dwc_otg_core_if *core_if, ++ struct dwc_otg_cil_callbacks *cb, ++ void *p); ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +new file mode 100644 +index 0000000..38c46df +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +@@ -0,0 +1,689 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/** ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * This file contains the Common Interrupt handlers. ++ */ ++#include "dwc_otg_plat.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++ ++#ifdef DEBUG ++inline const char *op_state_str(struct dwc_otg_core_if *core_if) ++{ ++ return (core_if->op_state == A_HOST ? "a_host" : ++ (core_if->op_state == A_SUSPEND ? "a_suspend" : ++ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : ++ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : ++ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); ++} ++#endif ++ ++/** This function will log a debug message ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_mode_mismatch_intr(struct dwc_otg_core_if *core_if) ++{ ++ union gintsts_data gintsts; ++ DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", ++ dwc_otg_mode(core_if) ? "Host" : "Device"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.modemismatch = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** Start the HCD. Helper function for using the HCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void hcd_start(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->start) ++ core_if->hcd_cb->start(core_if->hcd_cb->p); ++} ++ ++/** Stop the HCD. Helper function for using the HCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void hcd_stop(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->stop) ++ core_if->hcd_cb->stop(core_if->hcd_cb->p); ++} ++ ++/** Disconnect the HCD. Helper function for using the HCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void hcd_disconnect(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) ++ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); ++} ++ ++/** Inform the HCD the a New Session has begun. Helper function for ++ * using the HCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void hcd_session_start(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->session_start) ++ core_if->hcd_cb->session_start(core_if->hcd_cb->p); ++} ++ ++/** Start the PCD. Helper function for using the PCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void pcd_start(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->start) ++ core_if->pcd_cb->start(core_if->pcd_cb->p); ++} ++ ++/** Stop the PCD. Helper function for using the PCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void pcd_stop(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->stop) ++ core_if->pcd_cb->stop(core_if->pcd_cb->p); ++} ++ ++/** Suspend the PCD. Helper function for using the PCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void pcd_suspend(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->suspend) ++ core_if->pcd_cb->suspend(core_if->pcd_cb->p); ++} ++ ++/** Resume the PCD. Helper function for using the PCD callbacks. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++static inline void pcd_resume(struct dwc_otg_core_if *core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++} ++ ++/** ++ * This function handles the OTG Interrupts. It reads the OTG ++ * Interrupt Register (GOTGINT) to determine what interrupt has ++ * occurred. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_otg_intr(struct dwc_otg_core_if *core_if) ++{ ++ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; ++ union gotgint_data gotgint; ++ union gotgctl_data gotgctl; ++ union gintmsk_data gintmsk; ++ ++ gotgint.d32 = dwc_read_reg32(&global_regs->gotgint); ++ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, ++ op_state_str(core_if)); ++ ++ if (gotgint.b.sesenddet) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session End Detected++ (%s)\n", ++ op_state_str(core_if)); ++ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ ++ if (core_if->op_state == B_HOST) { ++ pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ /* If not B_HOST and Device HNP still set. HNP ++ * Did not succeed!*/ ++ if (gotgctl.b.devhnpen) { ++ DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); ++ DWC_ERROR("Device Not Connected/Responding!\n"); ++ } ++ ++ /* If Session End Detected the B-Cable has ++ * been disconnected. */ ++ /* Reset PCD and Gadget driver to a ++ * clean state. */ ++ pcd_stop(core_if); ++ } ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ if (gotgint.b.sesreqsucstschng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session Reqeust Success Status Change++\n"); ++ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) { ++ if ((core_if->core_params->phy_type == ++ DWC_PHY_TYPE_PARAM_FS) ++ && (core_if->core_params->i2c_enable)) { ++ core_if->srp_success = 1; ++ } else { ++ pcd_resume(core_if); ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ dwc_modify_reg32(&global_regs->gotgctl, ++ gotgctl.d32, 0); ++ } ++ } ++ } ++ if (gotgint.b.hstnegsucstschng) { ++ /* Print statements during the HNP interrupt handling ++ * can cause it to fail.*/ ++ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ if (gotgctl.b.hstnegscs) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ core_if->op_state = B_HOST; ++ /* ++ * Need to disable SOF interrupt immediately. ++ * When switching from device to host, the PCD ++ * interrupt handler won't handle the ++ * interrupt if host mode is already set. The ++ * HCD interrupt handler won't get called if ++ * the HCD state is HALT. This means that the ++ * interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ dwc_modify_reg32(&global_regs->gintmsk, ++ gintmsk.d32, 0); ++ pcd_stop(core_if); ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ hcd_start(core_if); ++ core_if->op_state = B_HOST; ++ } ++ } else { ++ gotgctl.d32 = 0; ++ gotgctl.b.hnpreq = 1; ++ gotgctl.b.devhnpen = 1; ++ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); ++ DWC_ERROR("Device Not Connected/Responding\n"); ++ } ++ } ++ if (gotgint.b.hstnegdet) { ++ /* The disconnect interrupt is set at the same time as ++ * Host Negotiation Detected. During the mode ++ * switch all interrupts are cleared so the disconnect ++ * interrupt handler will not get executed. ++ */ ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Host Negotiation Detected++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Device")); ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", ++ core_if->op_state); ++ hcd_disconnect(core_if); ++ pcd_start(core_if); ++ core_if->op_state = A_PERIPHERAL; ++ } else { ++ /* ++ * Need to disable SOF interrupt immediately. When ++ * switching from device to host, the PCD interrupt ++ * handler won't handle the interrupt if host mode is ++ * already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that ++ * the interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); ++ pcd_stop(core_if); ++ hcd_start(core_if); ++ core_if->op_state = A_HOST; ++ } ++ } ++ if (gotgint.b.adevtoutchng) ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "A-Device Timeout Change++\n"); ++ if (gotgint.b.debdone) ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); ++ ++ /* Clear GOTGINT */ ++ dwc_write_reg32(&core_if->core_global_regs->gotgint, gotgint.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Connector ID Status Change Interrupt. It ++ * reads the OTG Interrupt Register (GOTCTL) to determine whether this ++ * is a Device to Host Mode transition or a Host Mode to Device ++ * Transition. ++ * ++ * This only occurs when the cable is connected/removed from the PHY ++ * connector. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_conn_id_status_change_intr(struct dwc_otg_core_if *core_if) ++{ ++ uint32_t count = 0; ++ ++ union gintsts_data gintsts = {.d32 = 0 }; ++ union gintmsk_data gintmsk = {.d32 = 0 }; ++ union gotgctl_data gotgctl = {.d32 = 0 }; ++ ++ /* ++ * Need to disable SOF interrupt immediately. If switching from device ++ * to host, the PCD interrupt handler won't handle the interrupt if ++ * host mode is already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that the interrupt does ++ * not get handled and Linux complains loudly. ++ */ ++ gintmsk.b.sofintr = 1; ++ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ " ++Connector ID Status Change Interrupt++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); ++ gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); ++ ++ /* B-Device connector (Device Mode) */ ++ if (gotgctl.b.conidsts) { ++ /* Wait for switch to device mode. */ ++ while (!dwc_otg_is_device_mode(core_if)) { ++ DWC_PRINT("Waiting for Peripheral Mode, Mode=%s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ mdelay(100); ++ if (++count > 10000) ++ *(uint32_t *) NULL = 0; ++ } ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ pcd_start(core_if); ++ } else { ++ /* A-Device connector (Host Mode) */ ++ while (!dwc_otg_is_host_mode(core_if)) { ++ DWC_PRINT("Waiting for Host Mode, Mode=%s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ mdelay(100); ++ if (++count > 10000) ++ *(uint32_t *) NULL = 0; ++ } ++ core_if->op_state = A_HOST; ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ hcd_start(core_if); ++ } ++ ++ /* Set flag and clear interrupt */ ++ gintsts.b.conidstschng = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device is initiating the Session ++ * Request Protocol to request the host to turn on bus power so a new ++ * session can begin. The handler responds by turning on bus power. If ++ * the DWC_otg controller is in low power mode, the handler brings the ++ * controller out of low power mode before turning on bus power. ++ * ++ * @core_if: Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_session_req_intr(struct dwc_otg_core_if *core_if) ++{ ++ union gintsts_data gintsts; ++#ifndef DWC_HOST_ONLY ++ union hprt0_data hprt0; ++ ++ DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_PRINT("SRP: Device mode\n"); ++ } else { ++ DWC_PRINT("SRP: Host mode\n"); ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ hcd_session_start(core_if); ++ } ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sessreqintr = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the DWC_otg controller has detected a ++ * resume or remote wakeup sequence. If the DWC_otg controller is in ++ * low power mode, the handler must brings the controller out of low ++ * power mode. The controller automatically begins resume ++ * signaling. The handler schedules a time to stop resume signaling. ++ */ ++int32_t dwc_otg_handle_wakeup_detected_intr(struct dwc_otg_core_if *core_if) ++{ ++ union gintsts_data gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "++Resume and Remote Wakeup Detected Interrupt++\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ union dctl_data dctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", ++ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> ++ dsts)); ++#ifdef PARTIAL_POWER_DOWN ++ if (core_if->hwcfg4.b.power_optimiz) { ++ union pcgcctl_data power = {.d32 = 0 }; ++ ++ power.d32 = dwc_read_reg32(core_if->pcgcctl); ++ DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", power.d32); ++ ++ power.b.stoppclk = 0; ++ dwc_write_reg32(core_if->pcgcctl, power.d32); ++ ++ power.b.pwrclmp = 0; ++ dwc_write_reg32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 0; ++ dwc_write_reg32(core_if->pcgcctl, power.d32); ++ } ++#endif ++ /* Clear the Remote Wakeup Signalling */ ++ dctl.b.rmtwkupsig = 1; ++ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32, 0); ++ ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } else { ++ /* ++ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms ++ * so that OPT tests pass with all PHYs). ++ */ ++ union hprt0_data hprt0 = {.d32 = 0 }; ++ union pcgcctl_data pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); ++ udelay(10); ++ ++ /* Now wait for 70 ms. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); ++ mdelay(70); ++ hprt0.b.prtres = 0; /* Resume */ ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", ++ dwc_read_reg32(core_if->host_if->hprt0)); ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.wkupintr = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device has been disconnected from ++ * the root port. ++ */ ++int32_t dwc_otg_handle_disconnect_intr(struct dwc_otg_core_if *core_if) ++{ ++ union gintsts_data gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"), ++ op_state_str(core_if)); ++ ++/** @todo Consolidate this if statement. */ ++#ifndef DWC_HOST_ONLY ++ if (core_if->op_state == B_HOST) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ hcd_disconnect(core_if); ++ pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else if (dwc_otg_is_device_mode(core_if)) { ++ union gotgctl_data gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = ++ dwc_read_reg32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.hstsethnpen == 1) { ++ /* Do nothing, if HNP in process the OTG ++ * interrupt "Host Negotiation Detected" ++ * interrupt will do the mode switch. ++ */ ++ } else if (gotgctl.b.devhnpen == 0) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ hcd_disconnect(core_if); ++ pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); ++ } ++ } else { ++ if (core_if->op_state == A_HOST) { ++ /* A-Cable still connected but device disconnected. */ ++ hcd_disconnect(core_if); ++ } ++ } ++#endif ++ ++ gintsts.d32 = 0; ++ gintsts.b.disconnect = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that SUSPEND state has been detected on ++ * the USB. ++ * ++ * For HNP the USB Suspend interrupt signals the change from ++ * "a_peripheral" to "a_host". ++ * ++ * When power management is enabled the core will be put in low power ++ * mode. ++ */ ++int32_t dwc_otg_handle_usb_suspend_intr(struct dwc_otg_core_if *core_if) ++{ ++ union dsts_data dsts; ++ union gintsts_data gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ /* Check the Device status register to determine if the Suspend ++ * state is active. */ ++ dsts.d32 = ++ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); ++ DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " ++ "HWCFG4.power Optimize=%d\n", ++ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); ++ ++#ifdef PARTIAL_POWER_DOWN ++/** @todo Add a module parameter for power management. */ ++ ++ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { ++ union pcgcctl_data_t power = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_CIL, "suspend\n"); ++ ++ power.b.pwrclmp = 1; ++ dwc_write_reg32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 1; ++ dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); ++ ++ power.b.stoppclk = 1; ++ dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); ++ ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); ++ } ++#endif ++ /* PCD callback for suspend. */ ++ pcd_suspend(core_if); ++ } else { ++ if (core_if->op_state == A_PERIPHERAL) { ++ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ pcd_stop(core_if); ++ hcd_start(core_if); ++ core_if->op_state = A_HOST; ++ } ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_common_intr(struct dwc_otg_core_if *core_if) ++{ ++ union gintsts_data gintsts; ++ union gintmsk_data gintmsk; ++ union gintmsk_data gintmsk_common = {.d32 = 0 }; ++ gintmsk_common.b.wkupintr = 1; ++ gintmsk_common.b.sessreqintr = 1; ++ gintmsk_common.b.conidstschng = 1; ++ gintmsk_common.b.otgintr = 1; ++ gintmsk_common.b.modemismatch = 1; ++ gintmsk_common.b.disconnect = 1; ++ gintmsk_common.b.usbsuspend = 1; ++ /* ++ * @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ ++ gintsts.d32 = dwc_read_reg32(&core_if->core_global_regs->gintsts); ++ gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk); ++#ifdef DEBUG ++ /* if any common interrupts set */ ++ if (gintsts.d32 & gintmsk_common.d32) { ++ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", ++ gintsts.d32, gintmsk.d32); ++ } ++#endif ++ ++ return (gintsts.d32 & gintmsk.d32) & gintmsk_common.d32; ++ ++} ++ ++/** ++ * Common interrupt handler. ++ * ++ * The common interrupts are those that occur in both Host and Device mode. ++ * This handler handles the following interrupts: ++ * - Mode Mismatch Interrupt ++ * - Disconnect Interrupt ++ * - OTG Interrupt ++ * - Connector ID Status Change Interrupt ++ * - Session Request Interrupt. ++ * - Resume / Remote Wakeup Detected Interrupt. ++ * ++ */ ++extern int32_t dwc_otg_handle_common_intr(struct dwc_otg_core_if *core_if) ++{ ++ int retval = 0; ++ union gintsts_data gintsts; ++ ++ gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ ++ if (gintsts.b.modemismatch) ++ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); ++ if (gintsts.b.otgintr) ++ retval |= dwc_otg_handle_otg_intr(core_if); ++ if (gintsts.b.conidstschng) ++ retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); ++ if (gintsts.b.disconnect) ++ retval |= dwc_otg_handle_disconnect_intr(core_if); ++ if (gintsts.b.sessreqintr) ++ retval |= dwc_otg_handle_session_req_intr(core_if); ++ if (gintsts.b.wkupintr) ++ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); ++ if (gintsts.b.usbsuspend) ++ retval |= dwc_otg_handle_usb_suspend_intr(core_if); ++ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { ++ /* The port interrupt occurs while in device mode with HPRT0 ++ * Port Enable/Disable. ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.portintr = 1; ++ dwc_write_reg32(&core_if->core_global_regs->gintsts, ++ gintsts.d32); ++ retval |= 1; ++ ++ } ++ return retval; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h +new file mode 100644 +index 0000000..1cc116d +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h +@@ -0,0 +1,63 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __DWC_OTG_DRIVER_H__ ++#define __DWC_OTG_DRIVER_H__ ++ ++#include "dwc_otg_cil.h" ++ ++/* Type declarations */ ++struct dwc_otg_pcd; ++struct dwc_otg_hcd; ++ ++/** ++ * This structure is a wrapper that encapsulates the driver components used to ++ * manage a single DWC_otg controller. ++ */ ++struct dwc_otg_device { ++ /** Base address returned from ioremap() */ ++ void *base; ++ ++ /** Pointer to the core interface structure. */ ++ struct dwc_otg_core_if *core_if; ++ ++ /** Register offset for Diagnostic API.*/ ++ uint32_t reg_offset; ++ ++ /** Pointer to the PCD structure. */ ++ struct dwc_otg_pcd *pcd; ++ ++ /** Pointer to the HCD structure. */ ++ struct dwc_otg_hcd *hcd; ++ ++ /** Flag to indicate whether the common IRQ handler is installed. */ ++ uint8_t common_irq_installed; ++ ++}; ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +new file mode 100644 +index 0000000..a4392f5 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -0,0 +1,2878 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef DWC_DEVICE_ONLY ++ ++/** ++ * ++ * This file contains the implementation of the HCD. In Linux, the HCD ++ * implements the hc_driver API. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dwc_otg_driver.h" ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; ++ ++static const struct hc_driver dwc_otg_hc_driver = { ++ ++ .description = dwc_otg_hcd_name, ++ .product_desc = "DWC OTG Controller", ++ .hcd_priv_size = sizeof(struct dwc_otg_hcd), ++ ++ .irq = dwc_otg_hcd_irq, ++ ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ .start = dwc_otg_hcd_start, ++ .stop = dwc_otg_hcd_stop, ++ ++ .urb_enqueue = dwc_otg_hcd_urb_enqueue, ++ .urb_dequeue = dwc_otg_hcd_urb_dequeue, ++ .endpoint_disable = dwc_otg_hcd_endpoint_disable, ++ ++ .get_frame_number = dwc_otg_hcd_get_frame_number, ++ ++ .hub_status_data = dwc_otg_hcd_hub_status_data, ++ .hub_control = dwc_otg_hcd_hub_control, ++}; ++ ++/** ++ * Work queue function for starting the HCD when A-Cable is connected. ++ * The dwc_otg_hcd_start() must be called in a process context. ++ */ ++static void hcd_start_func(struct work_struct *work) ++{ ++ void *_vp = ++ (void *)(atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK); ++ struct usb_hcd *usb_hcd = (struct usb_hcd *)_vp; ++ DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, usb_hcd); ++ if (usb_hcd) ++ dwc_otg_hcd_start(usb_hcd); ++} ++ ++/** ++ * HCD Callback function for starting the HCD when A-Cable is ++ * connected. ++ * ++ * @_p: void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_start_cb(void *_p) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); ++ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; ++ union hprt0_data hprt0; ++ ++ if (core_if->op_state == B_HOST) { ++ /* ++ * Reset the port. During a HNP mode switch the reset ++ * needs to occur within 1ms and have a duration of at ++ * least 50ms. ++ */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ ((struct usb_hcd *)_p)->self.is_b_host = 1; ++ } else { ++ ((struct usb_hcd *)_p)->self.is_b_host = 0; ++ } ++ ++ /* Need to start the HCD in a non-interrupt context. */ ++ INIT_WORK(&dwc_otg_hcd->start_work, hcd_start_func); ++ atomic_long_set(&dwc_otg_hcd->start_work.data, (long)_p); ++ schedule_work(&dwc_otg_hcd->start_work); ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for stopping the HCD. ++ * ++ * @_p: void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_stop_cb(void *_p) ++{ ++ struct usb_hcd *usb_hcd = (struct usb_hcd *)_p; ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); ++ dwc_otg_hcd_stop(usb_hcd); ++ return 1; ++} ++ ++static void del_xfer_timers(struct dwc_otg_hcd *hcd) ++{ ++#ifdef DEBUG ++ int i; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) ++ del_timer(&hcd->core_if->hc_xfer_timer[i]); ++#endif ++} ++ ++static void del_timers(struct dwc_otg_hcd *hcd) ++{ ++ del_xfer_timers(hcd); ++ del_timer(&hcd->conn_timer); ++} ++ ++/** ++ * Processes all the URBs in a single list of QHs. Completes them with ++ * -ETIMEDOUT and frees the QTD. ++ */ ++static void kill_urbs_in_qh_list(struct dwc_otg_hcd *hcd, ++ struct list_head *_qh_list) ++{ ++ struct dwc_otg_qh *qh; ++ struct dwc_otg_qtd *qtd; ++ struct dwc_otg_qtd *qtd_next; ++ ++ list_for_each_entry(qh, _qh_list, qh_list_entry) { ++ list_for_each_entry_safe(qtd, qtd_next, &qh->qtd_list, ++ qtd_list_entry) { ++ if (qtd->urb != NULL) { ++ dwc_otg_hcd_complete_urb(hcd, qtd->urb, ++ -ETIMEDOUT); ++ qtd->urb = NULL; ++ } ++ dwc_otg_hcd_qtd_remove_and_free(qtd); ++ } ++ } ++} ++ ++/** ++ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic ++ * and periodic schedules. The QTD associated with each URB is removed from ++ * the schedule and freed. This function may be called when a disconnect is ++ * detected or when the HCD is being stopped. ++ */ ++static void kill_all_urbs(struct dwc_otg_hcd *hcd) ++{ ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @_p: void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_disconnect_cb(void *_p) ++{ ++ union gintsts_data intr; ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); ++ ++ /* ++ * Set status flags for the hub driver. ++ */ ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 0; ++ ++ /* ++ * Shutdown any transfers in process by clearing the Tx FIFO Empty ++ * interrupt mask and status bits and disabling subsequent host ++ * channel interrupts. ++ */ ++ intr.d32 = 0; ++ intr.b.nptxfempty = 1; ++ intr.b.ptxfempty = 1; ++ intr.b.hcintr = 1; ++ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, ++ intr.d32, 0); ++ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, ++ intr.d32, 0); ++ ++ del_timers(dwc_otg_hcd); ++ ++ /* ++ * Turn off the vbus power only if the core has transitioned to device ++ * mode. If still in host mode, need to keep power on to detect a ++ * reconnection. ++ */ ++ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { ++ if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { ++ union hprt0_data hprt0 = {.d32 = 0 }; ++ DWC_PRINT("Disconnect: PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ ++ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); ++ } ++ ++ /* Respond with an error status to all URBs in the schedule. */ ++ kill_all_urbs(dwc_otg_hcd); ++ ++ if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) { ++ /* Clean up any host channels that were in use. */ ++ int num_channels; ++ int i; ++ struct dwc_hc *channel; ++ struct dwc_otg_hc_regs *hc_regs; ++ union hcchar_data hcchar; ++ ++ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ /* Flush out any channel requests in slave mode. */ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (list_empty(&channel->hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if->host_if-> ++ hc_regs[i]; ++ hcchar.d32 = ++ dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ dwc_write_reg32(&hc_regs-> ++ hcchar, ++ hcchar.d32); ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (list_empty(&channel->hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if->host_if->hc_regs[i]; ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ /* Halt the channel. */ ++ hcchar.b.chdis = 1; ++ dwc_write_reg32(&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ ++ dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, ++ channel); ++ list_add_tail(&channel->hc_list_entry, ++ &dwc_otg_hcd->free_hc_list); ++ } ++ } ++ } ++ ++ /* A disconnect will end the session so the B-Device is no ++ * longer a B-host. */ ++ ((struct usb_hcd *)_p)->self.is_b_host = 0; ++ return 1; ++} ++ ++/** ++ * Connection timeout function. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. ++ */ ++void dwc_otg_hcd_connect_timeout(unsigned long _ptr) ++{ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%x)\n", __func__, (int)_ptr); ++ DWC_PRINT("Connect Timeout\n"); ++ DWC_ERROR("Device Not Connected/Responding\n"); ++} ++ ++/** ++ * Start the connection timer. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. The ++ * timer is deleted if a port connect interrupt occurs before the ++ * timer expires. ++ */ ++static void dwc_otg_hcd_start_connect_timer(struct dwc_otg_hcd *hcd) ++{ ++ init_timer(&hcd->conn_timer); ++ hcd->conn_timer.function = dwc_otg_hcd_connect_timeout; ++ hcd->conn_timer.data = (unsigned long)0; ++ hcd->conn_timer.expires = jiffies + (HZ * 10); ++ add_timer(&hcd->conn_timer); ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @_p: void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_session_start_cb(void *_p) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); ++ dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); ++ return 1; ++} ++ ++/** ++ * HCD Callback structure for handling mode switching. ++ */ ++static struct dwc_otg_cil_callbacks hcd_cil_callbacks = { ++ .start = dwc_otg_hcd_start_cb, ++ .stop = dwc_otg_hcd_stop_cb, ++ .disconnect = dwc_otg_hcd_disconnect_cb, ++ .session_start = dwc_otg_hcd_session_start_cb, ++ .p = 0, ++}; ++ ++/** ++ * Reset tasklet function ++ */ ++static void reset_tasklet_func(unsigned long data) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = (struct dwc_otg_hcd *)data; ++ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; ++ union hprt0_data hprt0; ++ ++ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ mdelay(60); ++ ++ hprt0.b.prtrst = 0; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++ ++ return; ++} ++ ++static struct tasklet_struct reset_tasklet = { ++ .next = NULL, ++ .state = 0, ++ .count = ATOMIC_INIT(0), ++ .func = reset_tasklet_func, ++ .data = 0, ++}; ++ ++static enum hrtimer_restart delayed_enable(struct hrtimer *t) ++{ ++ struct dwc_otg_hcd *hcd = container_of(t, struct dwc_otg_hcd, ++ poll_rate_limit); ++ struct dwc_otg_core_global_regs *global_regs = ++ hcd->core_if->core_global_regs; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ intr_mask.b.nptxfempty = 1; ++ dwc_modify_reg32(&global_regs->gintmsk, 0, intr_mask.d32); ++ ++ return HRTIMER_NORESTART; ++} ++ ++/** ++ * Initializes the HCD. This function allocates memory for and initializes the ++ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the ++ * USB bus with the core and calls the hc_driver->start() function. It returns ++ * a negative error on failure. ++ */ ++int __devinit dwc_otg_hcd_init(struct device *dev) ++{ ++ struct usb_hcd *hcd = NULL; ++ struct dwc_otg_hcd *dwc_otg_hcd = NULL; ++ struct dwc_otg_device *otg_dev = dev->platform_data; ++ ++ int num_channels; ++ int i; ++ struct dwc_hc *channel; ++ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n"); ++ ++ /* Set device flags indicating whether the HCD supports DMA. */ ++ if (otg_dev->core_if->dma_enable) { ++ DWC_PRINT("Using DMA mode\n"); ++ dev->coherent_dma_mask = ~0; ++ dev->dma_mask = &dev->coherent_dma_mask; ++ } else { ++ DWC_PRINT("Using Slave mode\n"); ++ dev->coherent_dma_mask = 0; ++ dev->dma_mask = NULL; ++ } ++ ++ /* ++ * Allocate memory for the base HCD plus the DWC OTG HCD. ++ * Initialize the base HCD. ++ */ ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, dev, dev_name(dev)); ++ if (hcd == NULL) { ++ retval = -ENOMEM; ++ goto error1; ++ } ++ hcd->regs = otg_dev->base; ++ hcd->self.otg_port = 1; ++ ++ /* Integrate TT in root hub, by default this is disbled. */ ++ hcd->has_tt = 1; ++ ++ /* Initialize the DWC OTG HCD. */ ++ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ spin_lock_init(&dwc_otg_hcd->global_lock); ++ ++ dwc_otg_hcd->core_if = otg_dev->core_if; ++ otg_dev->hcd = dwc_otg_hcd; ++ ++ /* Register the HCD CIL Callbacks */ ++ dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if, ++ &hcd_cil_callbacks, hcd); ++ ++ /* Initialize the non-periodic schedule. */ ++ INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_inactive); ++ INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_active); ++ ++ /* Initialize the periodic schedule. */ ++ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_inactive); ++ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_ready); ++ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_assigned); ++ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_queued); ++ ++ /* ++ * Create a host channel descriptor for each host channel implemented ++ * in the controller. Initialize the channel descriptor array. ++ */ ++ INIT_LIST_HEAD(&dwc_otg_hcd->free_hc_list); ++ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ channel = kmalloc(sizeof(struct dwc_hc), GFP_KERNEL); ++ if (channel == NULL) { ++ retval = -ENOMEM; ++ DWC_ERROR("%s: host channel allocation failed\n", ++ __func__); ++ goto error2; ++ } ++ memset(channel, 0, sizeof(struct dwc_hc)); ++ channel->hc_num = i; ++ dwc_otg_hcd->hc_ptr_array[i] = channel; ++#ifdef DEBUG ++ init_timer(&dwc_otg_hcd->core_if->hc_xfer_timer[i]); ++#endif ++ ++ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, ++ channel); ++ } ++ ++ /* Initialize the Connection timeout timer. */ ++ init_timer(&dwc_otg_hcd->conn_timer); ++ ++ /* Initialize reset tasklet. */ ++ reset_tasklet.data = (unsigned long)dwc_otg_hcd; ++ dwc_otg_hcd->reset_tasklet = &reset_tasklet; ++ ++ hrtimer_init(&dwc_otg_hcd->poll_rate_limit, CLOCK_MONOTONIC, ++ HRTIMER_MODE_REL); ++ dwc_otg_hcd->poll_rate_limit.function = delayed_enable; ++ ++ /* ++ * Finish generic HCD initialization and start the HCD. This function ++ * allocates the DMA buffer pool, registers the USB bus, requests the ++ * IRQ line, and calls dwc_otg_hcd_start method. ++ */ ++ retval = ++ usb_add_hcd(hcd, platform_get_irq(to_platform_device(dev), 0), ++ IRQF_SHARED); ++ if (retval < 0) ++ goto error2; ++ ++ /* ++ * Allocate space for storing data on status transactions. Normally no ++ * data is sent, but this space acts as a bit bucket. This must be ++ * done after usb_add_hcd since that function allocates the DMA buffer ++ * pool. ++ */ ++ if (otg_dev->core_if->dma_enable) { ++ dwc_otg_hcd->status_buf = ++ dma_alloc_coherent(dev, ++ DWC_OTG_HCD_STATUS_BUF_SIZE, ++ &dwc_otg_hcd->status_buf_dma, ++ GFP_KERNEL | GFP_DMA); ++ } else { ++ dwc_otg_hcd->status_buf = kmalloc(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ GFP_KERNEL); ++ } ++ if (dwc_otg_hcd->status_buf == NULL) { ++ retval = -ENOMEM; ++ DWC_ERROR("%s: status_buf allocation failed\n", __func__); ++ goto error3; ++ } ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, usbbus=%d\n", ++ hcd->self.busnum); ++ ++ return 0; ++ ++ /* Error conditions */ ++error3: ++ usb_remove_hcd(hcd); ++error2: ++ dwc_otg_hcd_free(hcd); ++ usb_put_hcd(hcd); ++error1: ++ return retval; ++} ++ ++/** ++ * Removes the HCD. ++ * Frees memory and resources associated with the HCD and deregisters the bus. ++ */ ++void dwc_otg_hcd_remove(struct device *dev) ++{ ++ struct dwc_otg_device *otg_dev = dev->platform_data; ++ struct dwc_otg_hcd *dwc_otg_hcd = otg_dev->hcd; ++ struct usb_hcd *hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n"); ++ ++ /* Turn off all interrupts */ ++ dwc_write_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0); ++ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gahbcfg, 1, ++ 0); ++ ++ usb_remove_hcd(hcd); ++ dwc_otg_hcd_free(hcd); ++ usb_put_hcd(hcd); ++ ++ return; ++} ++ ++/* ========================================================================= ++ * Linux HC Driver Functions ++ * ========================================================================= */ ++ ++/** ++ * Initializes dynamic portions of the DWC_otg HCD state. ++ */ ++static void hcd_reinit(struct dwc_otg_hcd *hcd) ++{ ++ struct list_head *item; ++ int num_channels; ++ int i; ++ struct dwc_hc *channel; ++ ++ hcd->flags.d32 = 0; ++ ++ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; ++ hcd->non_periodic_channels = 0; ++ hcd->periodic_channels = 0; ++ ++ /* ++ * Put all channels in the free channel list and clean up channel ++ * states. ++ */ ++ item = hcd->free_hc_list.next; ++ while (item != &hcd->free_hc_list) { ++ list_del(item); ++ item = hcd->free_hc_list.next; ++ } ++ num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ channel = hcd->hc_ptr_array[i]; ++ list_add_tail(&channel->hc_list_entry, &hcd->free_hc_list); ++ dwc_otg_hc_cleanup(hcd->core_if, channel); ++ } ++ ++ /* Initialize the DWC core for host mode operation. */ ++ dwc_otg_core_host_init(hcd->core_if); ++} ++ ++/** Initializes the DWC_otg controller and its root hub and prepares it for host ++ * mode operation. Activates the root port. Returns 0 on success and a negative ++ * error code on failure. */ ++int dwc_otg_hcd_start(struct usb_hcd *hcd) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; ++ unsigned long flags; ++ ++ struct usb_bus *bus; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); ++ ++ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); ++ ++ bus = hcd_to_bus(hcd); ++ ++ /* Initialize the bus state. If the core is in Device Mode ++ * HALT the USB bus and return. */ ++ if (dwc_otg_is_device_mode(core_if)) { ++ hcd->state = HC_STATE_HALT; ++ goto out; ++ } ++ hcd->state = HC_STATE_RUNNING; ++ ++ hcd_reinit(dwc_otg_hcd); ++out: ++ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); ++ ++ return 0; ++} ++ ++static void qh_list_free(struct dwc_otg_hcd *hcd, struct list_head *_qh_list) ++{ ++ struct list_head *item; ++ struct dwc_otg_qh *qh; ++ ++ if (_qh_list->next == NULL) { ++ /* The list hasn't been initialized yet. */ ++ return; ++ } ++ ++ /* Ensure there are no QTDs or URBs left. */ ++ kill_urbs_in_qh_list(hcd, _qh_list); ++ ++ for (item = _qh_list->next; item != _qh_list; item = _qh_list->next) { ++ qh = list_entry(item, struct dwc_otg_qh, qh_list_entry); ++ dwc_otg_hcd_qh_remove_and_free(hcd, qh); ++ } ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void dwc_otg_hcd_stop(struct usb_hcd *hcd) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ union hprt0_data hprt0 = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n"); ++ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); ++ ++ /* ++ * The root hub should be disconnected before this function is called. ++ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) ++ * and the QH lists (via ..._hcd_endpoint_disable). ++ */ ++ ++ /* Turn off the vbus power */ ++ DWC_PRINT("PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); ++ ++ return; ++} ++ ++/** Returns the current frame number. */ ++int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ union hfnum_data hfnum; ++ ++ hfnum.d32 = ++ dwc_read_reg32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> ++ hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", ++ hfnum.b.frnum); ++#endif ++ return hfnum.b.frnum; ++} ++ ++/** ++ * Frees secondary storage associated with the dwc_otg_hcd structure contained ++ * in the struct usb_hcd field. ++ */ ++void dwc_otg_hcd_free(struct usb_hcd *hcd) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ int i; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); ++ ++ del_timers(dwc_otg_hcd); ++ ++ /* Free memory for QH/QTD lists */ ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued); ++ ++ /* Free memory for the host channels. */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ struct dwc_hc *hc = dwc_otg_hcd->hc_ptr_array[i]; ++ if (hc != NULL) { ++ DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", ++ i, hc); ++ kfree(hc); ++ } ++ } ++ ++ if (dwc_otg_hcd->core_if->dma_enable) { ++ if (dwc_otg_hcd->status_buf_dma) { ++ dma_free_coherent(hcd->self.controller, ++ DWC_OTG_HCD_STATUS_BUF_SIZE, ++ dwc_otg_hcd->status_buf, ++ dwc_otg_hcd->status_buf_dma); ++ } ++ } else if (dwc_otg_hcd->status_buf != NULL) { ++ kfree(dwc_otg_hcd->status_buf); ++ } ++ ++ return; ++} ++ ++#ifdef DEBUG ++static void dump_urb_info(struct urb *urb, char *_fn_name) ++{ ++ DWC_PRINT("%s, urb %p\n", _fn_name, urb); ++ DWC_PRINT(" Device address: %d\n", usb_pipedevice(urb->pipe)); ++ DWC_PRINT(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), ++ (usb_pipein(urb->pipe) ? "IN" : "OUT")); ++ DWC_PRINT(" Endpoint type: %s\n", ++ ({ ++ char *pipetype; ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ pipetype = "CONTROL"; ++ break; ++ case PIPE_BULK: ++ pipetype = "BULK"; ++ break; ++ case PIPE_INTERRUPT: ++ pipetype = "INTERRUPT"; ++ break; ++ case PIPE_ISOCHRONOUS: ++ pipetype = "ISOCHRONOUS"; ++ break; ++ default: ++ pipetype = "UNKNOWN"; ++ break; ++ } ++ pipetype; ++ })) ; ++ DWC_PRINT(" Speed: %s\n", ++ ({ ++ char *speed; ++ switch (urb->dev->speed) { ++ case USB_SPEED_HIGH: ++ speed = "HIGH"; ++ break; ++ case USB_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case USB_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ } ++ speed; ++ })); ++ DWC_PRINT(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, ++ usb_pipeout(urb->pipe))); ++ DWC_PRINT(" Data buffer length: %d\n", urb->transfer_buffer_length); ++ DWC_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->transfer_buffer, (void *)urb->transfer_dma); ++ DWC_PRINT(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_PRINT(" Interval: %d\n", urb->interval); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINT(" ISO Desc %d:\n", i); ++ DWC_PRINT(" offset: %d, length %d\n", ++ urb->iso_frame_desc[i].offset, ++ urb->iso_frame_desc[i].length); ++ } ++ } ++} ++ ++static void dump_channel_info(struct dwc_otg_hcd *hcd, struct dwc_otg_qh * qh) ++{ ++ if (qh->channel != NULL) { ++ struct dwc_hc *hc = qh->channel; ++ struct list_head *item; ++ struct dwc_otg_qh *qh_item; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ int i; ++ ++ struct dwc_otg_hc_regs *hc_regs; ++ union hcchar_data hcchar; ++ union hcsplt_data hcsplt; ++ union hctsiz_data hctsiz; ++ uint32_t hcdma; ++ ++ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ hcdma = dwc_read_reg32(&hc_regs->hcdma); ++ ++ DWC_PRINT(" Assigned to channel %p:\n", hc); ++ DWC_PRINT(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, ++ hcsplt.d32); ++ DWC_PRINT(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, ++ hcdma); ++ DWC_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINT(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINT(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINT(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINT(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINT(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINT(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINT(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINT(" qh: %p\n", hc->qh); ++ DWC_PRINT(" NP inactive sched:\n"); ++ list_for_each(item, &hcd->non_periodic_sched_inactive) { ++ qh_item = list_entry(item, struct dwc_otg_qh, ++ qh_list_entry); ++ DWC_PRINT(" %p\n", qh_item); ++ } ++ DWC_PRINT(" NP active sched:\n"); ++ list_for_each(item, &hcd->non_periodic_sched_active) { ++ qh_item = list_entry(item, struct dwc_otg_qh, ++ qh_list_entry); ++ DWC_PRINT(" %p\n", qh_item); ++ } ++ DWC_PRINT(" Channels: \n"); ++ for (i = 0; i < num_channels; i++) { ++ struct dwc_hc *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINT(" %2d: %p\n", i, hc); ++ } ++ } ++} ++#endif ++ ++/* Starts processing a USB transfer request specified by a USB Request Block ++ * (URB). mem_flags indicates the type of memory allocation to use while ++ * processing this URB. */ ++int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, ++ struct urb *urb, unsigned _mem_flags) ++{ ++ unsigned long flags; ++ int retval = 0; ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct dwc_otg_qtd *qtd; ++ ++ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); ++ ++ /* ++ * Make sure the start of frame interrupt is enabled now that ++ * we know we should have queued data. The SOF interrupt ++ * handler automatically disables itself when idle to reduce ++ * the number of interrupts. See dwc_otg_hcd_handle_sof_intr() ++ * for the disable ++ */ ++ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, ++ DWC_SOF_INTR_MASK); ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) ++ dump_urb_info(urb, "dwc_otg_hcd_urb_enqueue"); ++#endif ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* No longer connected. */ ++ retval = -ENODEV; ++ goto out; ++ } ++ ++ qtd = dwc_otg_hcd_qtd_create(urb); ++ if (qtd == NULL) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); ++ retval = -ENOMEM; ++ goto out; ++ } ++ ++ retval = dwc_otg_hcd_qtd_add(qtd, dwc_otg_hcd); ++ if (retval < 0) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " ++ "Error status %d\n", retval); ++ dwc_otg_hcd_qtd_free(qtd); ++ } ++out: ++ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); ++ ++ return retval; ++} ++ ++/** Aborts/cancels a USB transfer request. Always returns 0 to indicate ++ * success. */ ++int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ++{ ++ unsigned long flags; ++ struct dwc_otg_hcd *dwc_otg_hcd; ++ struct dwc_otg_qtd *urb_qtd; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); ++ ++ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); ++ ++ urb_qtd = urb->hcpriv; ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "dwc_otg_hcd_urb_dequeue"); ++ if (urb_qtd == urb_qtd->qh->qtd_in_process) ++ dump_channel_info(dwc_otg_hcd, urb_qtd->qh); ++ } ++#endif ++ ++ if (urb_qtd == urb_qtd->qh->qtd_in_process) { ++ /* The QTD is in process (it has been assigned to a channel). */ ++ ++ if (dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * If still connected (i.e. in host mode), halt the ++ * channel so it can be used for other transfers. If ++ * no longer connected, the host registers can't be ++ * written to halt the channel since the core is in ++ * device mode. ++ */ ++ dwc_otg_hc_halt(dwc_otg_hcd->core_if, ++ urb_qtd->qh->channel, ++ DWC_OTG_HC_XFER_URB_DEQUEUE); ++ } ++ } ++ ++ /* ++ * Free the QTD and clean up the associated QH. Leave the QH in the ++ * schedule if it has any remaining QTDs. ++ */ ++ dwc_otg_hcd_qtd_remove_and_free(urb_qtd); ++ if (urb_qtd == urb_qtd->qh->qtd_in_process) { ++ dwc_otg_hcd_qh_deactivate(dwc_otg_hcd, urb_qtd->qh, 0); ++ urb_qtd->qh->channel = NULL; ++ urb_qtd->qh->qtd_in_process = NULL; ++ } else if (list_empty(&urb_qtd->qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(dwc_otg_hcd, urb_qtd->qh); ++ } ++ ++ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); ++ ++ urb->hcpriv = NULL; ++ ++ /* Higher layer software sets URB status. */ ++ usb_hcd_giveback_urb(hcd, urb, status); ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINT("Called usb_hcd_giveback_urb()\n"); ++ DWC_PRINT(" urb->status = %d\n", urb->status); ++ } ++ ++ return 0; ++} ++ ++/* Frees resources in the DWC_otg controller related to a given endpoint. Also ++ * clears state in the HCD related to the endpoint. Any URBs for the endpoint ++ * must already be dequeued. */ ++void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd, ++ struct usb_host_endpoint *_ep) ++{ ++ unsigned long flags; ++ struct dwc_otg_qh *qh; ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " ++ "endpoint=%d\n", _ep->desc.bEndpointAddress, ++ dwc_ep_addr_to_endpoint(_ep->desc.bEndpointAddress)); ++ ++ qh = _ep->hcpriv; ++ if (qh != NULL) { ++#if 1 ++ /* ++ * FIXME: Kludge to not crash on Octeon in SMP ++ * mode. Normally dwc_otg_hcd_qh_remove_and_free() is ++ * called even if the list isn't empty. This causes a ++ * crash on SMP, so we don't call it now. It works ++ * better, but probably does evil things I don't know ++ * about. ++ */ ++ /* Check that the QTD list is really empty */ ++ if (!list_empty(&qh->qtd_list)) { ++ pr_err("DWC OTG HCD EP DISABLE:" ++ " QTD List for this endpoint is not empty\n"); ++ } else ++#endif ++ { ++ dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh); ++ _ep->hcpriv = NULL; ++ } ++ } ++ ++ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); ++ ++ return; ++} ++ ++/* Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if ++ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid ++ * interrupt. ++ * ++ * This function is called by the USB core when an interrupt occurs */ ++irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) ++{ ++ irqreturn_t result; ++ unsigned long flags; ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); ++ ++ result = IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_otg_hcd)); ++ ++ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); ++ ++ return result; ++} ++ ++/** Creates Status Change bitmap for the root hub and root port. The bitmap is ++ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 ++ * is the status change indicator for the single root port. Returns 1 if either ++ * change indicator is 1, otherwise returns 0. */ ++int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, char *_buf) ++{ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ _buf[0] = 0; ++ _buf[0] |= (dwc_otg_hcd->flags.b.port_connect_status_change || ++ dwc_otg_hcd->flags.b.port_reset_change || ++ dwc_otg_hcd->flags.b.port_enable_change || ++ dwc_otg_hcd->flags.b.port_suspend_change || ++ dwc_otg_hcd->flags.b.port_over_current_change) << 1; ++ ++#ifdef DEBUG ++ if (_buf[0]) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" ++ " Root port status changed\n"); ++ DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", ++ dwc_otg_hcd->flags.b.port_connect_status_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", ++ dwc_otg_hcd->flags.b.port_reset_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", ++ dwc_otg_hcd->flags.b.port_enable_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", ++ dwc_otg_hcd->flags.b.port_suspend_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", ++ dwc_otg_hcd->flags.b.port_over_current_change); ++ } ++#endif ++ return (_buf[0] != 0); ++} ++ ++#ifdef DWC_HS_ELECT_TST ++/* ++ * Quick and dirty hack to implement the HS Electrical Test ++ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. ++ * ++ * This code was copied from our userspace app "hset". It sends a ++ * Get Device Descriptor control sequence in two parts, first the ++ * Setup packet by itself, followed some time later by the In and ++ * Ack packets. Rather than trying to figure out how to add this ++ * functionality to the normal driver code, we just hijack the ++ * hardware, using these two function to drive the hardware ++ * directly. ++ */ ++ ++struct dwc_otg_core_global_regs *global_regs; ++struct dwc_otg_host_global_regs *hc_global_regs; ++struct dwc_otg_hc_regs *hc_regs; ++uint32_t *data_fifo; ++ ++static void do_setup(void) ++{ ++ union gintsts_data gintsts; ++ union hctsiz_data hctsiz; ++ union hcchar_data hcchar; ++ union haint_data haint; ++ union hcint_data hcint; ++ ++ /* Enable HAINTs */ ++ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* ++ * Send Setup packet (Get Device Descriptor) ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_SETUP; ++ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ /* Fill FIFO with Setup data for Get Device Descriptor */ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ dwc_write_reg32(data_fifo++, 0x01000680); ++ dwc_write_reg32(data_fifo++, 0x00080000); ++ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ ++ /* Disable HCINTs */ ++ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++} ++ ++static void do_in_ack(void) ++{ ++ union gintsts_data gintsts; ++ union hctsiz_data hctsiz; ++ union hcchar_data hcchar; ++ union haint_data haint; ++ union hcint_data hcint; ++ union host_grxsts_data grxsts; ++ ++ /* Enable HAINTs */ ++ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* ++ * Receive Control In packet ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 1; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer */ ++ if (grxsts.b.bcnt > 0) { ++ int i; ++ int word_count = (grxsts.b.bcnt + 3) / 4; ++ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ ++ for (i = 0; i < word_count; i++) ++ (void)dwc_read_reg32(data_fifo++); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ ++ /* Read RXSTS */ ++ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ mdelay(1); ++ ++ /* ++ * Send handshake packet ++ */ ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 0; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ ++ /* Disable HCINTs */ ++ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++} ++#endif /* DWC_HS_ELECT_TST */ ++ ++/* Handles hub class-specific requests.*/ ++int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, ++ u16 _typeReq, ++ u16 _wValue, u16 _wIndex, char *_buf, u16 _wLength) ++{ ++ int retval = 0; ++ unsigned long flags; ++ ++ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct dwc_otg_core_if *core_if = hcd_to_dwc_otg_hcd(hcd)->core_if; ++ struct usb_hub_descriptor *desc; ++ union hprt0_data hprt0 = {.d32 = 0 }; ++ ++ uint32_t port_status; ++#ifdef DWC_HS_ELECT_TST ++ uint32_t t; ++ union gintmsk_data gintmsk; ++#endif ++ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); ++ ++ switch (_typeReq) { ++ case ClearHubFeature: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearHubFeature 0x%x\n", _wValue); ++ switch (_wValue) { ++ case C_HUB_LOCAL_POWER: ++ case C_HUB_OVER_CURRENT: ++ /* Nothing required here */ ++ break; ++ default: ++ retval = -EINVAL; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearHubFeature request %xh unknown\n", ++ _wValue); ++ } ++ break; ++ case ClearPortFeature: ++ if (!_wIndex || _wIndex > 1) ++ goto error; ++ ++ switch (_wValue) { ++ case USB_PORT_FEAT_ENABLE: ++ DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtena = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case USB_PORT_FEAT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ /* Clear Resume bit */ ++ mdelay(100); ++ hprt0.b.prtres = 0; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case USB_PORT_FEAT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case USB_PORT_FEAT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); ++ /* Port inidicator not supported */ ++ break; ++ case USB_PORT_FEAT_C_CONNECTION: ++ /* Clears drivers internal connect status change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 0; ++ break; ++ case USB_PORT_FEAT_C_RESET: ++ /* Clears the driver's internal Port Reset Change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); ++ dwc_otg_hcd->flags.b.port_reset_change = 0; ++ break; ++ case USB_PORT_FEAT_C_ENABLE: ++ /* Clears the driver's internal Port ++ * Enable/Disable Change flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); ++ dwc_otg_hcd->flags.b.port_enable_change = 0; ++ break; ++ case USB_PORT_FEAT_C_SUSPEND: ++ /* Clears the driver's internal Port Suspend ++ * Change flag, which is set when resume signaling on ++ * the host port is complete */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); ++ dwc_otg_hcd->flags.b.port_suspend_change = 0; ++ break; ++ case USB_PORT_FEAT_C_OVER_CURRENT: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); ++ dwc_otg_hcd->flags.b.port_over_current_change = 0; ++ break; ++ default: ++ retval = -EINVAL; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearPortFeature request %xh " ++ "unknown or unsupported\n", _wValue); ++ } ++ break; ++ case GetHubDescriptor: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubDescriptor\n"); ++ desc = (struct usb_hub_descriptor *)_buf; ++ desc->bDescLength = 9; ++ desc->bDescriptorType = 0x29; ++ desc->bNbrPorts = 1; ++ desc->wHubCharacteristics = 0x08; ++ desc->bPwrOn2PwrGood = 1; ++ desc->bHubContrCurrent = 0; ++ desc->bitmap[0] = 0; ++ desc->bitmap[1] = 0xff; ++ break; ++ case GetHubStatus: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubStatus\n"); ++ memset(_buf, 0, 4); ++ break; ++ case GetPortStatus: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetPortStatus\n"); ++ ++ if (!_wIndex || _wIndex > 1) ++ goto error; ++ ++ port_status = 0; ++ ++ if (dwc_otg_hcd->flags.b.port_connect_status_change) ++ port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); ++ ++ if (dwc_otg_hcd->flags.b.port_enable_change) ++ port_status |= (1 << USB_PORT_FEAT_C_ENABLE); ++ ++ if (dwc_otg_hcd->flags.b.port_suspend_change) ++ port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); ++ ++ if (dwc_otg_hcd->flags.b.port_reset_change) ++ port_status |= (1 << USB_PORT_FEAT_C_RESET); ++ ++ if (dwc_otg_hcd->flags.b.port_over_current_change) { ++ DWC_ERROR("Device Not Supported\n"); ++ port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT); ++ } ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return 0's for the remainder of the port status ++ * since the port register can't be read if the core ++ * is in device mode. ++ */ ++ *((__le32 *) _buf) = cpu_to_le32(port_status); ++ break; ++ } ++ ++ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); ++ ++ if (hprt0.b.prtconnsts) ++ port_status |= (1 << USB_PORT_FEAT_CONNECTION); ++ ++ if (hprt0.b.prtena) ++ port_status |= (1 << USB_PORT_FEAT_ENABLE); ++ ++ if (hprt0.b.prtsusp) ++ port_status |= (1 << USB_PORT_FEAT_SUSPEND); ++ ++ if (hprt0.b.prtovrcurract) ++ port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT); ++ ++ if (hprt0.b.prtrst) ++ port_status |= (1 << USB_PORT_FEAT_RESET); ++ ++ if (hprt0.b.prtpwr) ++ port_status |= (1 << USB_PORT_FEAT_POWER); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) ++ port_status |= (1 << USB_PORT_FEAT_HIGHSPEED); ++ else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) ++ port_status |= (1 << USB_PORT_FEAT_LOWSPEED); ++ ++ if (hprt0.b.prttstctl) ++ port_status |= (1 << USB_PORT_FEAT_TEST); ++ ++ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ ++ ++ *((__le32 *) _buf) = cpu_to_le32(port_status); ++ ++ break; ++ case SetHubFeature: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetHubFeature\n"); ++ /* No HUB features supported */ ++ break; ++ case SetPortFeature: ++ if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1)) ++ goto error; ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return without doing anything since the port ++ * register can't be written if the core is in device ++ * mode. ++ */ ++ break; ++ } ++ ++ switch (_wValue) { ++ case USB_PORT_FEAT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); ++ if (hcd->self.otg_port == _wIndex && ++ hcd->self.b_hnp_enable) { ++ union gotgctl_data gotgctl = {.d32 = 0 }; ++ gotgctl.b.hstsethnpen = 1; ++ dwc_modify_reg32(&core_if->core_global_regs-> ++ gotgctl, 0, gotgctl.d32); ++ core_if->op_state = A_SUSPEND; ++ } ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ /* Suspend the Phy Clock */ ++ { ++ union pcgcctl_data pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32); ++ } ++ ++ /* ++ * For HNP the bus must be suspended for at ++ * least 200ms. ++ */ ++ if (hcd->self.b_hnp_enable) ++ mdelay(200); ++ break; ++ case USB_PORT_FEAT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case USB_PORT_FEAT_RESET: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_RESET\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ /* When B-Host the Port reset bit is set in ++ * the Start HCD Callback function, so that ++ * the reset is started within 1ms of the HNP ++ * success interrupt. */ ++ if (!hcd->self.is_b_host) { ++ hprt0.b.prtrst = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ ++ mdelay(60); ++ hprt0.b.prtrst = 0; ++ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ ++#ifdef DWC_HS_ELECT_TST ++ case USB_PORT_FEAT_TEST: ++ t = (_wIndex >> 8); /* MSB wIndex USB */ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t); ++ warn("USB_PORT_FEAT_TEST %d\n", t); ++ if (t < 6) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prttstctl = t; ++ dwc_write_reg32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } else { ++ /* Setup global vars with reg ++ * addresses (quick and dirty hack, ++ * should be cleaned up) ++ */ ++ global_regs = core_if->core_global_regs; ++ hc_global_regs = ++ core_if->host_if->host_global_regs; ++ hc_regs = ++ (struct dwc_otg_hc_regs *) ((char *) ++ global_regs + ++ 0x500); ++ data_fifo = ++ (uint32_t *) ((char *)global_regs + ++ 0x1000); ++ ++ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ dwc_read_reg32(&global_regs->gintmsk); ++ ++ /* Disable all interrupts ++ * while we muck with the ++ * hardware directly ++ */ ++ dwc_write_reg32(&global_regs->gintmsk, ++ 0); ++ ++ /* 15 second delay per the test spec */ ++ mdelay(15000); ++ ++ /* Drive suspend on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtres = 0; ++ dwc_write_reg32(core_if->host_if->hprt0, ++ hprt0.d32); ++ ++ /* 15 second delay per the test spec */ ++ mdelay(15000); ++ ++ /* Drive resume on the root port */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 0; ++ hprt0.b.prtres = 1; ++ dwc_write_reg32(core_if->host_if->hprt0, ++ hprt0.d32); ++ mdelay(100); ++ ++ /* Clear the resume bit */ ++ hprt0.b.prtres = 0; ++ dwc_write_reg32(core_if->host_if->hprt0, ++ hprt0.d32); ++ ++ /* Restore interrupts */ ++ dwc_write_reg32(&global_regs->gintmsk, ++ gintmsk.d32); ++ } else if (t == 7) { ++ /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ dwc_read_reg32(&global_regs->gintmsk); ++ ++ /* ++ * Disable all interrupts ++ * while we muck with the ++ * hardware directly ++ */ ++ dwc_write_reg32(&global_regs->gintmsk, ++ 0); ++ ++ /* 15 second delay per the test spec */ ++ mdelay(15000); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* ++ * 15 second delay so nothing ++ * else happens for awhile. ++ */ ++ mdelay(15000); ++ ++ /* Restore interrupts */ ++ dwc_write_reg32(&global_regs->gintmsk, ++ gintmsk.d32); ++ } else if (t == 8) { ++ /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ dwc_read_reg32(&global_regs->gintmsk); ++ ++ /* ++ * Disable all interrupts ++ * while we muck with the ++ * hardware directly ++ */ ++ dwc_write_reg32(&global_regs->gintmsk, ++ 0); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ mdelay(15000); ++ ++ /* Send the In and Ack packets */ ++ do_in_ack(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ mdelay(15000); ++ ++ /* Restore interrupts */ ++ dwc_write_reg32(&global_regs->gintmsk, ++ gintmsk.d32); ++ } ++ } ++ break; ++#endif /* DWC_HS_ELECT_TST */ ++ ++ case USB_PORT_FEAT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); ++ /* Not supported */ ++ break; ++ default: ++ retval = -EINVAL; ++ DWC_ERROR("DWC OTG HCD - " ++ "SetPortFeature request %xh " ++ "unknown or unsupported\n", _wValue); ++ break; ++ } ++ break; ++ default: ++error: ++ retval = -EINVAL; ++ DWC_WARN("DWC OTG HCD - Unknown hub control request type or " ++ "invalid typeReq: %xh wIndex: %xh wValue: %xh\n", ++ _typeReq, _wIndex, _wValue); ++ break; ++ } ++ ++ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); ++ ++ return retval; ++} ++ ++/** ++ * Assigns transactions from a QTD to a free host channel and initializes the ++ * host channel to perform the transactions. The host channel is removed from ++ * the free list. ++ * ++ * @hcd: The HCD state structure. ++ * @_qh: Transactions from the first QTD for this QH are selected and ++ * assigned to a free host channel. ++ */ ++static void assign_and_init_hc(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *_qh) ++{ ++ struct dwc_hc *hc; ++ struct dwc_otg_qtd *qtd; ++ struct urb *urb; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, _qh); ++ ++ hc = list_entry(hcd->free_hc_list.next, struct dwc_hc, hc_list_entry); ++ ++ /* Remove the host channel from the free list. */ ++ list_del_init(&hc->hc_list_entry); ++ ++ qtd = list_entry(_qh->qtd_list.next, struct dwc_otg_qtd, ++ qtd_list_entry); ++ urb = qtd->urb; ++ _qh->channel = hc; ++ _qh->qtd_in_process = qtd; ++ ++ /* ++ * Use usb_pipedevice to determine device address. This address is ++ * 0 before the SET_ADDRESS command and the correct address afterward. ++ */ ++ hc->dev_addr = usb_pipedevice(urb->pipe); ++ hc->ep_num = usb_pipeendpoint(urb->pipe); ++ ++ if (urb->dev->speed == USB_SPEED_LOW) ++ hc->speed = DWC_OTG_EP_SPEED_LOW; ++ else if (urb->dev->speed == USB_SPEED_FULL) ++ hc->speed = DWC_OTG_EP_SPEED_FULL; ++ else ++ hc->speed = DWC_OTG_EP_SPEED_HIGH; ++ ++ hc->max_packet = dwc_max_packet(_qh->maxp); ++ ++ hc->xfer_started = 0; ++ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS; ++ hc->error_state = (qtd->error_count > 0); ++ hc->halt_on_queue = 0; ++ hc->halt_pending = 0; ++ hc->requests = 0; ++ ++ /* ++ * The following values may be modified in the transfer type section ++ * below. The xfer_len value may be reduced when the transfer is ++ * started to accommodate the max widths of the XferSize and PktCnt ++ * fields in the HCTSIZn register. ++ */ ++ hc->do_ping = _qh->ping_state; ++ hc->ep_is_in = (usb_pipein(urb->pipe) != 0); ++ hc->data_pid_start = _qh->data_toggle; ++ hc->multi_count = 1; ++ ++ if (hcd->core_if->dma_enable) { ++#ifdef CONFIG_CPU_CAVIUM_OCTEON ++ const uint64_t USBN_DMA0_INB_CHN0 = ++ CVMX_USBNX_DMA0_INB_CHN0(hcd->core_if->usb_num); ++#endif /* CONFIG_CPU_CAVIUM_OCTEON */ ++ hc->xfer_buff = ++ (uint8_t *) (unsigned long)urb->transfer_dma + ++ urb->actual_length; ++#ifdef CONFIG_CPU_CAVIUM_OCTEON ++ /* Octeon uses external DMA */ ++ wmb(); ++ cvmx_write_csr(USBN_DMA0_INB_CHN0 + hc->hc_num * 8, ++ (unsigned long)hc->xfer_buff); ++ cvmx_read_csr(USBN_DMA0_INB_CHN0 + hc->hc_num * 8); ++ DWC_DEBUGPL(DBG_HCDV, ++ "IN: hc->hc_num = %d, hc->xfer_buff = %p\n", ++ hc->hc_num, hc->xfer_buff); ++#endif /* CONFIG_CPU_CAVIUM_OCTEON */ ++ } else { ++ hc->xfer_buff = ++ (uint8_t *) urb->transfer_buffer + urb->actual_length; ++ } ++ hc->xfer_len = urb->transfer_buffer_length - urb->actual_length; ++ hc->xfer_count = 0; ++ ++ /* ++ * Set the split attributes ++ */ ++ hc->do_split = 0; ++ if (_qh->do_split) { ++ hc->do_split = 1; ++ hc->xact_pos = qtd->isoc_split_pos; ++ hc->complete_split = qtd->complete_split; ++ hc->hub_addr = urb->dev->tt->hub->devnum; ++ hc->port_addr = urb->dev->ttport; ++ } ++ ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL; ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); ++ hc->do_ping = 0; ++ hc->ep_is_in = 0; ++ hc->data_pid_start = DWC_OTG_HC_PID_SETUP; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = ++ (uint8_t *) (unsigned long)urb->setup_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->setup_packet; ++ } ++ hc->xfer_len = 8; ++ break; ++ case DWC_OTG_CONTROL_DATA: ++ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n"); ++ hc->data_pid_start = qtd->data_toggle; ++ break; ++ case DWC_OTG_CONTROL_STATUS: ++ /* ++ * Direction is opposite of data direction or IN if no ++ * data. ++ */ ++ DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n"); ++ if (urb->transfer_buffer_length == 0) { ++ hc->ep_is_in = 1; ++ } else { ++ hc->ep_is_in = ++ (usb_pipein(urb->pipe) != USB_DIR_IN); ++ } ++ if (hc->ep_is_in) ++ hc->do_ping = 0; ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ hc->xfer_len = 0; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = ++ (uint8_t *) (unsigned long)hcd-> ++ status_buf_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf; ++ } ++ break; ++ } ++ break; ++ case PIPE_BULK: ++ hc->ep_type = DWC_OTG_EP_TYPE_BULK; ++ break; ++ case PIPE_INTERRUPT: ++ hc->ep_type = DWC_OTG_EP_TYPE_INTR; ++ break; ++ case PIPE_ISOCHRONOUS: ++ { ++ struct usb_iso_packet_descriptor *frame_desc; ++ frame_desc = ++ &urb->iso_frame_desc[qtd->isoc_frame_index]; ++ hc->ep_type = DWC_OTG_EP_TYPE_ISOC; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = ++ (uint8_t *) (unsigned long)urb-> ++ transfer_dma; ++ } else { ++ hc->xfer_buff = ++ (uint8_t *) urb->transfer_buffer; ++ } ++ hc->xfer_buff += ++ frame_desc->offset + qtd->isoc_split_offset; ++ hc->xfer_len = ++ frame_desc->length - qtd->isoc_split_offset; ++ ++ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ if (hc->xfer_len <= 188) { ++ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ } else { ++ hc->xact_pos = ++ DWC_HCSPLIT_XACTPOS_BEGIN; ++ } ++ } ++ } ++ break; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This value may be modified when the transfer is started to ++ * reflect the actual transfer length. ++ */ ++ hc->multi_count = dwc_hb_mult(_qh->maxp); ++ } ++ ++ dwc_otg_hc_init(hcd->core_if, hc); ++ hc->qh = _qh; ++} ++ ++/** ++ * This function selects transactions from the HCD transfer schedule and ++ * assigns them to available host channels. It is called from HCD interrupt ++ * handler functions. ++ * ++ * @hcd: The HCD state structure. ++ * ++ * Returns The types of new transactions that were assigned to host channels. ++ */ ++enum dwc_otg_transaction_type dwc_otg_hcd_select_transactions(struct dwc_otg_hcd ++ *hcd) ++{ ++ struct list_head *qh_ptr; ++ struct dwc_otg_qh *qh; ++ int num_channels; ++ enum dwc_otg_transaction_type ret_val = DWC_OTG_TRANSACTION_NONE; ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); ++#endif ++ ++ /* Process entries in the periodic ready list. */ ++ qh_ptr = hcd->periodic_sched_ready.next; ++ while (qh_ptr != &hcd->periodic_sched_ready && ++ !list_empty(&hcd->free_hc_list)) { ++ ++ qh = list_entry(qh_ptr, struct dwc_otg_qh, qh_list_entry); ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the periodic ready schedule to the ++ * periodic assigned schedule. ++ */ ++ qh_ptr = qh_ptr->next; ++ list_move(&qh->qh_list_entry, &hcd->periodic_sched_assigned); ++ ++ ret_val = DWC_OTG_TRANSACTION_PERIODIC; ++ } ++ ++ /* ++ * Process entries in the inactive portion of the non-periodic ++ * schedule. Some free host channels may not be used if they are ++ * reserved for periodic transfers. ++ */ ++ qh_ptr = hcd->non_periodic_sched_inactive.next; ++ num_channels = hcd->core_if->core_params->host_channels; ++ while (qh_ptr != &hcd->non_periodic_sched_inactive && ++ (hcd->non_periodic_channels < ++ num_channels - hcd->periodic_channels) && ++ !list_empty(&hcd->free_hc_list)) { ++ ++ qh = list_entry(qh_ptr, struct dwc_otg_qh, qh_list_entry); ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the non-periodic inactive schedule to the ++ * non-periodic active schedule. ++ */ ++ qh_ptr = qh_ptr->next; ++ list_move(&qh->qh_list_entry, &hcd->non_periodic_sched_active); ++ ++ if (ret_val == DWC_OTG_TRANSACTION_NONE) ++ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; ++ else ++ ret_val = DWC_OTG_TRANSACTION_ALL; ++ ++ hcd->non_periodic_channels++; ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * Attempts to queue a single transaction request for a host channel ++ * associated with either a periodic or non-periodic transfer. This function ++ * assumes that there is space available in the appropriate request queue. For ++ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space ++ * is available in the appropriate Tx FIFO. ++ * ++ * @hcd: The HCD state structure. ++ * @_hc: Host channel descriptor associated with either a periodic or ++ * non-periodic transfer. ++ * @_fifo_dwords_avail: Number of DWORDs available in the periodic Tx ++ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic ++ * transfers. ++ * ++ * Returns 1 if a request is queued and more requests may be needed to ++ * complete the transfer, 0 if no more requests are required for this ++ * transfer, -1 if there is insufficient space in the Tx FIFO. ++ */ ++static int queue_transaction(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *_hc, uint16_t _fifo_dwords_avail) ++{ ++ int retval; ++ ++ if (hcd->core_if->dma_enable) { ++ if (!_hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, _hc); ++ _hc->qh->ping_state = 0; ++ } ++ retval = 0; ++ } else if (_hc->halt_pending) { ++ /* Don't queue a request if the channel has been halted. */ ++ retval = 0; ++ } else if (_hc->halt_on_queue) { ++ dwc_otg_hc_halt(hcd->core_if, _hc, _hc->halt_status); ++ retval = 0; ++ } else if (_hc->do_ping) { ++ if (!_hc->xfer_started) ++ dwc_otg_hc_start_transfer(hcd->core_if, _hc); ++ retval = 0; ++ } else if (!_hc->ep_is_in || ++ _hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ if ((_fifo_dwords_avail * 4) >= _hc->max_packet) { ++ if (!_hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, _hc); ++ retval = 1; ++ } else { ++ retval = ++ dwc_otg_hc_continue_transfer(hcd->core_if, ++ _hc); ++ } ++ } else { ++ retval = -1; ++ } ++ } else { ++ if (!_hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, _hc); ++ retval = 1; ++ } else { ++ retval = ++ dwc_otg_hc_continue_transfer(hcd->core_if, _hc); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Processes active non-periodic channels and queues transactions for these ++ * channels to the DWC_otg controller. After queueing transactions, the NP Tx ++ * FIFO Empty interrupt is enabled if there are more transactions to queue as ++ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx ++ * FIFO Empty interrupt is disabled. ++ */ ++static void process_non_periodic_channels(struct dwc_otg_hcd *hcd) ++{ ++ union gnptxsts_data tx_status; ++ struct list_head *orig_qh_ptr; ++ struct dwc_otg_qh *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ int more_to_do = 0; ++ ++ struct dwc_otg_core_global_regs *global_regs = ++ hcd->core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ /* ++ * Keep track of the starting point. Skip over the start-of-list ++ * entry. ++ */ ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ ++ orig_qh_ptr = hcd->non_periodic_qh_ptr; ++ ++ /* ++ * Process once through the active list or until no more space is ++ * available in the request queue or the Tx FIFO. ++ */ ++ do { ++ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ if (!hcd->core_if->dma_enable ++ && tx_status.b.nptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = list_entry(hcd->non_periodic_qh_ptr, struct dwc_otg_qh, ++ qh_list_entry); ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.nptxfspcavail); ++ ++ if (status > 0) { ++ more_to_do = 1; ++ } else if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* Advance to next QH, skipping start-of-list entry. */ ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ if (hcd->non_periodic_qh_ptr == ++ &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ ++ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); ++ ++ if (!hcd->core_if->dma_enable) { ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ intr_mask.b.nptxfempty = 1; ++ ++#ifdef DEBUG ++ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ if (no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the non-periodic ++ * Tx FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ dwc_modify_reg32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ if (more_to_do) { ++ /* When not using DMA, many USB ++ * devices cause excessive loads on ++ * the serial bus simply because they ++ * continuously poll the device for ++ * status. Here we use the timer to ++ * rate limit how fast we can get the ++ * the NP TX fifo empty interrupt. We ++ * leave the interrupt disable until ++ * the timer fires and reenables it */ ++ ++ /* We'll rate limit the interrupt at ++ * 20000 per second. Making this ++ * faster improves USB performance but ++ * uses more CPU */ ++ hrtimer_start_range_ns(&hcd->poll_rate_limit, ++ ktime_set(0, 50000), ++ 5000, HRTIMER_MODE_REL); ++ } ++ } ++ } ++} ++ ++/** ++ * Processes periodic channels for the next frame and queues transactions for ++ * these channels to the DWC_otg controller. After queueing transactions, the ++ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions ++ * to queue as Periodic Tx FIFO or request queue space becomes available. ++ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. ++ */ ++static void process_periodic_channels(struct dwc_otg_hcd *hcd) ++{ ++ union hptxsts_data tx_status; ++ struct list_head *qh_ptr; ++ struct dwc_otg_qh *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ ++ struct dwc_otg_host_global_regs *host_regs; ++ host_regs = hcd->core_if->host_if->host_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ ++ qh_ptr = hcd->periodic_sched_assigned.next; ++ while (qh_ptr != &hcd->periodic_sched_assigned) { ++ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); ++ if (tx_status.b.ptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = list_entry(qh_ptr, struct dwc_otg_qh, qh_list_entry); ++ ++ /* ++ * Set a flag if we're queuing high-bandwidth in slave mode. ++ * The flag prevents any halts to get into the request queue in ++ * the middle of multiple high-bandwidth packets getting queued. ++ */ ++ if ((!hcd->core_if->dma_enable) && ++ (qh->channel->multi_count > 1)) { ++ hcd->core_if->queuing_high_bandwidth = 1; ++ } ++ ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.ptxfspcavail); ++ if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* ++ * In Slave mode, stay on the current transfer until there is ++ * nothing more to do or the high-bandwidth request count is ++ * reached. In DMA mode, only need to queue one request. The ++ * controller automatically handles multiple packets for ++ * high-bandwidth transfers. ++ */ ++ if (hcd->core_if->dma_enable || ++ (status == 0 || ++ qh->channel->requests == qh->channel->multi_count)) { ++ qh_ptr = qh_ptr->next; ++ /* ++ * Move the QH from the periodic assigned schedule to ++ * the periodic queued schedule. ++ */ ++ list_move(&qh->qh_list_entry, ++ &hcd->periodic_sched_queued); ++ ++ /* done queuing high bandwidth */ ++ hcd->core_if->queuing_high_bandwidth = 0; ++ } ++ } ++ ++ if (!hcd->core_if->dma_enable) { ++ struct dwc_otg_core_global_regs *global_regs; ++ union gintmsk_data intr_mask = {.d32 = 0 }; ++ ++ global_regs = hcd->core_if->core_global_regs; ++ intr_mask.b.ptxfempty = 1; ++#ifdef DEBUG ++ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ if (!(list_empty(&hcd->periodic_sched_assigned)) || ++ no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the periodic Tx ++ * FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ dwc_modify_reg32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * This function processes the currently active host channels and queues ++ * transactions for these channels to the DWC_otg controller. It is called ++ * from HCD interrupt handler functions. ++ * ++ * @hcd: The HCD state structure. ++ * @_tr_type: The type(s) of transactions to queue (non-periodic, ++ * periodic, or both). ++ */ ++void dwc_otg_hcd_queue_transactions(struct dwc_otg_hcd *hcd, ++ enum dwc_otg_transaction_type _tr_type) ++{ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); ++#endif ++ /* Process host channels associated with periodic transfers. */ ++ if ((_tr_type == DWC_OTG_TRANSACTION_PERIODIC || ++ _tr_type == DWC_OTG_TRANSACTION_ALL) && ++ !list_empty(&hcd->periodic_sched_assigned)) { ++ ++ process_periodic_channels(hcd); ++ } ++ ++ /* Process host channels associated with non-periodic transfers. */ ++ if ((_tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || ++ _tr_type == DWC_OTG_TRANSACTION_ALL)) { ++ if (!list_empty(&hcd->non_periodic_sched_active)) { ++ process_non_periodic_channels(hcd); ++ } else { ++ /* ++ * Ensure NP Tx FIFO empty interrupt is disabled when ++ * there are no non-periodic transfers to process. ++ */ ++ union gintmsk_data gintmsk = {.d32 = 0 }; ++ gintmsk.b.nptxfempty = 1; ++ dwc_modify_reg32(&hcd->core_if->core_global_regs-> ++ gintmsk, gintmsk.d32, 0); ++ } ++ } ++} ++ ++/** ++ * Sets the final status of an URB and returns it to the device driver. Any ++ * required cleanup of the URB is performed. ++ */ ++void dwc_otg_hcd_complete_urb(struct dwc_otg_hcd *hcd, struct urb *urb, ++ int status) ++{ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINT("%s: urb %p, device %d, ep %d %s, status=%d\n", ++ __func__, urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "IN" : "OUT", status); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINT(" ISO Desc %d status: %d\n", ++ i, urb->iso_frame_desc[i].status); ++ } ++ } ++ } ++#endif ++ ++ urb->status = status; ++ urb->hcpriv = NULL; ++ ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); ++} ++ ++/* ++ * Returns the Queue Head for an URB. ++ */ ++struct dwc_otg_qh *dwc_urb_to_qh(struct urb *urb) ++{ ++ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); ++ return ep->hcpriv; ++} ++ ++#ifdef DEBUG ++void dwc_print_setup_data(uint8_t *setup) ++{ ++ int i; ++ if (CHK_DEBUG_LEVEL(DBG_HCD)) { ++ DWC_PRINT("Setup Data = MSB "); ++ for (i = 7; i >= 0; i--) ++ DWC_PRINT("%02x ", setup[i]); ++ DWC_PRINT("\n"); ++ DWC_PRINT(" bmRequestType Tranfer = %s\n", ++ (setup[0] & 0x80) ? "Device-to-Host" : ++ "Host-to-Device"); ++ DWC_PRINT(" bmRequestType Type = "); ++ switch ((setup[0] & 0x60) >> 5) { ++ case 0: ++ DWC_PRINT("Standard\n"); ++ break; ++ case 1: ++ DWC_PRINT("Class\n"); ++ break; ++ case 2: ++ DWC_PRINT("Vendor\n"); ++ break; ++ case 3: ++ DWC_PRINT("Reserved\n"); ++ break; ++ } ++ DWC_PRINT(" bmRequestType Recipient = "); ++ switch (setup[0] & 0x1f) { ++ case 0: ++ DWC_PRINT("Device\n"); ++ break; ++ case 1: ++ DWC_PRINT("Interface\n"); ++ break; ++ case 2: ++ DWC_PRINT("Endpoint\n"); ++ break; ++ case 3: ++ DWC_PRINT("Other\n"); ++ break; ++ default: ++ DWC_PRINT("Reserved\n"); ++ break; ++ } ++ DWC_PRINT(" bRequest = 0x%0x\n", setup[1]); ++ DWC_PRINT(" wValue = 0x%0x\n", *((uint16_t *) &setup[2])); ++ DWC_PRINT(" wIndex = 0x%0x\n", *((uint16_t *) &setup[4])); ++ DWC_PRINT(" wLength = 0x%0x\n\n", *((uint16_t *) &setup[6])); ++ } ++} ++#endif ++ ++void dwc_otg_hcd_dump_frrem(struct dwc_otg_hcd *hcd) ++{ ++#ifdef DEBUG ++ DWC_PRINT("Frame remaining at SOF:\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->frrem_samples, hcd->frrem_accum, ++ (hcd->frrem_samples > 0) ? ++ hcd->frrem_accum / hcd->frrem_samples : 0); ++ ++ DWC_PRINT("\n"); ++ DWC_PRINT("Frame remaining at start_transfer (uframe 7):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->core_if->hfnum_7_samples, ++ hcd->core_if->hfnum_7_frrem_accum, ++ (hcd->core_if->hfnum_7_samples > ++ 0) ? hcd->core_if->hfnum_7_frrem_accum / ++ hcd->core_if->hfnum_7_samples : 0); ++ DWC_PRINT("Frame remaining at start_transfer (uframe 0):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->core_if->hfnum_0_samples, ++ hcd->core_if->hfnum_0_frrem_accum, ++ (hcd->core_if->hfnum_0_samples > ++ 0) ? hcd->core_if->hfnum_0_frrem_accum / ++ hcd->core_if->hfnum_0_samples : 0); ++ DWC_PRINT("Frame remaining at start_transfer (uframe 1-6):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->core_if->hfnum_other_samples, ++ hcd->core_if->hfnum_other_frrem_accum, ++ (hcd->core_if->hfnum_other_samples > ++ 0) ? hcd->core_if->hfnum_other_frrem_accum / ++ hcd->core_if->hfnum_other_samples : 0); ++ ++ DWC_PRINT("\n"); ++ DWC_PRINT("Frame remaining at sample point A (uframe 7):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, ++ (hcd->hfnum_7_samples_a > 0) ? ++ hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0); ++ DWC_PRINT("Frame remaining at sample point A (uframe 0):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, ++ (hcd->hfnum_0_samples_a > 0) ? ++ hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0); ++ DWC_PRINT("Frame remaining at sample point A (uframe 1-6):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, ++ (hcd->hfnum_other_samples_a > 0) ? ++ hcd->hfnum_other_frrem_accum_a / ++ hcd->hfnum_other_samples_a : 0); ++ ++ DWC_PRINT("\n"); ++ DWC_PRINT("Frame remaining at sample point B (uframe 7):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, ++ (hcd->hfnum_7_samples_b > 0) ? ++ hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0); ++ DWC_PRINT("Frame remaining at sample point B (uframe 0):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, ++ (hcd->hfnum_0_samples_b > 0) ? ++ hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0); ++ DWC_PRINT("Frame remaining at sample point B (uframe 1-6):\n"); ++ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", ++ hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, ++ (hcd->hfnum_other_samples_b > 0) ? ++ hcd->hfnum_other_frrem_accum_b / ++ hcd->hfnum_other_samples_b : 0); ++#endif ++} ++ ++void dwc_otg_hcd_dump_state(struct dwc_otg_hcd *hcd) ++{ ++#ifdef DEBUG ++ int num_channels; ++ int i; ++ union gnptxsts_data np_tx_status; ++ union hptxsts_data p_tx_status; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_PRINT("\n"); ++ DWC_PRINT ++ ("************************************************************\n"); ++ DWC_PRINT("HCD State:\n"); ++ DWC_PRINT(" Num channels: %d\n", num_channels); ++ for (i = 0; i < num_channels; i++) { ++ struct dwc_hc *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINT(" Channel %d:\n", i); ++ DWC_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINT(" speed: %d\n", hc->speed); ++ DWC_PRINT(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINT(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINT(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINT(" multi_count: %d\n", hc->multi_count); ++ DWC_PRINT(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINT(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINT(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINT(" xfer_count: %d\n", hc->xfer_count); ++ DWC_PRINT(" halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_PRINT(" halt_pending: %d\n", hc->halt_pending); ++ DWC_PRINT(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINT(" do_split: %d\n", hc->do_split); ++ DWC_PRINT(" complete_split: %d\n", hc->complete_split); ++ DWC_PRINT(" hub_addr: %d\n", hc->hub_addr); ++ DWC_PRINT(" port_addr: %d\n", hc->port_addr); ++ DWC_PRINT(" xact_pos: %d\n", hc->xact_pos); ++ DWC_PRINT(" requests: %d\n", hc->requests); ++ DWC_PRINT(" qh: %p\n", hc->qh); ++ if (hc->xfer_started) { ++ union hfnum_data hfnum; ++ union hcchar_data hcchar; ++ union hctsiz_data hctsiz; ++ union hcint_data hcint; ++ union hcintmsk_data hcintmsk; ++ hfnum.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if-> ++ host_global_regs->hfnum); ++ hcchar.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> ++ hcchar); ++ hctsiz.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> ++ hctsiz); ++ hcint.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> ++ hcint); ++ hcintmsk.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> ++ hcintmsk); ++ DWC_PRINT(" hfnum: 0x%08x\n", hfnum.d32); ++ DWC_PRINT(" hcchar: 0x%08x\n", hcchar.d32); ++ DWC_PRINT(" hctsiz: 0x%08x\n", hctsiz.d32); ++ DWC_PRINT(" hcint: 0x%08x\n", hcint.d32); ++ DWC_PRINT(" hcintmsk: 0x%08x\n", hcintmsk.d32); ++ } ++ if (hc->xfer_started && (hc->qh != NULL) ++ && (hc->qh->qtd_in_process != NULL)) { ++ struct dwc_otg_qtd *qtd; ++ struct urb *urb; ++ qtd = hc->qh->qtd_in_process; ++ urb = qtd->urb; ++ DWC_PRINT(" URB Info:\n"); ++ DWC_PRINT(" qtd: %p, urb: %p\n", qtd, urb); ++ if (urb != NULL) { ++ DWC_PRINT(" Dev: %d, EP: %d %s\n", ++ usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "IN" : "OUT"); ++ DWC_PRINT(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, ++ usb_pipeout(urb-> ++ pipe))); ++ DWC_PRINT(" transfer_buffer: %p\n", ++ urb->transfer_buffer); ++ DWC_PRINT(" transfer_dma: %p\n", ++ (void *)urb->transfer_dma); ++ DWC_PRINT(" transfer_buffer_length: %d\n", ++ urb->transfer_buffer_length); ++ DWC_PRINT(" actual_length: %d\n", ++ urb->actual_length); ++ } ++ } ++ } ++ DWC_PRINT(" non_periodic_channels: %d\n", hcd->non_periodic_channels); ++ DWC_PRINT(" periodic_channels: %d\n", hcd->periodic_channels); ++ DWC_PRINT(" periodic_usecs: %d\n", hcd->periodic_usecs); ++ np_tx_status.d32 = ++ dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts); ++ DWC_PRINT(" NP Tx Req Queue Space Avail: %d\n", ++ np_tx_status.b.nptxqspcavail); ++ DWC_PRINT(" NP Tx FIFO Space Avail: %d\n", ++ np_tx_status.b.nptxfspcavail); ++ p_tx_status.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts); ++ DWC_PRINT(" P Tx Req Queue Space Avail: %d\n", ++ p_tx_status.b.ptxqspcavail); ++ DWC_PRINT(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); ++ dwc_otg_hcd_dump_frrem(hcd); ++ dwc_otg_dump_global_registers(hcd->core_if); ++ dwc_otg_dump_host_registers(hcd->core_if); ++ DWC_PRINT ++ ("************************************************************\n"); ++ DWC_PRINT("\n"); ++#endif ++} ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +new file mode 100644 +index 0000000..6dcf1f5 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +@@ -0,0 +1,661 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef DWC_DEVICE_ONLY ++#if !defined(__DWC_HCD_H__) ++#define __DWC_HCD_H__ ++ ++#include ++#include ++#include ++ ++#include <../drivers/usb/core/hcd.h> ++ ++struct dwc_otg_device; ++ ++#include "dwc_otg_cil.h" ++ ++/** ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Host Contoller Driver (HCD). ++ * ++ * The Host Controller Driver (HCD) is responsible for translating requests ++ * from the USB Driver into the appropriate actions on the DWC_otg controller. ++ * It isolates the USBD from the specifics of the controller by providing an ++ * API to the USBD. ++ */ ++ ++/** ++ * Phases for control transfers. ++ */ ++enum dwc_otg_control_phase { ++ DWC_OTG_CONTROL_SETUP, ++ DWC_OTG_CONTROL_DATA, ++ DWC_OTG_CONTROL_STATUS ++}; ++ ++/** Transaction types. */ ++enum dwc_otg_transaction_type { ++ DWC_OTG_TRANSACTION_NONE, ++ DWC_OTG_TRANSACTION_PERIODIC, ++ DWC_OTG_TRANSACTION_NON_PERIODIC, ++ DWC_OTG_TRANSACTION_ALL ++}; ++ ++struct dwc_otg_qh; ++ ++/* ++ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, ++ * interrupt, or isochronous transfer. A single QTD is created for each URB ++ * (of one of these types) submitted to the HCD. The transfer associated with ++ * a QTD may require one or multiple transactions. ++ * ++ * A QTD is linked to a Queue Head, which is entered in either the ++ * non-periodic or periodic schedule for execution. When a QTD is chosen for ++ * execution, some or all of its transactions may be executed. After ++ * execution, the state of the QTD is updated. The QTD may be retired if all ++ * its transactions are complete or if an error occurred. Otherwise, it ++ * remains in the schedule so more transactions can be executed later. ++ */ ++struct dwc_otg_qtd { ++ /* ++ * Determines the PID of the next data packet for the data phase of ++ * control transfers. Ignored for other transfer types.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Current phase for control transfers (Setup, Data, or Status). */ ++ enum dwc_otg_control_phase control_phase; ++ ++ /** Keep track of the current split type ++ * for FS/LS endpoints on a HS Hub */ ++ uint8_t complete_split; ++ ++ /** How many bytes transferred during SSPLIT OUT */ ++ uint32_t ssplit_out_xfer_count; ++ ++ /** ++ * Holds the number of bus errors that have occurred for a transaction ++ * within this transfer. ++ */ ++ uint8_t error_count; ++ ++ /** ++ * Index of the next frame descriptor for an isochronous transfer. A ++ * frame descriptor describes the buffer position and length of the ++ * data to be transferred in the next scheduled (micro)frame of an ++ * isochronous transfer. It also holds status for that transaction. ++ * The frame index starts at 0. ++ */ ++ int isoc_frame_index; ++ ++ /** Position of the ISOC split on full/low speed */ ++ uint8_t isoc_split_pos; ++ ++ /** Position of the ISOC split in the buffer for the current frame */ ++ uint16_t isoc_split_offset; ++ ++ /** URB for this transfer */ ++ struct urb *urb; ++ ++ /* The queue head for this transfer. */ ++ struct dwc_otg_qh *qh; ++ ++ /** This list of QTDs */ ++ struct list_head qtd_list_entry; ++ ++}; ++ ++/** ++ * A Queue Head (QH) holds the static characteristics of an endpoint and ++ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may ++ * be entered in either the non-periodic or periodic schedule. ++ */ ++struct dwc_otg_qh { ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - USB_ENDPOINT_XFER_CONTROL ++ * - USB_ENDPOINT_XFER_ISOC ++ * - USB_ENDPOINT_XFER_BULK ++ * - USB_ENDPOINT_XFER_INT ++ */ ++ uint8_t ep_type; ++ uint8_t ep_is_in; ++ ++ /** wMaxPacketSize Field of Endpoint Descriptor. */ ++ uint16_t maxp; ++ ++ /** ++ * Determines the PID of the next data packet for non-control ++ * transfers. Ignored for control transfers.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Ping state if 1. */ ++ uint8_t ping_state; ++ ++ /** ++ * List of QTDs for this QH. ++ */ ++ struct list_head qtd_list; ++ ++ /** Host channel currently processing transfers for this QH. */ ++ struct dwc_hc *channel; ++ ++ /** QTD currently assigned to a host channel for this QH. */ ++ struct dwc_otg_qtd *qtd_in_process; ++ ++ /** Full/low speed endpoint on high-speed hub requires split. */ ++ uint8_t do_split; ++ ++ /** @name Periodic schedule information */ ++ /** @{ */ ++ ++ /** Bandwidth in microseconds per (micro)frame. */ ++ uint8_t usecs; ++ ++ /** Interval between transfers in (micro)frames. */ ++ uint16_t interval; ++ ++ /** ++ * (micro)frame to initialize a periodic transfer. The transfer ++ * executes in the following (micro)frame. ++ */ ++ uint16_t sched_frame; ++ ++ /** (micro)frame at which last start split was initialized. */ ++ uint16_t start_split_frame; ++ ++ /** @} */ ++ ++ /** Entry for QH in either the periodic or non-periodic schedule. */ ++ struct list_head qh_list_entry; ++}; ++ ++/** ++ * This structure holds the state of the HCD, including the non-periodic and ++ * periodic schedules. ++ */ ++struct dwc_otg_hcd { ++ ++ /** DWC OTG Core Interface Layer */ ++ struct dwc_otg_core_if *core_if; ++ ++ /** Internal DWC HCD Flags */ ++ union dwc_otg_hcd_internal_flags { ++ uint32_t d32; ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:26; ++ unsigned port_over_current_change:1; ++ unsigned port_suspend_change:1; ++ unsigned port_enable_change:1; ++ unsigned port_reset_change:1; ++ unsigned port_connect_status:1; ++ unsigned port_connect_status_change:1; ++#else ++ unsigned port_connect_status_change:1; ++ unsigned port_connect_status:1; ++ unsigned port_reset_change:1; ++ unsigned port_enable_change:1; ++ unsigned port_suspend_change:1; ++ unsigned port_over_current_change:1; ++ unsigned reserved:26; ++#endif ++ } b; ++ } flags; ++ ++ /** ++ * Inactive items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are not ++ * currently assigned to a host channel. ++ */ ++ struct list_head non_periodic_sched_inactive; ++ ++ /** ++ * Active items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are ++ * currently assigned to a host channel. ++ */ ++ struct list_head non_periodic_sched_active; ++ ++ /** ++ * Pointer to the next Queue Head to process in the active ++ * non-periodic schedule. ++ */ ++ struct list_head *non_periodic_qh_ptr; ++ ++ /** ++ * Inactive items in the periodic schedule. This is a list of QHs for ++ * periodic transfers that are _not_ scheduled for the next frame. ++ * Each QH in the list has an interval counter that determines when it ++ * needs to be scheduled for execution. This scheduling mechanism ++ * allows only a simple calculation for periodic bandwidth used (i.e. ++ * must assume that all periodic transfers may need to execute in the ++ * same frame). However, it greatly simplifies scheduling and should ++ * be sufficient for the vast majority of OTG hosts, which need to ++ * connect to a small number of peripherals at one time. ++ * ++ * Items move from this list to periodic_sched_ready when the QH ++ * interval counter is 0 at SOF. ++ */ ++ struct list_head periodic_sched_inactive; ++ ++ /** ++ * List of periodic QHs that are ready for execution in the next ++ * frame, but have not yet been assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_assigned as host ++ * channels become available during the current frame. ++ */ ++ struct list_head periodic_sched_ready; ++ ++ /** ++ * List of periodic QHs to be executed in the next frame that are ++ * assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_queued as the ++ * transactions for the QH are queued to the DWC_otg controller. ++ */ ++ struct list_head periodic_sched_assigned; ++ ++ /** ++ * List of periodic QHs that have been queued for execution. ++ * ++ * Items move from this list to either periodic_sched_inactive or ++ * periodic_sched_ready when the channel associated with the transfer ++ * is released. If the interval for the QH is 1, the item moves to ++ * periodic_sched_ready because it must be rescheduled for the next ++ * frame. Otherwise, the item moves to periodic_sched_inactive. ++ */ ++ struct list_head periodic_sched_queued; ++ ++ /** ++ * Total bandwidth claimed so far for periodic transfers. This value ++ * is in microseconds per (micro)frame. The assumption is that all ++ * periodic transfers may occur in the same (micro)frame. ++ */ ++ uint16_t periodic_usecs; ++ ++ /** ++ * Frame number read from the core at SOF. The value ranges from 0 to ++ * DWC_HFNUM_MAX_FRNUM. ++ */ ++ uint16_t frame_number; ++ ++ /** ++ * Free host channels in the controller. This is a list of ++ * struct dwc_hc items. ++ */ ++ struct list_head free_hc_list; ++ ++ /** ++ * Number of host channels assigned to periodic transfers. Currently ++ * assuming that there is a dedicated host channel for each periodic ++ * transaction and at least one host channel available for ++ * non-periodic transactions. ++ */ ++ int periodic_channels; ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int non_periodic_channels; ++ ++ /** ++ * Array of pointers to the host channel descriptors. Allows accessing ++ * a host channel descriptor given the host channel number. This is ++ * useful in interrupt handlers. ++ */ ++ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; ++ ++ /** ++ * Buffer to use for any data received during the status phase of a ++ * control transfer. Normally no data is transferred during the status ++ * phase. This buffer is used as a bit bucket. ++ */ ++ uint8_t *status_buf; ++ ++ /** ++ * DMA address for status_buf. ++ */ ++ dma_addr_t status_buf_dma; ++#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 ++ ++ /** ++ * Structure to allow starting the HCD in a non-interrupt context ++ * during an OTG role change. ++ */ ++ struct work_struct start_work; ++ ++ /** ++ * Connection timer. An OTG host must display a message if the device ++ * does not connect. Started when the VBus power is turned on via ++ * sysfs attribute "buspower". ++ */ ++ struct timer_list conn_timer; ++ ++ /* Tasket to do a reset */ ++ struct tasklet_struct *reset_tasklet; ++ ++ struct hrtimer poll_rate_limit; ++ ++ spinlock_t global_lock; ++ ++#ifdef DEBUG ++ uint32_t frrem_samples; ++ uint64_t frrem_accum; ++ ++ uint32_t hfnum_7_samples_a; ++ uint64_t hfnum_7_frrem_accum_a; ++ uint32_t hfnum_0_samples_a; ++ uint64_t hfnum_0_frrem_accum_a; ++ uint32_t hfnum_other_samples_a; ++ uint64_t hfnum_other_frrem_accum_a; ++ ++ uint32_t hfnum_7_samples_b; ++ uint64_t hfnum_7_frrem_accum_b; ++ uint32_t hfnum_0_samples_b; ++ uint64_t hfnum_0_frrem_accum_b; ++ uint32_t hfnum_other_samples_b; ++ uint64_t hfnum_other_frrem_accum_b; ++#endif ++ ++}; ++ ++/** Gets the dwc_otg_hcd from a struct usb_hcd */ ++static inline struct dwc_otg_hcd *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd) ++{ ++ return (struct dwc_otg_hcd *)(hcd->hcd_priv); ++} ++ ++/** Gets the struct usb_hcd that contains a struct dwc_otg_hcd. */ ++static inline struct usb_hcd *dwc_otg_hcd_to_hcd(struct dwc_otg_hcd ++ *dwc_otg_hcd) ++{ ++ return container_of((void *)dwc_otg_hcd, struct usb_hcd, hcd_priv); ++} ++ ++/** @name HCD Create/Destroy Functions */ ++/** @{ */ ++extern int __init dwc_otg_hcd_init(struct device *_dev); ++extern void dwc_otg_hcd_remove(struct device *_dev); ++/** @} */ ++ ++/** @name Linux HC Driver API Functions */ ++ ++extern int dwc_otg_hcd_start(struct usb_hcd *hcd); ++extern void dwc_otg_hcd_stop(struct usb_hcd *hcd); ++extern int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd); ++extern void dwc_otg_hcd_free(struct usb_hcd *hcd); ++extern int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, ++ struct urb *urb, unsigned mem_flags); ++extern int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, ++ struct urb *urb, int status); ++extern void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd, ++ struct usb_host_endpoint *ep); ++extern irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); ++extern int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, char *buf); ++extern int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, ++ u16 typeReq, ++ u16 wValue, ++ u16 wIndex, char *buf, u16 wLength); ++ ++ ++/** @name Transaction Execution Functions */ ++extern enum dwc_otg_transaction_type dwc_otg_hcd_select_transactions(struct ++ dwc_otg_hcd ++ *hcd); ++extern void dwc_otg_hcd_queue_transactions(struct dwc_otg_hcd *hcd, ++ enum dwc_otg_transaction_type tr_type); ++extern void dwc_otg_hcd_complete_urb(struct dwc_otg_hcd *hcd, struct urb *urb, ++ int status); ++ ++/** @name Interrupt Handler Functions */ ++extern int32_t dwc_otg_hcd_handle_intr(struct dwc_otg_hcd *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_sof_intr(struct dwc_otg_hcd *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_port_intr(struct dwc_otg_hcd *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_disconnect_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_intr(struct dwc_otg_hcd *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_n_intr(struct dwc_otg_hcd *dwc_otg_hcd, ++ uint32_t num); ++extern int32_t dwc_otg_hcd_handle_session_req_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(struct dwc_otg_hcd ++ *dwc_otg_hcd); ++ ++/** @name Schedule Queue Functions */ ++ ++/* Implemented in dwc_otg_hcd_queue.c */ ++extern struct dwc_otg_qh *dwc_otg_hcd_qh_create(struct dwc_otg_hcd *hcd, ++ struct urb *urb); ++extern void dwc_otg_hcd_qh_init(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh, ++ struct urb *urb); ++extern void dwc_otg_hcd_qh_free(struct dwc_otg_qh *qh); ++extern int dwc_otg_hcd_qh_add(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh); ++extern void dwc_otg_hcd_qh_remove(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh); ++extern void dwc_otg_hcd_qh_deactivate(struct dwc_otg_hcd *hcd, ++ struct dwc_otg_qh *qh, int sched_csplit); ++ ++/** Remove and free a QH */ ++static inline void dwc_otg_hcd_qh_remove_and_free(struct dwc_otg_hcd *hcd, ++ struct dwc_otg_qh *qh) ++{ ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ dwc_otg_hcd_qh_free(qh); ++} ++ ++/** Allocates memory for a QH structure. ++ * Returns Returns the memory allocate or NULL on error. */ ++static inline struct dwc_otg_qh *dwc_otg_hcd_qh_alloc(void) ++{ ++ return kmalloc(sizeof(struct dwc_otg_qh), GFP_ATOMIC); ++} ++ ++extern struct dwc_otg_qtd *dwc_otg_hcd_qtd_create(struct urb *urb); ++extern void dwc_otg_hcd_qtd_init(struct dwc_otg_qtd *qtd, struct urb *urb); ++extern int dwc_otg_hcd_qtd_add(struct dwc_otg_qtd *qtd, ++ struct dwc_otg_hcd *dwc_otg_hcd); ++ ++/** Allocates memory for a QTD structure. ++ * Returns Returns the memory allocate or NULL on error. */ ++static inline struct dwc_otg_qtd *dwc_otg_hcd_qtd_alloc(void) ++{ ++ return kmalloc(sizeof(struct dwc_otg_qtd), GFP_ATOMIC); ++} ++ ++/** ++ * Frees the memory for a QTD structure. QTD should already be removed from ++ * list. ++ * @qtd: QTD to free. ++ */ ++static inline void dwc_otg_hcd_qtd_free(struct dwc_otg_qtd *qtd) ++{ ++ kfree(qtd); ++} ++ ++/** ++ * Removes a QTD from list. ++ * @qtd: QTD to remove from list. ++ */ ++static inline void dwc_otg_hcd_qtd_remove(struct dwc_otg_qtd *qtd) ++{ ++ list_del(&qtd->qtd_list_entry); ++} ++ ++/** Remove and free a QTD */ ++static inline void dwc_otg_hcd_qtd_remove_and_free(struct dwc_otg_qtd *qtd) ++{ ++ dwc_otg_hcd_qtd_remove(qtd); ++ dwc_otg_hcd_qtd_free(qtd); ++} ++ ++/** @name Internal Functions */ ++struct dwc_otg_qh *dwc_urb_to_qh(struct urb *urb); ++void dwc_otg_hcd_dump_frrem(struct dwc_otg_hcd *hcd); ++void dwc_otg_hcd_dump_state(struct dwc_otg_hcd *hcd); ++ ++/** Gets the usb_host_endpoint associated with an URB. */ ++static inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) ++{ ++ struct usb_device *dev = urb->dev; ++ int ep_num = usb_pipeendpoint(urb->pipe); ++ ++ if (usb_pipein(urb->pipe)) ++ return dev->ep_in[ep_num]; ++ else ++ return dev->ep_out[ep_num]; ++} ++ ++/* ++ * Gets the endpoint number from a bEndpointAddress argument. The endpoint is ++ * qualified with its direction (possible 32 endpoints per device). ++ */ ++#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) \ ++ ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ ++ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) ++ ++/** Gets the QH that contains the list_head */ ++#define dwc_list_to_qh(_list_head_ptr_) \ ++ (container_of(_list_head_ptr_, struct dwc_otg_qh, qh_list_entry)) ++ ++/** Gets the QTD that contains the list_head */ ++#define dwc_list_to_qtd(_list_head_ptr_) \ ++ (container_of(_list_head_ptr_, struct dwc_otg_qtd, qtd_list_entry)) ++ ++/** Check if QH is non-periodic */ ++#define dwc_qh_is_non_per(_qh_ptr_) \ ++ ((_qh_ptr_->ep_type == USB_ENDPOINT_XFER_BULK) || \ ++ (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL)) ++ ++/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ ++#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) ++ ++/** Packet size for any kind of endpoint descriptor */ ++#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) ++ ++/** ++ * Returns true if frame1 is less than or equal to frame2. The comparison is ++ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the ++ * frame number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) ++{ ++ return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= ++ (DWC_HFNUM_MAX_FRNUM >> 1); ++} ++ ++/** ++ * Returns true if frame1 is greater than frame2. The comparison is done ++ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame ++ * number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) ++{ ++ return (frame1 != frame2) && ++ (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < ++ (DWC_HFNUM_MAX_FRNUM >> 1)); ++} ++ ++/** ++ * Increments frame by the amount specified by inc. The addition is done ++ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. ++ */ ++static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) ++{ ++ return (frame + inc) & DWC_HFNUM_MAX_FRNUM; ++} ++ ++static inline uint16_t dwc_full_frame_num(uint16_t frame) ++{ ++ return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; ++} ++ ++static inline uint16_t dwc_micro_frame_num(uint16_t frame) ++{ ++ return frame & 0x7; ++} ++ ++#ifdef DEBUG ++/** ++ * Macro to sample the remaining PHY clocks left in the current frame. This ++ * may be used during debugging to determine the average time it takes to ++ * execute sections of code. There are two possible sample points, "a" and ++ * "b", so the letter argument must be one of these values. ++ * ++ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For ++ * example, "cat /sys/devices/lm0/hcd_frrem". ++ */ ++#define dwc_sample_frrem(_hcd, _qh, _letter) \ ++{ \ ++ union hfnum_data hfnum; \ ++ struct dwc_otg_qtd *qtd; \ ++ qtd = list_entry(_qh->qtd_list.next, struct dwc_otg_qtd, qtd_list_entry); \ ++ if (usb_pipeint(qtd->urb->pipe) && qh->start_split_frame != 0 && !qtd->complete_split) { \ ++ hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ ++ switch (hfnum.b.frnum & 0x7) { \ ++ case 7: \ ++ _hcd->hfnum_7_samples_##_letter++; \ ++ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ case 0: \ ++ _hcd->hfnum_0_samples_##_letter++; \ ++ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ default: \ ++ _hcd->hfnum_other_samples_##_letter++; \ ++ _hcd->hfnum_other_frrem_accum_##_letter += \ ++ hfnum.b.frrem; \ ++ break; \ ++ } \ ++ } \ ++} ++#else ++#define dwc_sample_frrem(hcd, qh, letter) ++#endif ++#endif ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +new file mode 100644 +index 0000000..2c4266f +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -0,0 +1,1890 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef DWC_DEVICE_ONLY ++ ++#include "dwc_otg_driver.h" ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++/* ++ * This file contains the implementation of the HCD Interrupt handlers. ++ */ ++ ++/* This function handles interrupts for the HCD. */ ++int32_t dwc_otg_hcd_handle_intr(struct dwc_otg_hcd *dwc_otg_hcd) ++{ ++ int retval = 0; ++ ++ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; ++ union gintsts_data gintsts; ++#ifdef DEBUG ++ struct dwc_otg_core_global_regs *global_regs = ++ core_if->core_global_regs; ++#endif ++ ++ /* Check if HOST Mode */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ gintsts.d32 = dwc_otg_read_core_intr(core_if); ++ if (!gintsts.d32) ++ return 0; ++#ifdef DEBUG ++ /* Don't print debug message in the interrupt handler on SOF */ ++# ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++# endif ++ DWC_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++#ifdef DEBUG ++# ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++# endif ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Interrupt Detected " ++ "gintsts&gintmsk=0x%08x\n", ++ gintsts.d32); ++#endif ++ ++ if (gintsts.b.sofintr) ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ ++ if (gintsts.b.rxstsqlvl) ++ retval |= ++ dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd); ++ ++ if (gintsts.b.nptxfempty) ++ retval |= ++ dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd); ++ ++ if (gintsts.b.i2cintr) ++ ;/** @todo Implement i2cintr handler. */ ++ ++ if (gintsts.b.portintr) ++ retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); ++ ++ if (gintsts.b.hcintr) ++ retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); ++ ++ if (gintsts.b.ptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_perio_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++#ifdef DEBUG ++# ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++# endif ++ { ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD Finished Servicing Interrupts\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", ++ dwc_read_reg32(&global_regs->gintsts)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", ++ dwc_read_reg32(&global_regs->gintmsk)); ++ } ++#endif ++ ++#ifdef DEBUG ++# ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++# endif ++ DWC_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++ } ++ ++ return retval; ++} ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++#warning Compiling code to track missed SOFs ++#define FRAME_NUM_ARRAY_SIZE 1000 ++/** ++ * This function is for debug only. ++ */ ++static inline void track_missed_sofs(uint16_t _curr_frame_number) ++{ ++ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static int frame_num_idx; ++ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; ++ static int dumped_frame_num_array; ++ ++ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { ++ if ((((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != ++ _curr_frame_number)) { ++ frame_num_array[frame_num_idx] = _curr_frame_number; ++ last_frame_num_array[frame_num_idx++] = last_frame_num; ++ } ++ } else if (!dumped_frame_num_array) { ++ int i; ++ printk(KERN_EMERG USB_DWC "Frame Last Frame\n"); ++ printk(KERN_EMERG USB_DWC "----- ----------\n"); ++ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { ++ printk(KERN_EMERG USB_DWC "0x%04x 0x%04x\n", ++ frame_num_array[i], last_frame_num_array[i]); ++ } ++ dumped_frame_num_array = 1; ++ } ++ last_frame_num = _curr_frame_number; ++} ++#endif ++ ++/** ++ * Handles the start-of-frame interrupt in host mode. Non-periodic ++ * transactions may be queued to the DWC_otg controller for the current ++ * (micro)frame. Periodic transactions may be queued to the controller for the ++ * next (micro)frame. ++ */ ++int32_t dwc_otg_hcd_handle_sof_intr(struct dwc_otg_hcd *hcd) ++{ ++ union hfnum_data hfnum; ++ struct list_head *qh_entry; ++ struct dwc_otg_qh *qh; ++ enum dwc_otg_transaction_type tr_type; ++ union gintsts_data gintsts = {.d32 = 0 }; ++ ++ hfnum.d32 = ++ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); ++#endif ++ ++ hcd->frame_number = hfnum.b.frnum; ++ ++#ifdef DEBUG ++ hcd->frrem_accum += hfnum.b.frrem; ++ hcd->frrem_samples++; ++#endif ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++ track_missed_sofs(hcd->frame_number); ++#endif ++ ++ /* Determine whether any periodic QHs should be executed. */ ++ qh_entry = hcd->periodic_sched_inactive.next; ++ while (qh_entry != &hcd->periodic_sched_inactive) { ++ qh = list_entry(qh_entry, struct dwc_otg_qh, qh_list_entry); ++ qh_entry = qh_entry->next; ++ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { ++ /* ++ * Move QH to the ready list to be executed next ++ * (micro)frame. ++ */ ++ list_move(&qh->qh_list_entry, ++ &hcd->periodic_sched_ready); ++ } ++ } ++ ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } else if (list_empty(&hcd->periodic_sched_inactive) && ++ list_empty(&hcd->periodic_sched_ready) && ++ list_empty(&hcd->periodic_sched_assigned) && ++ list_empty(&hcd->periodic_sched_queued)) { ++ /* ++ * We don't have USB data to send. Unfortunately the ++ * Synopsis block continues to generate interrupts at ++ * about 8k/sec. In order not waste time on these ++ * useless interrupts, we're going to disable the SOF ++ * interrupt. It will be re-enabled when a new packet ++ * is enqueued in dwc_otg_hcd_urb_enqueue() ++ */ ++ dwc_modify_reg32(&hcd->core_if->core_global_regs->gintmsk, ++ DWC_SOF_INTR_MASK, 0); ++ } ++ ++ /* Clear interrupt */ ++ gintsts.b.sofintr = 1; ++ dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/* Handles the Rx Status Queue Level Interrupt, which indicates that ++ * there is at least one packet in the Rx FIFO. The packets are moved ++ * from the FIFO to memory if the DWC_otg controller is operating in ++ * Slave mode. */ ++int32_t ++dwc_otg_hcd_handle_rx_status_q_level_intr(struct dwc_otg_hcd *dwc_otg_hcd) ++{ ++ union host_grxsts_data grxsts; ++ struct dwc_hc *hc = NULL; ++ ++ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); ++ ++ grxsts.d32 = ++ dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; ++ ++ /* Packet Status */ ++ DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); ++ DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); ++ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, ++ hc->data_pid_start); ++ DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer. */ ++ if (grxsts.b.bcnt > 0) { ++ dwc_otg_read_packet(dwc_otg_hcd->core_if, ++ hc->xfer_buff, grxsts.b.bcnt); ++ ++ /* Update the HC fields for the next packet received. */ ++ hc->xfer_count += grxsts.b.bcnt; ++ hc->xfer_buff += grxsts.b.bcnt; ++ } ++ ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: ++ case DWC_GRXSTS_PKTSTS_CH_HALTED: ++ /* Handled in interrupt, just ignore data */ ++ break; ++ default: ++ DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", ++ grxsts.b.pktsts); ++ break; ++ } ++ ++ return 1; ++} ++ ++/* This interrupt occurs when the non-periodic Tx FIFO is ++ * half-empty. More data packets may be written to the FIFO for OUT ++ * transfers. More requests may be written to the non-periodic request ++ * queue for IN transfers. This interrupt is enabled only in Slave ++ * mode. */ ++int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(struct dwc_otg_hcd * ++ dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_NON_PERIODIC); ++ return 1; ++} ++ ++/* This interrupt occurs when the periodic Tx FIFO is half-empty. More ++ * data packets may be written to the FIFO for OUT transfers. More ++ * requests may be written to the periodic request queue for IN ++ * transfers. This interrupt is enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(struct dwc_otg_hcd * ++ dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_PERIODIC); ++ return 1; ++} ++ ++/* There are multiple conditions that can cause a port interrupt. This ++ * function determines which interrupt conditions have occurred and ++ * handles them appropriately. */ ++int32_t dwc_otg_hcd_handle_port_intr(struct dwc_otg_hcd *dwc_otg_hcd) ++{ ++ int retval = 0; ++ union hprt0_data hprt0; ++ union hprt0_data hprt0_modify; ++ ++ hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); ++ hprt0_modify.d32 = ++ dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); ++ ++ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in ++ * GINTSTS */ ++ ++ hprt0_modify.b.prtena = 0; ++ hprt0_modify.b.prtconndet = 0; ++ hprt0_modify.b.prtenchng = 0; ++ hprt0_modify.b.prtovrcurrchng = 0; ++ ++ /* Port Connect Detected ++ * Set flag and clear if detected */ ++ if (hprt0.b.prtconndet) { ++ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " ++ "Port Connect Detected--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 1; ++ hprt0_modify.b.prtconndet = 1; ++ ++ /* B-Device has connected, Delete the connection timer. */ ++ del_timer(&dwc_otg_hcd->conn_timer); ++ ++ /* The Hub driver asserts a reset when it sees port connect ++ * status change flag */ ++ retval |= 1; ++ } ++ ++ /* Port Enable Changed ++ * Clear if detected - Set internal flag if disabled */ ++ if (hprt0.b.prtenchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Enable Changed--\n", hprt0.d32); ++ hprt0_modify.b.prtenchng = 1; ++ if (hprt0.b.prtena == 1) { ++ int do_reset = 0; ++ struct dwc_otg_core_params *params = ++ dwc_otg_hcd->core_if->core_params; ++ struct dwc_otg_core_global_regs *global_regs = ++ dwc_otg_hcd->core_if->core_global_regs; ++ struct dwc_otg_host_if *host_if = ++ dwc_otg_hcd->core_if->host_if; ++ ++ /* Check if we need to adjust the PHY clock speed for ++ * low power and adjust it */ ++ if (params->host_support_fs_ls_low_power) { ++ union gusbcfg_data usbcfg; ++ ++ usbcfg.d32 = ++ dwc_read_reg32(&global_regs->gusbcfg); ++ ++ if ((hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) ++ || (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED)) { ++ /* ++ * Low power ++ */ ++ union hcfg_data hcfg; ++ if (usbcfg.b.phylpwrclksel == 0) { ++ /* Set PHY low power clock select for FS/LS devices */ ++ usbcfg.b.phylpwrclksel = 1; ++ dwc_write_reg32(&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ ++ hcfg.d32 = ++ dwc_read_reg32(&host_if->host_global_regs->hcfg); ++ ++ if ((hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_LOW_SPEED) ++ && (params-> ++ host_ls_low_power_phy_clk == ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) { ++ /* 6 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_6_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_6_MHZ; ++ dwc_write_reg32(&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } else { ++ /* 48 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 48 MHz ()\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_48_MHZ) { ++ hcfg.b.fslspclksel = DWC_HCFG_48_MHZ; ++ dwc_write_reg32(&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } ++ } else { ++ /* ++ * Not low power ++ */ ++ if (usbcfg.b.phylpwrclksel == 1) { ++ usbcfg.b.phylpwrclksel = 0; ++ dwc_write_reg32(&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ } ++ if (do_reset) ++ tasklet_schedule(dwc_otg_hcd->reset_tasklet); ++ } ++ if (!do_reset) ++ /* ++ * Port has been enabled set the reset ++ * change flag ++ */ ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++ } else { ++ dwc_otg_hcd->flags.b.port_enable_change = 1; ++ } ++ retval |= 1; ++ } ++ ++ /** Overcurrent Change Interrupt */ ++ if (hprt0.b.prtovrcurrchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Overcurrent Changed--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_over_current_change = 1; ++ hprt0_modify.b.prtovrcurrchng = 1; ++ retval |= 1; ++ } ++ ++ /* Clear Port Interrupts */ ++ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, ++ hprt0_modify.d32); ++ ++ return retval; ++} ++ ++/** This interrupt indicates that one or more host channels has a pending ++ * interrupt. There are multiple conditions that can cause each host channel ++ * interrupt. This function determines which conditions have occurred for each ++ * host channel interrupt and handles them appropriately. */ ++int32_t dwc_otg_hcd_handle_hc_intr(struct dwc_otg_hcd *dwc_otg_hcd) ++{ ++ int i; ++ int retval = 0; ++ union haint_data haint; ++ ++ /* Clear appropriate bits in HCINTn to clear the interrupt bit in ++ * GINTSTS */ ++ ++ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); ++ ++ for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { ++ if (haint.b2.chint & (1 << i)) ++ retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); ++ } ++ ++ return retval; ++} ++ ++/* Macro used to clear one channel interrupt */ ++#define clear_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ union hcint_data hcint_clear = {.d32 = 0}; \ ++ hcint_clear.b._intr_ = 1; \ ++ dwc_write_reg32(&((_hc_regs_)->hcint), hcint_clear.d32); \ ++} while (0) ++ ++/* ++ * Macro used to disable one channel interrupt. Channel interrupts are ++ * disabled when the channel is halted or released by the interrupt handler. ++ * There is no need to handle further interrupts of that type until the ++ * channel is re-assigned. In fact, subsequent handling may cause crashes ++ * because the channel structures are cleaned up when the channel is released. ++ */ ++#define disable_hc_int(_hc_regs_, _intr_) \ ++ do { \ ++ union hcintmsk_data hcintmsk = {.d32 = 0}; \ ++ hcintmsk.b._intr_ = 1; \ ++ dwc_modify_reg32(&((_hc_regs_)->hcintmsk), hcintmsk.d32, 0); \ ++ } while (0) ++ ++/** ++ * Gets the actual length of a transfer after the transfer halts. _halt_status ++ * holds the reason for the halt. ++ * ++ * For IN transfers where _halt_status is DWC_OTG_HC_XFER_COMPLETE, ++ * *_short_read is set to 1 upon return if less than the requested ++ * number of bytes were transferred. Otherwise, *_short_read is set to 0 upon ++ * return. _short_read may also be NULL on entry, in which case it remains ++ * unchanged. ++ */ ++static uint32_t get_actual_xfer_length(struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status _halt_status, ++ int *_short_read) ++{ ++ union hctsiz_data hctsiz; ++ uint32_t length; ++ ++ if (_short_read != NULL) ++ *_short_read = 0; ++ ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ ++ if (_halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ if (hc->ep_is_in) { ++ length = hc->xfer_len - hctsiz.b.xfersize; ++ if (_short_read != NULL) ++ *_short_read = (hctsiz.b.xfersize != 0); ++ } else if (hc->qh->do_split) { ++ length = qtd->ssplit_out_xfer_count; ++ } else { ++ length = hc->xfer_len; ++ } ++ } else { ++ /* ++ * Must use the hctsiz.pktcnt field to determine how much data ++ * has been transferred. This field reflects the number of ++ * packets that have been transferred via the USB. This is ++ * always an integral number of packets if the transfer was ++ * halted before its normal completion. (Can't use the ++ * hctsiz.xfersize field because that reflects the number of ++ * bytes transferred via the AHB, not the USB). ++ */ ++ length = ++ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; ++ } ++ ++ return length; ++} ++ ++/** ++ * Updates the state of the URB after a Transfer Complete interrupt on the ++ * host channel. Updates the actual_length field of the URB based on the ++ * number of bytes transferred via the host channel. Sets the URB status ++ * if the data transfer is finished. ++ * ++ * Returns 1 if the data transfer specified by the URB is completely finished, ++ * 0 otherwise. ++ */ ++static int update_urb_state_xfer_comp(struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct urb *urb, struct dwc_otg_qtd *qtd) ++{ ++ int xfer_done = 0; ++ int short_read = 0; ++ ++ urb->actual_length += get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, ++ &short_read); ++ ++ if (short_read || (urb->actual_length == urb->transfer_buffer_length)) { ++ xfer_done = 1; ++ if (short_read && (urb->transfer_flags & URB_SHORT_NOT_OK)) ++ urb->status = -EREMOTEIO; ++ else ++ urb->status = 0; ++ } ++#ifdef DEBUG ++ { ++ union hctsiz_data hctsiz; ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", ++ hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->transfer_buffer_length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", ++ short_read, xfer_done); ++ } ++#endif ++ ++ return xfer_done; ++} ++ ++/* ++ * Save the starting data toggle for the next transfer. The data toggle is ++ * saved in the QH for non-control transfers and it's saved in the QTD for ++ * control transfers. ++ */ ++static void save_data_toggle(struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ union hctsiz_data hctsiz; ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { ++ struct dwc_otg_qh *qh = hc->qh; ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ else ++ qh->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } else { ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA0; ++ else ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++} ++ ++/** ++ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic ++ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are ++ * still linked to the QH, the QH is added to the end of the inactive ++ * non-periodic schedule. For periodic QHs, removes the QH from the periodic ++ * schedule if no more QTDs are linked to the QH. ++ */ ++static void deactivate_qh(struct dwc_otg_hcd *hcd, ++ struct dwc_otg_qh *qh, int free_qtd) ++{ ++ int continue_split = 0; ++ struct dwc_otg_qtd *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); ++ ++ qtd = list_entry(qh->qtd_list.next, struct dwc_otg_qtd, qtd_list_entry); ++ ++ if (qtd->complete_split) { ++ continue_split = 1; ++ } else if ((qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID) || ++ (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END)) { ++ continue_split = 1; ++ } ++ ++ if (free_qtd) { ++ dwc_otg_hcd_qtd_remove_and_free(qtd); ++ continue_split = 0; ++ } ++ ++ qh->channel = NULL; ++ qh->qtd_in_process = NULL; ++ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); ++} ++ ++/** ++ * Updates the state of an Isochronous URB when the transfer is stopped for ++ * any reason. The fields of the current entry in the frame descriptor array ++ * are set based on the transfer state and the input _halt_status. Completes ++ * the Isochronous URB if all the URB frames have been completed. ++ * ++ * Returns DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be ++ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE. ++ */ ++static enum dwc_otg_halt_status ++update_isoc_urb_state(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status halt_status) ++{ ++ struct urb *urb = qtd->urb; ++ enum dwc_otg_halt_status ret_val = halt_status; ++ struct usb_iso_packet_descriptor *frame_desc; ++ ++ frame_desc = &urb->iso_frame_desc[qtd->isoc_frame_index]; ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_COMPLETE: ++ frame_desc->status = 0; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ break; ++ case DWC_OTG_HC_XFER_FRAME_OVERRUN: ++ urb->error_count++; ++ if (hc->ep_is_in) ++ frame_desc->status = -ENOSR; ++ else ++ frame_desc->status = -ECOMM; ++ frame_desc->actual_length = 0; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->error_count++; ++ frame_desc->status = -EOVERFLOW; ++ /* Don't need to update actual_length in this case. */ ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->error_count++; ++ frame_desc->status = -EPROTO; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ break; ++ default: ++ DWC_ERROR("%s: Unhandled halt_status (%d)\n", __func__, ++ halt_status); ++ BUG(); ++ break; ++ } ++ ++ if (++qtd->isoc_frame_index == urb->number_of_packets) { ++ /* ++ * urb->status is not used for isoc transfers. ++ * The individual frame_desc statuses are used instead. ++ */ ++ dwc_otg_hcd_complete_urb(hcd, urb, 0); ++ qtd->urb = NULL; ++ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ ret_val = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * Releases a host channel for use by other transfers. Attempts to select and ++ * queue more transactions since at least one host channel is available. ++ * ++ * @hcd: The HCD state structure. ++ * @hc: The host channel to release. ++ * @qtd: The QTD associated with the host channel. This QTD may be freed ++ * if the transfer is complete or an error has occurred. ++ * @_halt_status: Reason the channel is being released. This status ++ * determines the actions taken by this function. ++ */ ++static void release_channel(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status halt_status) ++{ ++ enum dwc_otg_transaction_type tr_type; ++ int free_qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n", ++ __func__, hc->hc_num, halt_status); ++ ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_URB_COMPLETE: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_AHB_ERR: ++ case DWC_OTG_HC_XFER_STALL: ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ if (qtd->error_count >= 3) { ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with transaction error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -EPROTO; ++ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPROTO); ++ qtd->urb = NULL; ++ } else { ++ free_qtd = 0; ++ } ++ break; ++ case DWC_OTG_HC_XFER_URB_DEQUEUE: ++ /* ++ * The QTD has already been removed and the QH has been ++ * deactivated. Don't want to do anything except release the ++ * host channel and try to queue more transfers. ++ */ ++ goto cleanup; ++ case DWC_OTG_HC_XFER_NO_HALT_STATUS: ++ DWC_ERROR("%s: No halt_status, channel %d\n", __func__, ++ hc->hc_num); ++ free_qtd = 0; ++ break; ++ default: ++ free_qtd = 0; ++ break; ++ } ++ ++ deactivate_qh(hcd, hc->qh, free_qtd); ++ ++cleanup: ++ /* ++ * Release the host channel for use by other transfers. The cleanup ++ * function clears the channel interrupt enables and conditions, so ++ * there's no need to clear the Channel Halted interrupt separately. ++ */ ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ list_add_tail(&hc->hc_list_entry, &hcd->free_hc_list); ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hcd->non_periodic_channels--; ++ break; ++ ++ default: ++ /* ++ * Don't release reservations for periodic channels here. ++ * That's done when a periodic transfer is descheduled (i.e. ++ * when the QH is removed from the periodic schedule). ++ */ ++ break; ++ } ++ ++ /* Try to queue more transfers now that there's a free channel. */ ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++} ++ ++/** ++ * Halts a host channel. If the channel cannot be halted immediately because ++ * the request queue is full, this function ensures that the FIFO empty ++ * interrupt for the appropriate queue is enabled so that the halt request can ++ * be queued when there is space in the request queue. ++ * ++ * This function may also be called in DMA mode. In that case, the channel is ++ * simply released since the core always halts the channel automatically in ++ * DMA mode. ++ */ ++static void halt_channel(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status halt_status) ++{ ++ if (hcd->core_if->dma_enable) { ++ release_channel(hcd, hc, qtd, halt_status); ++ return; ++ } ++ ++ /* Slave mode processing... */ ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ ++ if (hc->halt_on_queue) { ++ union gintmsk_data gintmsk = {.d32 = 0 }; ++ struct dwc_otg_core_global_regs *global_regs; ++ global_regs = hcd->core_if->core_global_regs; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ /* ++ * Make sure the Non-periodic Tx FIFO empty interrupt ++ * is enabled so that the non-periodic schedule will ++ * be processed. ++ */ ++ gintmsk.b.nptxfempty = 1; ++ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } else { ++ /* ++ * Move the QH from the periodic queued schedule to ++ * the periodic assigned schedule. This allows the ++ * halt to be queued when the periodic schedule is ++ * processed. ++ */ ++ list_move(&hc->qh->qh_list_entry, ++ &hcd->periodic_sched_assigned); ++ ++ /* ++ * Make sure the Periodic Tx FIFO Empty interrupt is ++ * enabled so that the periodic schedule will be ++ * processed. ++ */ ++ gintmsk.b.ptxfempty = 1; ++ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ } ++} ++ ++/** ++ * Performs common cleanup for non-periodic transfers after a Transfer ++ * Complete interrupt. This function should be called after any endpoint type ++ * specific handling is finished to release the host channel. ++ */ ++static void complete_non_periodic_xfer(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status halt_status) ++{ ++ union hcint_data hcint; ++ ++ qtd->error_count = 0; ++ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. This ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ hc->qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ /* ++ * Always halt and release the host channel to make it available for ++ * more transfers. There may still be more phases for a control ++ * transfer or more data packets for a bulk transfer at this point, ++ * but the host channel is still halted. A channel will be reassigned ++ * to the transfer when the non-periodic schedule is processed after ++ * the channel is released. This allows transactions to be queued ++ * properly via dwc_otg_hcd_queue_transactions, which also enables the ++ * Tx FIFO Empty interrupt if necessary. ++ */ ++ if (hc->ep_is_in) { ++ /* ++ * IN transfers in Slave mode require an explicit disable to ++ * halt the channel. (In DMA mode, this call simply releases ++ * the channel.) ++ */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* ++ * The channel is automatically disabled by the core for OUT ++ * transfers in Slave mode. ++ */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++/** ++ * Performs common cleanup for periodic transfers after a Transfer Complete ++ * interrupt. This function should be called after any endpoint type specific ++ * handling is finished to release the host channel. ++ */ ++static void complete_periodic_xfer(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status halt_status) ++{ ++ union hctsiz_data hctsiz; ++ qtd->error_count = 0; ++ ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { ++ /* Core halts channel in these cases. */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* Flush any outstanding requests from the Tx queue. */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++/** ++ * Handles a host channel Transfer Complete interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xfercomp_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ int urb_xfer_done; ++ enum dwc_otg_halt_status halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ struct urb *urb = qtd->urb; ++ int pipe_type = usb_pipetype(urb->pipe); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transfer Complete--\n", hc->hc_num); ++ ++ /* ++ * Handle xfer complete on CSPLIT. ++ */ ++ if (hc->qh->do_split) ++ qtd->complete_split = 0; ++ ++ /* Update the QTD and URB states. */ ++ switch (pipe_type) { ++ case PIPE_CONTROL: ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ if (urb->transfer_buffer_length > 0) ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ else ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control setup transaction done\n"); ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ case DWC_OTG_CONTROL_DATA:{ ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, ++ urb, qtd); ++ if (urb_xfer_done) { ++ qtd->control_phase = ++ DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control data transfer done\n"); ++ } else { ++ save_data_toggle(hc, hc_regs, qtd); ++ } ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ } ++ case DWC_OTG_CONTROL_STATUS: ++ DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); ++ if (urb->status == -EINPROGRESS) ++ urb->status = 0; ++ dwc_otg_hcd_complete_urb(hcd, urb, urb->status); ++ qtd->urb = NULL; ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ break; ++ } ++ ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, ++ halt_status); ++ break; ++ case PIPE_BULK: ++ DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ if (urb_xfer_done) { ++ dwc_otg_hcd_complete_urb(hcd, urb, urb->status); ++ qtd->urb = NULL; ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ save_data_toggle(hc, hc_regs, qtd); ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, ++ halt_status); ++ break; ++ case PIPE_INTERRUPT: ++ DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ ++ /* ++ * Interrupt URB is done on the first transfer complete ++ * interrupt. ++ */ ++ dwc_otg_hcd_complete_urb(hcd, urb, urb->status); ++ qtd->urb = NULL; ++ save_data_toggle(hc, hc_regs, qtd); ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_URB_COMPLETE); ++ break; ++ case PIPE_ISOCHRONOUS: ++ DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); ++ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE); ++ } ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ } ++ ++ disable_hc_int(hc_regs, xfercompl); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel STALL interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_stall_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ struct urb *urb = qtd->urb; ++ int pipe_type = usb_pipetype(urb->pipe); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "STALL Received--\n", hc->hc_num); ++ ++ if (pipe_type == PIPE_CONTROL) { ++ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPIPE); ++ qtd->urb = NULL; ++ } ++ ++ if (pipe_type == PIPE_BULK || pipe_type == PIPE_INTERRUPT) { ++ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPIPE); ++ qtd->urb = NULL; ++ /* ++ * USB protocol requires resetting the data toggle for bulk ++ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) ++ * setup command is issued to the endpoint. Anticipate the ++ * CLEAR_FEATURE command since a STALL has occurred and reset ++ * the data toggle now. ++ */ ++ hc->qh->data_toggle = 0; ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); ++ ++ disable_hc_int(hc_regs, stall); ++ ++ return 1; ++} ++ ++/* ++ * Updates the state of the URB when a transfer has been stopped due to an ++ * abnormal condition before the transfer completes. Modifies the ++ * actual_length field of the URB to reflect the number of bytes that have ++ * actually been transferred via the host channel. ++ */ ++static void update_urb_state_xfer_intr(struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct urb *urb, ++ struct dwc_otg_qtd *qtd, ++ enum dwc_otg_halt_status halt_status) ++{ ++ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ urb->actual_length += bytes_transferred; ++ ++#ifdef DEBUG ++ { ++ union hctsiz_data hctsiz; ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", ++ hc->start_pkt_count); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", ++ hc->max_packet); ++ DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", ++ bytes_transferred); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->transfer_buffer_length); ++ } ++#endif ++} ++ ++/** ++ * Handles a host channel NAK interrupt. This handler may be called in either ++ * DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nak_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NAK Received--\n", hc->hc_num); ++ ++ /* ++ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and ++ * interrupt. Re-start the SSPLIT transfer. ++ */ ++ if (hc->do_split) { ++ if (hc->complete_split) ++ qtd->error_count = 0; ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ goto handle_nak_done; ++ } ++ ++ switch (usb_pipetype(qtd->urb->pipe)) { ++ case PIPE_CONTROL: ++ case PIPE_BULK: ++ if (hcd->core_if->dma_enable && hc->ep_is_in) { ++ /* ++ * NAK interrupts are enabled on bulk/control IN ++ * transfers in DMA mode for the sole purpose of ++ * resetting the error count after a transaction error ++ * occurs. The core will continue transferring data. ++ */ ++ qtd->error_count = 0; ++ goto handle_nak_done; ++ } ++ ++ /* ++ * NAK interrupts normally occur during OUT transfers in DMA ++ * or Slave mode. For IN transfers, more requests will be ++ * queued as request queue space is available. ++ */ ++ qtd->error_count = 0; ++ ++ if (!hc->qh->ping_state) { ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, ++ qtd, DWC_OTG_HC_XFER_NAK); ++ save_data_toggle(hc, hc_regs, qtd); ++ if (qtd->urb->dev->speed == USB_SPEED_HIGH) ++ hc->qh->ping_state = 1; ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will ++ * start/continue. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case PIPE_INTERRUPT: ++ qtd->error_count = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case PIPE_ISOCHRONOUS: ++ /* Should never get called for isochronous transfers. */ ++ BUG(); ++ break; ++ } ++ ++handle_nak_done: ++ disable_hc_int(hc_regs, nak); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel ACK interrupt. This interrupt is enabled when ++ * performing the PING protocol in Slave mode, when errors occur during ++ * either Slave mode or DMA mode, and during Start Split transactions. ++ */ ++static int32_t handle_hc_ack_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "ACK Received--\n", hc->hc_num); ++ ++ if (hc->do_split) { ++ /* ++ * Handle ACK on SSPLIT. ++ * ACK should not occur in CSPLIT. ++ */ ++ if ((!hc->ep_is_in) ++ && (hc->data_pid_start != DWC_OTG_HC_PID_SETUP)) { ++ qtd->ssplit_out_xfer_count = hc->xfer_len; ++ } ++ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { ++ /* Don't need complete for isochronous out transfers. */ ++ qtd->complete_split = 1; ++ } ++ ++ /* ISOC OUT */ ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && !hc->ep_is_in) { ++ switch (hc->xact_pos) { ++ case DWC_HCSPLIT_XACTPOS_ALL: ++ break; ++ case DWC_HCSPLIT_XACTPOS_END: ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ break; ++ case DWC_HCSPLIT_XACTPOS_BEGIN: ++ case DWC_HCSPLIT_XACTPOS_MID: ++ /* ++ * For BEGIN or MID, calculate the length for ++ * the next microframe to determine the correct ++ * SSPLIT token, either MID or END. ++ */ ++ do { ++ struct usb_iso_packet_descriptor ++ *frame_desc; ++ ++ frame_desc = ++ &qtd->urb->iso_frame_desc[qtd->isoc_frame_index]; ++ qtd->isoc_split_offset += 188; ++ ++ if ((frame_desc->length - ++ qtd->isoc_split_offset) <= 188) { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_END; ++ } else { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_MID; ++ } ++ ++ } while (0); ++ break; ++ } ++ } else { ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } else { ++ qtd->error_count = 0; ++ ++ if (hc->qh->ping_state) { ++ hc->qh->ping_state = 0; ++ /* ++ * Halt the channel so the transfer can be re-started ++ * from the appropriate point. This only happens in ++ * Slave mode. In DMA mode, the ping_state is cleared ++ * when the transfer is started because the core ++ * automatically executes the PING, then the transfer. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } ++ ++ /* ++ * If the ACK occurred when _not_ in the PING state, let the channel ++ * continue transferring data after clearing the error count. ++ */ ++ ++ disable_hc_int(hc_regs, ack); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel NYET interrupt. This interrupt should only occur on ++ * Bulk and Control OUT endpoints and for complete split transactions. If a ++ * NYET occurs at the same time as a Transfer Complete interrupt, it is ++ * handled in the xfercomp interrupt handler, not here. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nyet_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NYET Received--\n", hc->hc_num); ++ ++ /* ++ * NYET on CSPLIT ++ * re-do the CSPLIT immediately on non-periodic ++ */ ++ if ((hc->do_split) && (hc->complete_split)) { ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_INTR) || ++ (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { ++ int frnum = ++ dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd ++ (hcd)); ++ ++ if (dwc_full_frame_num(frnum) != ++ dwc_full_frame_num(hc->qh->sched_frame)) { ++ /* ++ * No longer in the same full speed frame. ++ * Treat this as a transaction error. ++ */ ++#if 0 ++ /** @todo Fix system performance so this can ++ * be treated as an error. Right now complete ++ * splits cannot be scheduled precisely enough ++ * due to other system activity, so this error ++ * occurs regularly in Slave mode. ++ */ ++ qtd->error_count++; ++#endif ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ /** @todo add support for isoc release */ ++ goto handle_nyet_done; ++ } ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ goto handle_nyet_done; ++ } ++ ++ hc->qh->ping_state = 1; ++ qtd->error_count = 0; ++ ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NYET); ++ save_data_toggle(hc, hc_regs, qtd); ++ ++ /* ++ * Halt the channel and re-start the transfer so the PING ++ * protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ ++handle_nyet_done: ++ disable_hc_int(hc_regs, nyet); ++ return 1; ++} ++ ++/** ++ * Handles a host channel babble interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_babble_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Babble Error--\n", hc->hc_num); ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EOVERFLOW); ++ qtd->urb = NULL; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); ++ } else { ++ enum dwc_otg_halt_status halt_status; ++ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ disable_hc_int(hc_regs, bblerr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel AHB error interrupt. This handler is only called in ++ * DMA mode. ++ */ ++static int32_t handle_hc_ahberr_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ union hcchar_data hcchar; ++ union hcsplt_data hcsplt; ++ union hctsiz_data hctsiz; ++ uint32_t hcdma; ++ struct urb *urb = qtd->urb; ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "AHB Error--\n", hc->hc_num); ++ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ hcdma = dwc_read_reg32(&hc_regs->hcdma); ++ ++ DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); ++ DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); ++ DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); ++ DWC_ERROR(" Device address: %d\n", usb_pipedevice(urb->pipe)); ++ DWC_ERROR(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), ++ (usb_pipein(urb->pipe) ? "IN" : "OUT")); ++ DWC_ERROR(" Endpoint type: %s\n", ++ ({ ++ char *pipetype; ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ pipetype = "CONTROL"; ++ break; ++ case PIPE_BULK: ++ pipetype = "BULK"; ++ break; ++ case PIPE_INTERRUPT: ++ pipetype = "INTERRUPT"; ++ break; ++ case PIPE_ISOCHRONOUS: ++ pipetype = "ISOCHRONOUS"; ++ break; ++ default: ++ pipetype = "UNKNOWN"; ++ break; ++ } ++ pipetype; ++ })); ++ DWC_ERROR(" Speed: %s\n", ++ ({ ++ char *speed; ++ switch (urb->dev->speed) { ++ case USB_SPEED_HIGH: ++ speed = "HIGH"; ++ break; ++ case USB_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case USB_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ } ++ speed; ++ })); ++ DWC_ERROR(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); ++ DWC_ERROR(" Data buffer length: %d\n", urb->transfer_buffer_length); ++ DWC_ERROR(" Transfer buffer: %p, Transfer DMA: 0x%llx\n", ++ urb->transfer_buffer, (unsigned long long)urb->transfer_dma); ++ DWC_ERROR(" Setup buffer: %p, Setup DMA: 0x%llx\n", ++ urb->setup_packet, (unsigned long long)urb->setup_dma); ++ DWC_ERROR(" Interval: %d\n", urb->interval); ++ ++ dwc_otg_hcd_complete_urb(hcd, urb, -EIO); ++ qtd->urb = NULL; ++ ++ /* ++ * Force a channel halt. Don't call halt_channel because that won't ++ * write to the HCCHARn register in DMA mode to force the halt. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); ++ ++ disable_hc_int(hc_regs, ahberr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel transaction error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xacterr_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transaction Error--\n", hc->hc_num); ++ ++ switch (usb_pipetype(qtd->urb->pipe)) { ++ case PIPE_CONTROL: ++ case PIPE_BULK: ++ qtd->error_count++; ++ if (!hc->qh->ping_state) { ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, ++ qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ save_data_toggle(hc, hc_regs, qtd); ++ if (!hc->ep_is_in ++ && qtd->urb->dev->speed == USB_SPEED_HIGH) { ++ hc->qh->ping_state = 1; ++ } ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case PIPE_INTERRUPT: ++ qtd->error_count++; ++ if ((hc->do_split) && (hc->complete_split)) ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case PIPE_ISOCHRONOUS: ++ { ++ enum dwc_otg_halt_status halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++ ++ disable_hc_int(hc_regs, xacterr); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel frame overrun interrupt. This handler may be called ++ * in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_frmovrun_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ enum dwc_otg_halt_status halt_status; ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Frame Overrun--\n", hc->hc_num); ++ ++ switch (usb_pipetype(qtd->urb->pipe)) { ++ case PIPE_CONTROL: ++ case PIPE_BULK: ++ break; ++ case PIPE_INTERRUPT: ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ break; ++ case PIPE_ISOCHRONOUS: ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ halt_channel(hcd, hc, qtd, halt_status); ++ break; ++ } ++ ++ disable_hc_int(hc_regs, frmovrun); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel data toggle error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_datatglerr_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Data Toggle Error--\n", hc->hc_num); ++ ++ if (hc->ep_is_in) { ++ qtd->error_count = 0; ++ } else { ++ DWC_ERROR("Data Toggle Error on OUT transfer," ++ "channel %d\n", hc->hc_num); ++ } ++ ++ disable_hc_int(hc_regs, datatglerr); ++ ++ return 1; ++} ++ ++#ifdef DEBUG ++/** ++ * This function is for debug only. It checks that a valid halt status is set ++ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is ++ * taken and a warning is issued. ++ * Returns 1 if halt status is ok, 0 otherwise. ++ */ ++static inline int halt_status_ok(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ union hcchar_data hcchar; ++ union hctsiz_data hctsiz; ++ union hcint_data hcint; ++ union hcintmsk_data hcintmsk; ++ union hcsplt_data hcsplt; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { ++ /* ++ * This code is here only as a check. This condition should ++ * never happen. Ignore the halt if it does occur. ++ */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); ++ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); ++ DWC_WARN ++ ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " ++ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " ++ "hcint 0x%08x, hcintmsk 0x%08x, " ++ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, ++ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, ++ hcintmsk.d32, hcsplt.d32, qtd->complete_split); ++ ++ DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", ++ __func__, hc->hc_num); ++ DWC_WARN("\n"); ++ clear_hc_int(hc_regs, chhltd); ++ return 0; ++ } ++ ++ /* ++ * This code is here only as a check. hcchar.chdis should ++ * never be set when the halt interrupt occurs. Halt the ++ * channel again if it does occur. ++ */ ++ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: hcchar.chdis set unexpectedly, " ++ "hcchar 0x%08x, trying to halt again\n", ++ __func__, hcchar.d32); ++ clear_hc_int(hc_regs, chhltd); ++ hc->halt_pending = 0; ++ halt_channel(hcd, hc, qtd, hc->halt_status); ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/** ++ * Handles a host Channel Halted interrupt in DMA mode. This handler ++ * determines the reason the channel halted and proceeds accordingly. ++ */ ++static void handle_hc_chhltd_intr_dma(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ union hcint_data hcint; ++ union hcintmsk_data hcintmsk; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ /* ++ * Just release the channel. A dequeue can happen on a ++ * transfer timeout. In the case of an AHB Error, the channel ++ * was forced to halt because there's no way to gracefully ++ * recover. ++ */ ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ return; ++ } ++ ++ /* Read the HCINTn register to determine the cause for the halt. */ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); ++ ++ if (hcint.b.xfercomp) { ++ /* ++ * @todo This is here because of a possible hardware ++ * bug. Spec says that on SPLIT-ISOC OUT transfers in ++ * DMA mode that a HALT interrupt w/ACK bit set should ++ * occur, but I only see the XFERCOMP bit, even with ++ * it masked out. This is a workaround for that ++ * behavior. Should fix this when hardware is fixed. ++ */ ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && (!hc->ep_is_in)) ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xacterr) { ++ /* ++ * Must handle xacterr before nak or ack. Could get a xacterr ++ * at the same time as either of these on a BULK/CONTROL OUT ++ * that started with a PING. The xacterr takes precedence. ++ */ ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nyet) { ++ /* ++ * Must handle nyet before nak or ack. Could get a nyet at the ++ * same time as either of those on a BULK/CONTROL OUT that ++ * started with a PING. The nyet takes precedence. ++ */ ++ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.bblerr) { ++ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.frmovrun) { ++ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nak && !hcintmsk.b.nak) { ++ /* ++ * If nak is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the nak is handled by ++ * the nak interrupt handler, not here. Handle nak here for ++ * BULK/CONTROL OUT transfers, which halt on a NAK to allow ++ * rewinding the buffer pointer. ++ */ ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ack && !hcintmsk.b.ack) { ++ /* ++ * If ack is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the ack is handled by ++ * the ack interrupt handler, not here. Handle ack here for ++ * split transfers. Start splits halt on ACK. ++ */ ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * A periodic transfer halted with no other channel ++ * interrupts set. Assume it was halted by the core ++ * because it could not be completed in its scheduled ++ * (micro)frame. ++ */ ++#ifdef DEBUG ++ DWC_PRINT("%s: Halt channel %d (assume incomplete " ++ "periodic transfer)\n", ++ __func__, hc->hc_num); ++#endif ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); ++ } else { ++ DWC_ERROR("%s: Channel %d, DMA Mode -- ChHltd set, " ++ "but reason for halting is unknown, hcint " ++ "0x%08x, intsts 0x%08x\n", ++ __func__, hc->hc_num, hcint.d32, ++ dwc_read_reg32(&hcd->core_if->core_global_regs-> ++ gintsts)); ++ } ++ } ++} ++ ++/** ++ * Handles a host channel Channel Halted interrupt. ++ * ++ * In slave mode, this handler is called only when the driver specifically ++ * requests a halt. This occurs during handling other host channel interrupts ++ * (e.g. nak, xacterr, stall, nyet, etc.). ++ * ++ * In DMA mode, this is the interrupt that occurs when the core has finished ++ * processing a transfer on a channel. Other host channel interrupts (except ++ * ahberr) are disabled in DMA mode. ++ */ ++static int32_t handle_hc_chhltd_intr(struct dwc_otg_hcd *hcd, ++ struct dwc_hc *hc, ++ struct dwc_otg_hc_regs *hc_regs, ++ struct dwc_otg_qtd *qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Channel Halted--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_enable) { ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); ++ } else { ++#ifdef DEBUG ++ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) ++ return 1; ++#endif ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ } ++ ++ return 1; ++} ++ ++/** Handles interrupt for a specific Host Channel */ ++int32_t dwc_otg_hcd_handle_hc_n_intr(struct dwc_otg_hcd *dwc_otg_hcd, ++ uint32_t _num) ++{ ++ int retval = 0; ++ union hcint_data hcint; ++ union hcintmsk_data hcintmsk; ++ struct dwc_hc *hc; ++ struct dwc_otg_hc_regs *hc_regs; ++ struct dwc_otg_qtd *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", _num); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[_num]; ++ hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[_num]; ++ qtd = list_entry(hc->qh->qtd_list.next, struct dwc_otg_qtd, ++ qtd_list_entry); ++ ++ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); ++ DWC_DEBUGPL(DBG_HCDV, ++ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", ++ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); ++ hcint.d32 = hcint.d32 & hcintmsk.d32; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ if ((hcint.b.chhltd) && (hcint.d32 != 0x2)) ++ hcint.b.chhltd = 0; ++ } ++ ++ if (hcint.b.xfercomp) { ++ retval |= ++ handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ /* ++ * If NYET occurred at same time as Xfer Complete, the NYET is ++ * handled by the Xfer Complete interrupt handler. Don't want ++ * to call the NYET interrupt handler in this case. ++ */ ++ hcint.b.nyet = 0; ++ } ++ if (hcint.b.chhltd) ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.ahberr) ++ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.stall) ++ retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.nak) ++ retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.ack) ++ retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.nyet) ++ retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.xacterr) ++ retval |= ++ handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.bblerr) ++ retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.frmovrun) ++ retval |= ++ handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ if (hcint.b.datatglerr) ++ retval |= ++ handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +new file mode 100644 +index 0000000..e4c96f2 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +@@ -0,0 +1,695 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef DWC_DEVICE_ONLY ++ ++/* ++ * ++ * This file contains the functions to manage Queue Heads and Queue ++ * Transfer Descriptors. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dwc_otg_driver.h" ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++/** ++ * This function allocates and initializes a QH. ++ * ++ * @hcd: The HCD state structure for the DWC OTG controller. ++ * @urb: Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ * ++ * Returns Returns pointer to the newly allocated QH, or NULL on error. */ ++struct dwc_otg_qh *dwc_otg_hcd_qh_create(struct dwc_otg_hcd *hcd, ++ struct urb *urb) ++{ ++ struct dwc_otg_qh *qh; ++ ++ /* Allocate memory */ ++ /** @todo add memflags argument */ ++ qh = dwc_otg_hcd_qh_alloc(); ++ if (qh == NULL) ++ return NULL; ++ ++ dwc_otg_hcd_qh_init(hcd, qh, urb); ++ return qh; ++} ++ ++/** Free each QTD in the QH's QTD-list then free the QH. QH should already be ++ * removed from a list. QTD list should already be empty if called from URB ++ * Dequeue. ++ * ++ * @qh: The QH to free. ++ */ ++void dwc_otg_hcd_qh_free(struct dwc_otg_qh *qh) ++{ ++ struct dwc_otg_qtd *qtd; ++ struct list_head *pos; ++ ++ /* Free each QTD in the QTD list */ ++ for (pos = qh->qtd_list.next; ++ pos != &qh->qtd_list; pos = qh->qtd_list.next) { ++ list_del(pos); ++ qtd = dwc_list_to_qtd(pos); ++ dwc_otg_hcd_qtd_free(qtd); ++ } ++ ++ kfree(qh); ++ return; ++} ++ ++/** Initializes a QH structure. ++ * ++ * @hcd: The HCD state structure for the DWC OTG controller. ++ * @qh: The QH to init. ++ * @urb: Holds the information about the device/endpoint that we need ++ * to initialize the QH. */ ++#define SCHEDULE_SLOP 10 ++void dwc_otg_hcd_qh_init(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh, ++ struct urb *urb) ++{ ++ memset(qh, 0, sizeof(struct dwc_otg_qh)); ++ ++ /* Initialize QH */ ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ qh->ep_type = USB_ENDPOINT_XFER_CONTROL; ++ break; ++ case PIPE_BULK: ++ qh->ep_type = USB_ENDPOINT_XFER_BULK; ++ break; ++ case PIPE_ISOCHRONOUS: ++ qh->ep_type = USB_ENDPOINT_XFER_ISOC; ++ break; ++ case PIPE_INTERRUPT: ++ qh->ep_type = USB_ENDPOINT_XFER_INT; ++ break; ++ } ++ ++ qh->ep_is_in = usb_pipein(urb->pipe) ? 1 : 0; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ qh->maxp = ++ usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe))); ++ INIT_LIST_HEAD(&qh->qtd_list); ++ INIT_LIST_HEAD(&qh->qh_list_entry); ++ qh->channel = NULL; ++ ++ /* FS/LS Enpoint on HS Hub ++ * NOT virtual root hub */ ++ qh->do_split = 0; ++ if (((urb->dev->speed == USB_SPEED_LOW) || ++ (urb->dev->speed == USB_SPEED_FULL)) && ++ (urb->dev->tt) && (urb->dev->tt->hub->devnum != 1)) { ++ DWC_DEBUGPL(DBG_HCD, ++ "QH init: EP %d: TT found at hub addr %d, for " ++ "port %d\n", ++ usb_pipeendpoint(urb->pipe), ++ urb->dev->tt->hub->devnum, urb->dev->ttport); ++ qh->do_split = 1; ++ } ++ ++ if (qh->ep_type == USB_ENDPOINT_XFER_INT || ++ qh->ep_type == USB_ENDPOINT_XFER_ISOC) { ++ /* Compute scheduling parameters once and save them. */ ++ union hprt0_data hprt; ++ ++ /* todo Account for split transfers in the bus time. */ ++ int bytecount = ++ dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); ++ /* ++ * The results from usb_calc_bus_time are in nanosecs, ++ * so divide the result by 1000 to convert to ++ * microsecs expected by this driver ++ */ ++ qh->usecs = usb_calc_bus_time(urb->dev->speed, ++ usb_pipein(urb->pipe), ++ (qh->ep_type == ++ USB_ENDPOINT_XFER_ISOC), ++ bytecount) / 1000; ++ ++ /* Start in a slightly future (micro)frame. */ ++ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, ++ SCHEDULE_SLOP); ++ qh->interval = urb->interval; ++#if 0 ++ /* Increase interrupt polling rate for debugging. */ ++ if (qh->ep_type == USB_ENDPOINT_XFER_INT) ++ qh->interval = 8; ++#endif ++ hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0); ++ if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && ++ ((urb->dev->speed == USB_SPEED_LOW) || ++ (urb->dev->speed == USB_SPEED_FULL))) { ++ qh->interval *= 8; ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ ++ } ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", ++ urb->dev->devnum); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) == USB_DIR_IN ? "IN" : "OUT"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", ++ ({ ++ char *speed; ++ switch (urb->dev->speed) { ++ case USB_SPEED_LOW: ++ speed = "low"; ++ break; ++ case USB_SPEED_FULL: ++ speed = "full"; ++ break; ++ case USB_SPEED_HIGH: ++ speed = "high"; ++ break; ++ default: ++ speed = "?"; ++ break; ++ } ++ speed; ++ })); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", ++ ({ ++ char *type; ++ switch (qh->ep_type) { ++ case USB_ENDPOINT_XFER_ISOC: ++ type = "isochronous"; ++ break; ++ case USB_ENDPOINT_XFER_INT: ++ type = "interrupt"; ++ break; ++ case USB_ENDPOINT_XFER_CONTROL: ++ type = "control"; ++ break; ++ case USB_ENDPOINT_XFER_BULK: ++ type = "bulk"; ++ break; ++ default: ++ type = "?"; ++ break; ++ } ++ type; ++ })); ++#ifdef DEBUG ++ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", ++ qh->usecs); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", ++ qh->interval); ++ } ++#endif ++ ++ return; ++} ++ ++/** ++ * Checks that a channel is available for a periodic transfer. ++ * ++ * Returns 0 if successful, negative error code otherise. ++ */ ++static int periodic_channel_available(struct dwc_otg_hcd *hcd) ++{ ++ /* ++ * Currently assuming that there is a dedicated host channnel for each ++ * periodic transaction plus at least one host channel for ++ * non-periodic transactions. ++ */ ++ int status; ++ int num_channels; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ if ((hcd->periodic_channels + hcd->non_periodic_channels < ++ num_channels) && (hcd->periodic_channels < num_channels - 1)) { ++ status = 0; ++ } else { ++ DWC_NOTICE ++ ("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", ++ __func__, num_channels, hcd->periodic_channels, ++ hcd->non_periodic_channels); ++ status = -ENOSPC; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that there is sufficient bandwidth for the specified QH in the ++ * periodic schedule. For simplicity, this calculation assumes that all the ++ * transfers in the periodic schedule may occur in the same (micro)frame. ++ * ++ * @hcd: The HCD state structure for the DWC OTG controller. ++ * @qh: QH containing periodic bandwidth required. ++ * ++ * Returns 0 if successful, negative error code otherwise. ++ */ ++static int check_periodic_bandwidth(struct dwc_otg_hcd *hcd, ++ struct dwc_otg_qh *qh) ++{ ++ int status; ++ uint16_t max_claimed_usecs; ++ ++ status = 0; ++ ++ if (hcd->core_if->core_params->speed == DWC_SPEED_PARAM_HIGH) { ++ /* ++ * High speed mode. ++ * Max periodic usecs is 80% x 125 usec = 100 usec. ++ */ ++ max_claimed_usecs = 100 - qh->usecs; ++ } else { ++ /* ++ * Full speed mode. ++ * Max periodic usecs is 90% x 1000 usec = 900 usec. ++ */ ++ max_claimed_usecs = 900 - qh->usecs; ++ } ++ ++ if (hcd->periodic_usecs > max_claimed_usecs) { ++ DWC_NOTICE("%s: already claimed usecs %d, required usecs %d\n", ++ __func__, hcd->periodic_usecs, qh->usecs); ++ status = -ENOSPC; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that the max transfer size allowed in a host channel is large enough ++ * to handle the maximum data transfer in a single (micro)frame for a periodic ++ * transfer. ++ * ++ * @hcd: The HCD state structure for the DWC OTG controller. ++ * @qh: QH for a periodic endpoint. ++ * ++ * Returns 0 if successful, negative error code otherwise. ++ */ ++static int check_max_xfer_size(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) ++{ ++ int status; ++ uint32_t max_xfer_size; ++ uint32_t max_channel_xfer_size; ++ ++ status = 0; ++ ++ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); ++ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; ++ ++ if (max_xfer_size > max_channel_xfer_size) { ++ DWC_NOTICE("%s: Periodic xfer length %d > " ++ "max xfer length for channel %d\n", ++ __func__, max_xfer_size, max_channel_xfer_size); ++ status = -ENOSPC; ++ } ++ ++ return status; ++} ++ ++/** ++ * Schedules an interrupt or isochronous transfer in the periodic schedule. ++ * ++ * @hcd: The HCD state structure for the DWC OTG controller. ++ * @qh: QH for the periodic transfer. The QH should already contain the ++ * scheduling information. ++ * ++ * Returns 0 if successful, negative error code otherwise. ++ */ ++static int schedule_periodic(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) ++{ ++ int status = 0; ++ ++ status = periodic_channel_available(hcd); ++ if (status) { ++ DWC_NOTICE("%s: No host channel available for periodic " ++ "transfer.\n", __func__); ++ return status; ++ } ++ ++ status = check_periodic_bandwidth(hcd, qh); ++ if (status) { ++ DWC_NOTICE("%s: Insufficient periodic bandwidth for " ++ "periodic transfer.\n", __func__); ++ return status; ++ } ++ ++ status = check_max_xfer_size(hcd, qh); ++ if (status) { ++ DWC_NOTICE("%s: Channel max transfer size too small " ++ "for periodic transfer.\n", __func__); ++ return status; ++ } ++ ++ /* Always start in the inactive schedule. */ ++ list_add_tail(&qh->qh_list_entry, &hcd->periodic_sched_inactive); ++ ++ /* Reserve the periodic channel. */ ++ hcd->periodic_channels++; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs += qh->usecs; ++ ++ /* ++ * Update average periodic bandwidth claimed and # periodic ++ * reqs for usbfs. ++ */ ++ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated += ++ qh->usecs / qh->interval; ++ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { ++ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs++; ++ DWC_DEBUGPL(DBG_HCD, ++ "Scheduled intr: qh %p, usecs %d, period %d\n", qh, ++ qh->usecs, qh->interval); ++ } else { ++ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs++; ++ DWC_DEBUGPL(DBG_HCD, ++ "Scheduled isoc: qh %p, usecs %d, period %d\n", qh, ++ qh->usecs, qh->interval); ++ } ++ ++ return status; ++} ++ ++/** ++ * This function adds a QH to either the non periodic or periodic schedule if ++ * it is not already in the schedule. If the QH is already in the schedule, no ++ * action is taken. ++ * ++ * Returns 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_add(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) ++{ ++ int status = 0; ++ ++ if (!spin_is_locked(&hcd->global_lock)) { ++ pr_err("%s don't have hcd->global_lock", __func__); ++ BUG(); ++ } ++ ++ if (!list_empty(&qh->qh_list_entry)) { ++ /* QH already in a schedule. */ ++ goto done; ++ } ++ ++ /* Add the new QH to the appropriate schedule */ ++ if (dwc_qh_is_non_per(qh)) { ++ /* Always start in the inactive schedule. */ ++ list_add_tail(&qh->qh_list_entry, ++ &hcd->non_periodic_sched_inactive); ++ } else { ++ status = schedule_periodic(hcd, qh); ++ } ++ ++done: ++ return status; ++} ++ ++/** ++ * Removes an interrupt or isochronous transfer from the periodic schedule. ++ * ++ * @hcd: The HCD state structure for the DWC OTG controller. ++ * @qh: QH for the periodic transfer. ++ */ ++static void deschedule_periodic(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) ++{ ++ list_del_init(&qh->qh_list_entry); ++ ++ /* Release the periodic channel reservation. */ ++ hcd->periodic_channels--; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs -= qh->usecs; ++ ++ /* ++ * Update average periodic bandwidth claimed and # periodic ++ * reqs for usbfs. ++ */ ++ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated -= ++ qh->usecs / qh->interval; ++ ++ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { ++ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs--; ++ DWC_DEBUGPL(DBG_HCD, ++ "Descheduled intr: qh %p, usecs %d, period %d\n", ++ qh, qh->usecs, qh->interval); ++ } else { ++ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs--; ++ DWC_DEBUGPL(DBG_HCD, ++ "Descheduled isoc: qh %p, usecs %d, period %d\n", ++ qh, qh->usecs, qh->interval); ++ } ++} ++ ++/** ++ * Removes a QH from either the non-periodic or periodic schedule. Memory is ++ * not freed. ++ * ++ * @hcd: The HCD state structure. ++ * @qh: QH to remove from schedule. */ ++void dwc_otg_hcd_qh_remove(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) ++{ ++ if (!spin_is_locked(&hcd->global_lock)) { ++ pr_err("%s don't have hcd->global_lock", __func__); ++ BUG(); ++ } ++ ++ if (list_empty(&qh->qh_list_entry)) { ++ /* QH is not in a schedule. */ ++ goto done; ++ } ++ ++ if (dwc_qh_is_non_per(qh)) { ++ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ list_del_init(&qh->qh_list_entry); ++ } else { ++ deschedule_periodic(hcd, qh); ++ } ++ ++done: ++ ; ++} ++ ++/** ++ * Deactivates a QH. For non-periodic QHs, removes the QH from the active ++ * non-periodic schedule. The QH is added to the inactive non-periodic ++ * schedule if any QTDs are still attached to the QH. ++ * ++ * For periodic QHs, the QH is removed from the periodic queued schedule. If ++ * there are any QTDs still attached to the QH, the QH is added to either the ++ * periodic inactive schedule or the periodic ready schedule and its next ++ * scheduled frame is calculated. The QH is placed in the ready schedule if ++ * the scheduled frame has been reached already. Otherwise it's placed in the ++ * inactive schedule. If there are no QTDs attached to the QH, the QH is ++ * completely removed from the periodic schedule. ++ */ ++void dwc_otg_hcd_qh_deactivate(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh, ++ int sched_next_periodic_split) ++{ ++ uint16_t frame_number; ++ ++ if (!spin_is_locked(&hcd->global_lock)) { ++ pr_err("%s don't have hcd->global_lock", __func__); ++ BUG(); ++ } ++ ++ if (dwc_qh_is_non_per(qh)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ if (!list_empty(&qh->qtd_list)) ++ /* Add back to inactive non-periodic schedule. */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ return; ++ } ++ ++ frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd)); ++ ++ if (qh->do_split) { ++ /* Schedule the next continuing periodic split transfer */ ++ if (sched_next_periodic_split) { ++ ++ qh->sched_frame = frame_number; ++ if (dwc_frame_num_le(frame_number, ++ dwc_frame_num_inc(qh->start_split_frame, ++ 1))) { ++ /* ++ * Allow one frame to elapse after ++ * start split microframe before ++ * scheduling complete split, but DONT ++ * if we are doing the next start ++ * split in the same frame for an ISOC ++ * out. ++ */ ++ if ((qh->ep_type != USB_ENDPOINT_XFER_ISOC) ++ || (qh->ep_is_in != 0)) { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, ++ 1); ++ } ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->start_split_frame, ++ qh->interval); ++ if (dwc_frame_num_le(qh->sched_frame, frame_number)) ++ qh->sched_frame = frame_number; ++ ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ } else { ++ qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, ++ qh->interval); ++ if (dwc_frame_num_le(qh->sched_frame, frame_number)) ++ qh->sched_frame = frame_number; ++ } ++ ++ if (list_empty(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* ++ * Remove from periodic_sched_queued and move to ++ * appropriate queue. ++ */ ++ if (qh->sched_frame == frame_number) { ++ list_move(&qh->qh_list_entry, ++ &hcd->periodic_sched_ready); ++ } else { ++ list_move(&qh->qh_list_entry, ++ &hcd->periodic_sched_inactive); ++ } ++ } ++} ++ ++/** ++ * This function allocates and initializes a QTD. ++ * ++ * @urb: The URB to create a QTD from. Each URB-QTD pair will end up ++ * pointing to each other so each pair should have a unique correlation. ++ * ++ * Returns Returns pointer to the newly allocated QTD, or NULL on error. */ ++struct dwc_otg_qtd *dwc_otg_hcd_qtd_create(struct urb *urb) ++{ ++ struct dwc_otg_qtd *qtd; ++ ++ qtd = dwc_otg_hcd_qtd_alloc(); ++ if (qtd == NULL) ++ return NULL; ++ ++ dwc_otg_hcd_qtd_init(qtd, urb); ++ return qtd; ++} ++ ++/** ++ * Initializes a QTD structure. ++ * ++ * @qtd: The QTD to initialize. ++ * @urb: The URB to use for initialization. ++ */ ++void dwc_otg_hcd_qtd_init(struct dwc_otg_qtd *qtd, struct urb *urb) ++{ ++ memset(qtd, 0, sizeof(struct dwc_otg_qtd)); ++ qtd->urb = urb; ++ if (usb_pipecontrol(urb->pipe)) { ++ /* ++ * The only time the QTD data toggle is used is on the data ++ * phase of control transfers. This phase always starts with ++ * DATA1. ++ */ ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ qtd->control_phase = DWC_OTG_CONTROL_SETUP; ++ } ++ ++ /* start split */ ++ qtd->complete_split = 0; ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ ++ /* Store the qtd ptr in the urb to reference what QTD. */ ++ urb->hcpriv = qtd; ++ return; ++} ++ ++/** ++ * This function adds a QTD to the QTD-list of a QH. It will find the correct ++ * QH to place the QTD into. If it does not find a QH, then it will create a ++ * new QH. If the QH to which the QTD is added is not currently scheduled, it ++ * is placed into the proper schedule based on its EP type. ++ * ++ * @qtd: The QTD to add ++ * @dwc_otg_hcd: The DWC HCD structure ++ * ++ * Returns 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qtd_add(struct dwc_otg_qtd *qtd, ++ struct dwc_otg_hcd *dwc_otg_hcd) ++{ ++ struct usb_host_endpoint *ep; ++ struct dwc_otg_qh *qh; ++ int retval = 0; ++ ++ struct urb *urb = qtd->urb; ++ ++ /* ++ * Get the QH which holds the QTD-list to insert to. Create QH if it ++ * doesn't exist. ++ */ ++ ep = dwc_urb_to_endpoint(urb); ++ qh = ep->hcpriv; ++ if (qh == NULL) { ++ qh = dwc_otg_hcd_qh_create(dwc_otg_hcd, urb); ++ if (qh == NULL) { ++ retval = -ENOMEM; ++ goto done; ++ } ++ ep->hcpriv = qh; ++ } ++ qtd->qh = qh; ++ retval = dwc_otg_hcd_qh_add(dwc_otg_hcd, qh); ++ if (retval == 0) ++ list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list); ++done: ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_octeon.c b/drivers/usb/host/dwc_otg/dwc_otg_octeon.c +new file mode 100644 +index 0000000..5e92b3c +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_octeon.c +@@ -0,0 +1,1078 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* permission constants */ ++#include ++#include ++ ++#include "dwc_otg_plat.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_cil.h" ++#ifndef DWC_HOST_ONLY ++#include "dwc_otg_pcd.h" ++#endif ++#include "dwc_otg_hcd.h" ++ ++#define DWC_DRIVER_VERSION "2.40a 10-APR-2006" ++#define DWC_DRIVER_DESC "HS OTG USB Controller driver" ++ ++static const char dwc_driver_name[] = "dwc_otg"; ++int dwc_errata_write_count; /* See dwc_otg_plat.h, dwc_write_reg32 */ ++ ++/*-------------------------------------------------------------------------*/ ++/* Encapsulate the module parameter settings */ ++ ++static struct dwc_otg_core_params dwc_otg_module_params = { ++ .opt = -1, ++ .otg_cap = -1, ++ .dma_enable = -1, ++ .dma_burst_size = -1, ++ .speed = -1, ++ .host_support_fs_ls_low_power = -1, ++ .host_ls_low_power_phy_clk = -1, ++ .enable_dynamic_fifo = -1, ++ .data_fifo_size = -1, ++ .dev_rx_fifo_size = -1, ++ .dev_nperio_tx_fifo_size = -1, ++ .dev_perio_tx_fifo_size = {-1, /* dev_perio_tx_fifo_size_1 */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1}, /* 15 */ ++ .host_rx_fifo_size = -1, ++ .host_nperio_tx_fifo_size = -1, ++ .host_perio_tx_fifo_size = -1, ++ .max_transfer_size = -1, ++ .max_packet_count = -1, ++ .host_channels = -1, ++ .dev_endpoints = -1, ++ .phy_type = -1, ++ .phy_utmi_width = -1, ++ .phy_ulpi_ddr = -1, ++ .phy_ulpi_ext_vbus = -1, ++ .i2c_enable = -1, ++ .ulpi_fs_ls = -1, ++ .ts_dline = -1, ++}; ++ ++/** ++ * Global Debug Level Mask. ++ */ ++uint32_t g_dbg_lvl; /* 0 -> OFF */ ++ ++/** ++ * This function shows the Driver Version. ++ */ ++static ssize_t version_show(struct device_driver *dev, char *buf) ++{ ++ return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n", ++ DWC_DRIVER_VERSION); ++} ++ ++static DRIVER_ATTR(version, S_IRUGO, version_show, NULL); ++ ++/** ++ * This function is called during module intialization to verify that ++ * the module parameters are in a valid state. ++ */ ++static int check_parameters(struct dwc_otg_core_if *core_if) ++{ ++ int i; ++ int retval = 0; ++ ++/* Checks if the parameter is outside of its valid range of values */ ++#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \ ++ ((dwc_otg_module_params._param_ < (_low_)) || \ ++ (dwc_otg_module_params._param_ > (_high_))) ++ ++/* If the parameter has been set by the user, check that the parameter value is ++ * within the value range of values. If not, report a module error. */ ++#define DWC_OTG_PARAM_ERR(_param_, _low_, _high_, _string_) \ ++ do { \ ++ if (dwc_otg_module_params._param_ != -1) { \ ++ if (DWC_OTG_PARAM_TEST(_param_, (_low_), (_high_))) { \ ++ DWC_ERROR("`%d' invalid for parameter `%s'\n", \ ++ dwc_otg_module_params._param_, _string_); \ ++ dwc_otg_module_params._param_ = dwc_param_##_param_##_default; \ ++ retval++; \ ++ } \ ++ } \ ++ } while (0) ++ ++ DWC_OTG_PARAM_ERR(opt, 0, 1, "opt"); ++ DWC_OTG_PARAM_ERR(otg_cap, 0, 2, "otg_cap"); ++ DWC_OTG_PARAM_ERR(dma_enable, 0, 1, "dma_enable"); ++ DWC_OTG_PARAM_ERR(speed, 0, 1, "speed"); ++ DWC_OTG_PARAM_ERR(host_support_fs_ls_low_power, 0, 1, ++ "host_support_fs_ls_low_power"); ++ DWC_OTG_PARAM_ERR(host_ls_low_power_phy_clk, 0, 1, ++ "host_ls_low_power_phy_clk"); ++ DWC_OTG_PARAM_ERR(enable_dynamic_fifo, 0, 1, "enable_dynamic_fifo"); ++ DWC_OTG_PARAM_ERR(data_fifo_size, 32, 32768, "data_fifo_size"); ++ DWC_OTG_PARAM_ERR(dev_rx_fifo_size, 16, 32768, "dev_rx_fifo_size"); ++ DWC_OTG_PARAM_ERR(dev_nperio_tx_fifo_size, 16, 32768, ++ "dev_nperio_tx_fifo_size"); ++ DWC_OTG_PARAM_ERR(host_rx_fifo_size, 16, 32768, "host_rx_fifo_size"); ++ DWC_OTG_PARAM_ERR(host_nperio_tx_fifo_size, 16, 32768, ++ "host_nperio_tx_fifo_size"); ++ DWC_OTG_PARAM_ERR(host_perio_tx_fifo_size, 16, 32768, ++ "host_perio_tx_fifo_size"); ++ DWC_OTG_PARAM_ERR(max_transfer_size, 2047, 524288, "max_transfer_size"); ++ DWC_OTG_PARAM_ERR(max_packet_count, 15, 511, "max_packet_count"); ++ DWC_OTG_PARAM_ERR(host_channels, 1, 16, "host_channels"); ++ DWC_OTG_PARAM_ERR(dev_endpoints, 1, 15, "dev_endpoints"); ++ DWC_OTG_PARAM_ERR(phy_type, 0, 2, "phy_type"); ++ DWC_OTG_PARAM_ERR(phy_ulpi_ddr, 0, 1, "phy_ulpi_ddr"); ++ DWC_OTG_PARAM_ERR(phy_ulpi_ext_vbus, 0, 1, "phy_ulpi_ext_vbus"); ++ DWC_OTG_PARAM_ERR(i2c_enable, 0, 1, "i2c_enable"); ++ DWC_OTG_PARAM_ERR(ulpi_fs_ls, 0, 1, "ulpi_fs_ls"); ++ DWC_OTG_PARAM_ERR(ts_dline, 0, 1, "ts_dline"); ++ ++ if (dwc_otg_module_params.dma_burst_size != -1) { ++ if (DWC_OTG_PARAM_TEST(dma_burst_size, 1, 1) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 4, 4) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 8, 8) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 16, 16) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 32, 32) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 64, 64) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 128, 128) && ++ DWC_OTG_PARAM_TEST(dma_burst_size, 256, 256)) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dma_burst_size'\n", ++ dwc_otg_module_params.dma_burst_size); ++ dwc_otg_module_params.dma_burst_size = 32; ++ retval++; ++ } ++ } ++ ++ if (dwc_otg_module_params.phy_utmi_width != -1) { ++ if (DWC_OTG_PARAM_TEST(phy_utmi_width, 8, 8) && ++ DWC_OTG_PARAM_TEST(phy_utmi_width, 16, 16)) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `phy_utmi_width'\n", ++ dwc_otg_module_params.phy_utmi_width); ++ dwc_otg_module_params.phy_utmi_width = 16; ++ retval++; ++ } ++ } ++ ++ for (i = 0; i < 15; i++) { ++ /* @todo should be like above */ ++ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != ++ (unsigned)-1) { ++ if (DWC_OTG_PARAM_TEST ++ (dev_perio_tx_fifo_size[i], 4, 768)) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `%s_%d'\n", ++ dwc_otg_module_params. ++ dev_perio_tx_fifo_size[i], ++ "dev_perio_tx_fifo_size", i); ++ dwc_otg_module_params. ++ dev_perio_tx_fifo_size[i] = ++ dwc_param_dev_perio_tx_fifo_size_default; ++ retval++; ++ } ++ } ++ } ++ ++ /* At this point, all module parameters that have been set by the user ++ * are valid, and those that have not are left unset. Now set their ++ * default values and/or check the parameters against the hardware ++ * configurations of the OTG core. */ ++ ++/* This sets the parameter to the default value if it has not been set by the ++ * user */ ++#define PARAM_SET_DEFAULT(_param_) \ ++ ({ \ ++ int changed = 1; \ ++ if (dwc_otg_module_params._param_ == -1) { \ ++ changed = 0; \ ++ dwc_otg_module_params._param_ = dwc_param_##_param_##_default; \ ++ } \ ++ changed; \ ++ }) ++ ++/* This checks the macro agains the hardware configuration to see if it is ++ * valid. It is possible that the default value could be invalid. In this ++ * case, it will report a module error if the user touched the parameter. ++ * Otherwise it will adjust the value without any error. */ ++#define PARAM_CHECK_VALID(_param_, _str_, _is_valid_, _set_valid_) \ ++ ({ \ ++ int changed = PARAM_SET_DEFAULT(_param_); \ ++ int error = 0; \ ++ if (!(_is_valid_)) { \ ++ if (changed) { \ ++ DWC_ERROR("`%d' invalid for parameter `%s'. Check HW configuration.\n", dwc_otg_module_params._param_, _str_); \ ++ error = 1; \ ++ } \ ++ dwc_otg_module_params._param_ = (_set_valid_); \ ++ } \ ++ error; \ ++ }) ++ ++ /* OTG Cap */ ++ retval += PARAM_CHECK_VALID(otg_cap, "otg_cap", ++ ({ ++ int valid; ++ valid = 1; ++ switch (dwc_otg_module_params.otg_cap) { ++ case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE: ++ if (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ valid = 0; ++ break; ++ case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: ++ if ((core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ && (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ++ valid = 0; ++ break; ++ case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: ++ /* always valid */ ++ break; ++ } ++ valid; ++ }), ++ (((core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ || (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ++ ? ++ DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)); ++ ++ retval += PARAM_CHECK_VALID(dma_enable, "dma_enable", ++ ((dwc_otg_module_params. ++ dma_enable == 1) ++ && (core_if->hwcfg2.b. ++ architecture == 0)) ? 0 : 1, ++ 0); ++ ++ retval += PARAM_CHECK_VALID(opt, "opt", 1, 0); ++ ++ PARAM_SET_DEFAULT(dma_burst_size); ++ ++ retval += PARAM_CHECK_VALID(host_support_fs_ls_low_power, ++ "host_support_fs_ls_low_power", ++ 1, 0); ++ ++ retval += PARAM_CHECK_VALID(enable_dynamic_fifo, ++ "enable_dynamic_fifo", ++ ((dwc_otg_module_params.enable_dynamic_fifo == 0) ++ || (core_if->hwcfg2.b.dynamic_fifo == 1)), 0); ++ ++ retval += PARAM_CHECK_VALID(data_fifo_size, ++ "data_fifo_size", ++ dwc_otg_module_params.data_fifo_size <= core_if->hwcfg3.b.dfifo_depth, ++ core_if->hwcfg3.b.dfifo_depth); ++ ++ retval += PARAM_CHECK_VALID(dev_rx_fifo_size, ++ "dev_rx_fifo_size", ++ (dwc_otg_module_params.dev_rx_fifo_size <= ++ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)), ++ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)); ++ ++ retval += PARAM_CHECK_VALID(dev_nperio_tx_fifo_size, ++ "dev_nperio_tx_fifo_size", ++ dwc_otg_module_params.dev_nperio_tx_fifo_size <= ++ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16), ++ dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16); ++ ++ retval += PARAM_CHECK_VALID(host_rx_fifo_size, ++ "host_rx_fifo_size", ++ dwc_otg_module_params.host_rx_fifo_size <= ++ dwc_read_reg32(&core_if->core_global_regs->grxfsiz), ++ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)); ++ ++ retval += PARAM_CHECK_VALID(host_nperio_tx_fifo_size, ++ "host_nperio_tx_fifo_size", ++ dwc_otg_module_params.host_nperio_tx_fifo_size <= ++ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16), ++ dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16); ++ ++ retval += PARAM_CHECK_VALID(host_perio_tx_fifo_size, ++ "host_perio_tx_fifo_size", ++ dwc_otg_module_params.host_perio_tx_fifo_size <= ++ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16), ++ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16)); ++ ++ retval += PARAM_CHECK_VALID(max_transfer_size, ++ "max_transfer_size", ++ dwc_otg_module_params.max_transfer_size < ++ (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11)), ++ (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11)) - 1); ++ ++ retval += PARAM_CHECK_VALID(max_packet_count, ++ "max_packet_count", ++ dwc_otg_module_params.max_packet_count < ++ (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)), ++ (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1); ++ ++ retval += PARAM_CHECK_VALID(host_channels, ++ "host_channels", ++ dwc_otg_module_params.host_channels <= (core_if->hwcfg2.b.num_host_chan + 1), ++ core_if->hwcfg2.b.num_host_chan + 1); ++ ++ retval += PARAM_CHECK_VALID(dev_endpoints, ++ "dev_endpoints", ++ dwc_otg_module_params.dev_endpoints <= core_if->hwcfg2.b.num_dev_ep, ++ core_if->hwcfg2.b.num_dev_ep); ++ ++/* ++ * Define the following to disable the FS PHY Hardware checking. This is for ++ * internal testing only. ++ * ++ * #define NO_FS_PHY_HW_CHECKS ++ */ ++ ++#ifdef NO_FS_PHY_HW_CHECKS ++ retval += PARAM_CHECK_VALID(phy_type, "phy_type", 1, 0); ++#else ++ retval += PARAM_CHECK_VALID(phy_type, "phy_type", ++ ({ ++ int valid = 0; ++ if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_UTMI) && ((core_if->hwcfg2.b.hs_phy_type == 1) || (core_if->hwcfg2.b.hs_phy_type == 3))) ++ valid = 1; ++ else if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_ULPI) && ((core_if->hwcfg2.b.hs_phy_type == 2) || (core_if->hwcfg2.b.hs_phy_type == 3))) ++ valid = 1; ++ else if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) && (core_if->hwcfg2.b.fs_phy_type == 1)) ++ valid = 1; ++ valid; ++ }), ++ ({ ++ int set = DWC_PHY_TYPE_PARAM_FS; ++ if (core_if->hwcfg2.b.hs_phy_type) { ++ if ((core_if->hwcfg2.b.hs_phy_type == 3) ++ || (core_if->hwcfg2.b.hs_phy_type == 1)) ++ set = DWC_PHY_TYPE_PARAM_UTMI; ++ else ++ set = DWC_PHY_TYPE_PARAM_ULPI; ++ } ++ set; ++ })); ++#endif ++ ++ retval += PARAM_CHECK_VALID(speed, "speed", ++ dwc_otg_module_params.speed == 0 ++ && (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? 0 : 1, ++ dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS ? 1 : 0); ++ ++ retval += PARAM_CHECK_VALID(host_ls_low_power_phy_clk, ++ "host_ls_low_power_phy_clk", ++ dwc_otg_module_params.host_ls_low_power_phy_clk == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ ++ && (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? 0 : 1, ++ (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ : DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ); ++ ++ PARAM_SET_DEFAULT(phy_ulpi_ddr); ++ PARAM_SET_DEFAULT(phy_ulpi_ext_vbus); ++ PARAM_SET_DEFAULT(phy_utmi_width); ++ PARAM_SET_DEFAULT(ulpi_fs_ls); ++ PARAM_SET_DEFAULT(ts_dline); ++ ++#ifdef NO_FS_PHY_HW_CHECKS ++ retval += PARAM_CHECK_VALID(i2c_enable, "i2c_enable", 1, 0); ++#else ++ retval += PARAM_CHECK_VALID(i2c_enable, "i2c_enable", ++ dwc_otg_module_params.i2c_enable == 1 ++ && (core_if->hwcfg3.b.i2c == 0) ? 0 : 1, 0); ++#endif ++ ++ for (i = 0; i < 15; i++) { ++ ++ int changed = 1; ++ int error = 0; ++ ++ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] == -1) { ++ changed = 0; ++ dwc_otg_module_params.dev_perio_tx_fifo_size[i] = ++ dwc_param_dev_perio_tx_fifo_size_default; ++ } ++ if (! ++ (dwc_otg_module_params.dev_perio_tx_fifo_size[i] <= ++ (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz[i])))) { ++ if (changed) { ++ DWC_ERROR("`%d' invalid for parameter " ++ "`dev_perio_fifo_size_%d'. " ++ "Check HW configuration.\n", ++ dwc_otg_module_params. ++ dev_perio_tx_fifo_size[i], i); ++ error = 1; ++ } ++ dwc_otg_module_params.dev_perio_tx_fifo_size[i] = ++ dwc_read_reg32(&core_if->core_global_regs-> ++ dptxfsiz[i]); ++ } ++ retval += error; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Device and host modes) interrupts. ++ */ ++static irqreturn_t dwc_otg_common_irq(int _irq, void *_dev) ++{ ++ struct dwc_otg_device *otg_dev = _dev; ++ int32_t retval = IRQ_NONE; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&otg_dev->hcd->global_lock, flags); ++ ++ retval = dwc_otg_handle_common_intr(otg_dev->core_if); ++ ++ spin_unlock_irqrestore(&otg_dev->hcd->global_lock, flags); ++ ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function is called when a device is unregistered with the ++ * dwc_otg_driver. This happens, for example, when the rmmod command is ++ * executed. The device may or may not be electrically present. If it is ++ * present, the driver stops device processing. Any resources used on behalf ++ * of this device are freed. ++ * ++ * @dev: ++ */ ++static int dwc_otg_driver_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct dwc_otg_device *otg_dev = dev->platform_data; ++ DWC_DEBUGPL(DBG_ANY, "%s(%p)\n", __func__, dev); ++ ++ if (otg_dev == NULL) ++ /* Memory allocation for the dwc_otg_device failed. */ ++ return -ENOMEM; ++ ++ /* ++ * Free the IRQ ++ */ ++ if (otg_dev->common_irq_installed) ++ free_irq(platform_get_irq(to_platform_device(dev), 0), otg_dev); ++ ++#ifndef DWC_DEVICE_ONLY ++ if (otg_dev->hcd != NULL) ++ dwc_otg_hcd_remove(dev); ++#endif ++ ++#ifndef DWC_HOST_ONLY ++ if (otg_dev->pcd != NULL) ++ dwc_otg_pcd_remove(dev); ++#endif ++ if (otg_dev->core_if != NULL) ++ dwc_otg_cil_remove(otg_dev->core_if); ++ ++ /* ++ * Remove the device attributes ++ */ ++ dwc_otg_attr_remove(dev); ++ ++ /* ++ * Clear the platform_data pointer. ++ */ ++ dev->platform_data = 0; ++ return 0; ++} ++ ++/** ++ * This function is called when an device is bound to a ++ * dwc_otg_driver. It creates the driver components required to ++ * control the device (CIL, HCD, and PCD) and it initializes the ++ * device. The driver components are stored in a dwc_otg_device ++ * structure. A reference to the dwc_otg_device is saved in the ++ * device. This allows the driver to access the dwc_otg_device ++ * structure on subsequent calls to driver methods for this device. ++ * ++ * @dev: device definition ++ */ ++static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) ++{ ++ struct resource *res_base; ++ struct device *dev = &pdev->dev; ++ struct dwc_otg_device *dwc_otg_device; ++ int32_t snpsid; ++ unsigned long flags; ++ int irq; ++ int retval; ++ ++ dev_dbg(dev, "dwc_otg_driver_probe(%p)\n", dev); ++ ++ dwc_otg_device = devm_kzalloc(&pdev->dev, ++ sizeof(struct dwc_otg_device), ++ GFP_KERNEL); ++ if (!dwc_otg_device) { ++ dev_err(dev, "kmalloc of dwc_otg_device failed\n"); ++ return -ENOMEM; ++ } ++ dwc_otg_device->reg_offset = 0xFFFFFFFF; ++ ++ /* ++ * Map the DWC_otg Core memory into virtual address space. ++ */ ++ res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res_base) ++ goto err_ports; ++ ++ dwc_otg_device->base = ++ devm_ioremap_nocache(&pdev->dev, ++ res_base->start, ++ res_base->end - res_base->start); ++ ++ if (!dwc_otg_device->base) ++ goto err_ports; ++ ++ dev_dbg(dev, "base=%p\n", dwc_otg_device->base); ++ ++ /* ++ * Attempt to ensure this device is really a DWC_otg Controller. ++ * Read and verify the SNPSID register contents. The value should be ++ * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX". ++ */ ++ snpsid = ++ dwc_read_reg32((uint32_t *) ((uint8_t *) dwc_otg_device->base + ++ 0x40)); ++ if ((snpsid & 0xFFFFF000) != 0x4F542000) { ++ dev_err(dev, "Bad value for SNPSID: 0x%08x\n", snpsid); ++ goto err_ports; ++ } ++ ++ /* ++ * Initialize driver data to point to the global DWC_otg ++ * Device structure. ++ */ ++ dev->platform_data = dwc_otg_device; ++ dev_dbg(dev, "dwc_otg_device=0x%p\n", dwc_otg_device); ++ ++ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base, ++ &dwc_otg_module_params); ++ if (dwc_otg_device->core_if == 0) { ++ dev_err(dev, "CIL initialization failed!\n"); ++ goto err_ports; ++ } ++ dwc_otg_device->core_if->usb_num = to_platform_device(dev)->id; ++ ++ /* ++ * Validate parameter values. ++ */ ++ if (check_parameters(dwc_otg_device->core_if) != 0) ++ goto err_ports; ++ ++ /* ++ * Create Device Attributes in sysfs ++ */ ++ dwc_otg_attr_create(dev); ++ ++ /* ++ * Disable the global interrupt until all the interrupt ++ * handlers are installed. ++ */ ++ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); ++ /* ++ * Install the interrupt handler for the common interrupts before ++ * enabling common interrupts in core_init below. ++ */ ++ irq = platform_get_irq(to_platform_device(dev), 0); ++ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", irq); ++ retval = request_irq(irq, dwc_otg_common_irq, ++ IRQF_SHARED, "dwc_otg", dwc_otg_device); ++ if (retval != 0) { ++ DWC_ERROR("request of irq%d failed\n", irq); ++ goto err_ports; ++ } else { ++ dwc_otg_device->common_irq_installed = 1; ++ } ++ ++ /* ++ * Initialize the DWC_otg core. ++ */ ++ dwc_otg_core_init(dwc_otg_device->core_if); ++ ++#ifndef DWC_HOST_ONLY ++ /* ++ * Initialize the PCD ++ */ ++ retval = dwc_otg_pcd_init(dev); ++ if (retval != 0) { ++ DWC_ERROR("dwc_otg_pcd_init failed\n"); ++ dwc_otg_device->pcd = NULL; ++ goto err_ports; ++ } ++#endif ++#ifndef DWC_DEVICE_ONLY ++ /* ++ * Initialize the HCD ++ */ ++ retval = dwc_otg_hcd_init(dev); ++ if (retval != 0) { ++ DWC_ERROR("dwc_otg_hcd_init failed\n"); ++ dwc_otg_device->hcd = NULL; ++ goto err_ports; ++ } ++#endif ++ ++ /* ++ * Enable the global interrupt after all the interrupt ++ * handlers are installed. ++ */ ++ local_irq_save(flags); ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ local_irq_restore(flags); ++ ++ return 0; ++ ++err_ports: ++ devm_kfree(&pdev->dev, dwc_otg_device); ++ return -ENOENT; ++} ++ ++/** ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. Both drivers and ++ * devices are registered with a bus driver. The bus driver matches ++ * devices to drivers based on information in the device and driver ++ * structures. ++ * ++ * The probe function is called when the bus driver matches a device ++ * to this driver. The remove function is called when a device is ++ * unregistered with the bus driver. ++ */ ++static struct platform_driver dwc_otg_driver = { ++ .probe = dwc_otg_driver_probe, ++ .remove = dwc_otg_driver_remove, ++ .driver = { ++ .name = dwc_driver_name, ++ .owner = THIS_MODULE}, ++}; ++ ++/** ++ * This function is called when the dwc_otg_driver is installed with the ++ * insmod command. It registers the dwc_otg_driver structure with the ++ * appropriate bus driver. This will cause the dwc_otg_driver_probe function ++ * to be called. In addition, the bus driver will automatically expose ++ * attributes defined for the device and driver in the special sysfs file ++ * system. ++ * ++ * Returns ++ */ ++static int __init dwc_otg_driver_init(void) ++{ ++ int retval; ++ ++ pr_info("%s: version %s\n", dwc_driver_name, DWC_DRIVER_VERSION); ++ ++ /* Though core was configured for external dma override that with slave ++ mode only for CN31XX. DMA is broken in this chip */ ++ if (OCTEON_IS_MODEL(OCTEON_CN31XX)) ++ dwc_otg_module_params.dma_enable = 0; ++ ++ retval = platform_driver_register(&dwc_otg_driver); ++ ++ if (retval < 0) { ++ pr_err("%s retval=%d\n", __func__, retval); ++ return retval; ++ } ++ if (driver_create_file(&dwc_otg_driver.driver, &driver_attr_version)) ++ pr_warning("DWC_OTG: Failed to create driver version file\n"); ++ ++ return retval; ++} ++module_init(dwc_otg_driver_init); ++ ++/** ++ * This function is called when the driver is removed from the kernel ++ * with the rmmod command. The driver unregisters itself with its bus ++ * driver. ++ * ++ */ ++static void __exit dwc_otg_driver_cleanup(void) ++{ ++ printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n"); ++ ++ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); ++ ++ platform_driver_unregister(&dwc_otg_driver); ++ ++ printk(KERN_INFO "%s module removed\n", dwc_driver_name); ++} ++module_exit(dwc_otg_driver_cleanup); ++ ++MODULE_DESCRIPTION(DWC_DRIVER_DESC); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE("GPL"); ++ ++module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444); ++MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None"); ++module_param_named(opt, dwc_otg_module_params.opt, int, 0444); ++MODULE_PARM_DESC(opt, "OPT Mode"); ++module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444); ++MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled"); ++module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int, ++ 0444); ++MODULE_PARM_DESC(dma_burst_size, ++ "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256"); ++module_param_named(speed, dwc_otg_module_params.speed, int, 0444); ++MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed"); ++module_param_named(host_support_fs_ls_low_power, ++ dwc_otg_module_params.host_support_fs_ls_low_power, int, ++ 0444); ++MODULE_PARM_DESC(host_support_fs_ls_low_power, ++ "Support Low Power w/FS or LS 0=Support 1=Don't Support"); ++module_param_named(host_ls_low_power_phy_clk, ++ dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444); ++MODULE_PARM_DESC(host_ls_low_power_phy_clk, ++ "Low Speed Low Power Clock 0=48Mhz 1=6Mhz"); ++module_param_named(enable_dynamic_fifo, ++ dwc_otg_module_params.enable_dynamic_fifo, int, 0444); ++MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing"); ++module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int, ++ 0444); ++MODULE_PARM_DESC(data_fifo_size, ++ "Total number of words in the data FIFO memory 32-32768"); ++module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size, ++ int, 0444); ++MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); ++module_param_named(dev_nperio_tx_fifo_size, ++ dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(dev_nperio_tx_fifo_size, ++ "Number of words in the non-periodic Tx FIFO 16-32768"); ++module_param_named(dev_perio_tx_fifo_size_1, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_1, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_2, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_2, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_3, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_3, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_4, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_4, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_5, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_5, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_6, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_6, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_7, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_7, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_8, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_8, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_9, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_9, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_10, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_10, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_11, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_11, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_12, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_12, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_13, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_13, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_14, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_14, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_15, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_15, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size, ++ int, 0444); ++MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); ++module_param_named(host_nperio_tx_fifo_size, ++ dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(host_nperio_tx_fifo_size, ++ "Number of words in the non-periodic Tx FIFO 16-32768"); ++module_param_named(host_perio_tx_fifo_size, ++ dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(host_perio_tx_fifo_size, ++ "Number of words in the host periodic Tx FIFO 16-32768"); ++module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size, ++ int, 0444); ++/** @todo Set the max to 512K, modify checks */ ++MODULE_PARM_DESC(max_transfer_size, ++ "The maximum transfer size supported in bytes 2047-65535"); ++module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count, ++ int, 0444); ++MODULE_PARM_DESC(max_packet_count, ++ "The maximum number of packets in a transfer 15-511"); ++module_param_named(host_channels, dwc_otg_module_params.host_channels, int, ++ 0444); ++MODULE_PARM_DESC(host_channels, ++ "The number of host channel registers to use 1-16"); ++module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int, ++ 0444); ++MODULE_PARM_DESC(dev_endpoints, ++ "The number of endpoints in addition to EP0 available " ++ "for device mode 1-15"); ++module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444); ++MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI"); ++module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int, ++ 0444); ++MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits"); ++module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444); ++MODULE_PARM_DESC(phy_ulpi_ddr, ++ "ULPI at double or single data rate 0=Single 1=Double"); ++module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus, ++ int, 0444); ++MODULE_PARM_DESC(phy_ulpi_ext_vbus, ++ "ULPI PHY using internal or external vbus 0=Internal"); ++module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444); ++MODULE_PARM_DESC(i2c_enable, "FS PHY Interface"); ++module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444); ++MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only"); ++module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444); ++MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs"); ++module_param_named(debug, g_dbg_lvl, int, 0644); ++MODULE_PARM_DESC(debug, ""); ++ ++/** @page "Module Parameters" ++ * ++ * The following parameters may be specified when starting the module. ++ * These parameters define how the DWC_otg controller should be ++ * configured. Parameter values are passed to the CIL initialization ++ * function dwc_otg_cil_init ++ * ++ * Example: modprobe dwc_otg speed=1 otg_cap=1 ++ * ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++*/ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_plat.h b/drivers/usb/host/dwc_otg/dwc_otg_plat.h +new file mode 100644 +index 0000000..93ef282 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_plat.h +@@ -0,0 +1,236 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_PLAT_H__) ++#define __DWC_OTG_PLAT_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define SZ_256K 0x00040000 ++#ifndef CONFIG_64BIT ++#define OCTEON_USB_BASE_ADDRESS 0x80016F0010000000ull ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains the Platform Specific constants, interfaces ++ * (functions and macros) for Linux. ++ * ++ */ ++ ++/** ++ * Reads the content of a register. ++ * ++ * @_reg: address of register to read. ++ * Returns contents of the register. ++ * ++ ++ * Usage:
++ * uint32_t dev_ctl = dwc_read_reg32(&dev_regs->dctl); ++ */ ++static inline uint32_t dwc_read_reg32(uint32_t *_reg) ++{ ++ uint32_t result; ++ /* USB device registers on Octeon are 32bit address swapped */ ++#ifdef CONFIG_64BIT ++ uint64_t address = (unsigned long)_reg ^ 4; ++#else ++ uint64_t address = OCTEON_USB_BASE_ADDRESS | ((unsigned long)_reg ^ 4); ++#endif ++ result = cvmx_read64_uint32(address); ++ return result; ++}; ++ ++/** ++ * Writes a register with a 32 bit value. ++ * ++ * @_reg: address of register to read. ++ * @_value: to write to _reg. ++ * ++ * Usage:
++ * dwc_write_reg32(&dev_regs->dctl, 0); ++ */ ++static inline void dwc_write_reg32(uint32_t *_reg, ++ const uint32_t _value) ++{ ++ /* USB device registers on Octeon are 32bit address swapped */ ++#ifdef CONFIG_64BIT ++ uint64_t address = (unsigned long)_reg ^ 4; ++#else ++ uint64_t address = OCTEON_USB_BASE_ADDRESS | ((unsigned long)_reg ^ 4); ++#endif ++ wmb(); ++ cvmx_write64_uint32(address, _value); ++ ++#ifdef CONFIG_CPU_CAVIUM_OCTEON ++ /* O2P/O1P pass 1 bug workaround: A read must occur for at least ++ every 3rd write to insure that the writes do not overrun the ++ USBN. */ ++ if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)) { ++ extern int dwc_errata_write_count; ++ if (++dwc_errata_write_count > 2) { ++ cvmx_read_csr(CVMX_USBNX_DMA0_INB_CHN0(0)); ++ dwc_errata_write_count = 0; ++ } ++ } ++#endif ++}; ++ ++/** ++ * This function modifies bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ * ++ * @_reg: address of register to read. ++ * @_clear_mask: bit mask to be cleared. ++ * @_set_mask: bit mask to be set. ++ * ++ * Usage:
++ * // Clear the SOF Interrupt Mask bit and
++ * // set the OTG Interrupt mask bit, leaving all others as they were. ++ * dwc_modify_reg32(&dev_regs->gintmsk, DWC_SOF_INT, DWC_OTG_INT);
++ */ ++static inline void dwc_modify_reg32(uint32_t *_reg, ++ const uint32_t _clear_mask, ++ const uint32_t _set_mask) ++{ ++ uint32_t value = dwc_read_reg32(_reg); ++ value &= ~_clear_mask; ++ value |= _set_mask; ++ dwc_write_reg32(_reg, value); ++}; ++ ++/* ++ * Debugging support vanishes in non-debug builds. ++ */ ++ ++/** ++ * The Debug Level bit-mask variable. ++ */ ++extern uint32_t g_dbg_lvl; ++/** ++ * Set the Debug Level variable. ++ */ ++static inline uint32_t SET_DEBUG_LEVEL(const uint32_t _new) ++{ ++ uint32_t old = g_dbg_lvl; ++ g_dbg_lvl = _new; ++ return old; ++} ++ ++/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ ++#define DBG_CIL (0x2) ++/** When debug level has the DBG_CILV bit set, display CIL Verbose debug ++ * messages */ ++#define DBG_CILV (0x20) ++/** When debug level has the DBG_PCD bit set, display PCD (Device) debug ++ * messages */ ++#define DBG_PCD (0x4) ++/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug ++ * messages */ ++#define DBG_PCDV (0x40) ++/** When debug level has the DBG_HCD bit set, display Host debug messages */ ++#define DBG_HCD (0x8) ++/** When debug level has the DBG_HCDV bit set, display Verbose Host debug ++ * messages */ ++#define DBG_HCDV (0x80) ++/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host ++ * mode. */ ++#define DBG_HCD_URB (0x800) ++ ++/** When debug level has any bit set, display debug messages */ ++#define DBG_ANY (0xFF) ++ ++/** All debug messages off */ ++#define DBG_OFF 0 ++ ++/** Prefix string for DWC_DEBUG print macros. */ ++#define USB_DWC "DWC_otg: " ++ ++/** ++ * Print a debug message when the Global debug level variable contains ++ * the bit defined in lvl. ++ * ++ * @lvl: - Debug level, use one of the DBG_ constants above. ++ * @x: - like printf ++ * ++ * Example:

++ * ++ * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); ++ * ++ *
++ * results in:
++ * ++ * usb-DWC_otg: dwc_otg_cil_init(ca867000) ++ * ++ */ ++#ifdef DEBUG ++ ++# define DWC_DEBUGPL(lvl, x...) \ ++ do { \ ++ if ((lvl)&g_dbg_lvl) \ ++ printk(KERN_DEBUG USB_DWC x); \ ++ } while (0) ++# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x) ++ ++# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) ++ ++#else ++ ++# define DWC_DEBUGPL(lvl, x...) do { } while (0) ++# define DWC_DEBUGP(x...) ++ ++# define CHK_DEBUG_LEVEL(level) (0) ++ ++#endif /*DEBUG*/ ++/* ++ * Print an Error message. ++ */ ++#define DWC_ERROR(x...) printk(KERN_ERR USB_DWC x) ++/* ++ * Print a Warning message. ++ */ ++#define DWC_WARN(x...) printk(KERN_WARNING USB_DWC x) ++/* ++ * Print a notice (normal but significant message). ++ */ ++#define DWC_NOTICE(x...) printk(KERN_NOTICE USB_DWC x) ++/* ++ * Basic message printing. ++ */ ++#define DWC_PRINT(x...) printk(KERN_INFO USB_DWC x) ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h +new file mode 100644 +index 0000000..34cc4f7 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h +@@ -0,0 +1,2355 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __DWC_OTG_REGS_H__ ++#define __DWC_OTG_REGS_H__ ++ ++/* ++ * ++ * This file contains the data structures for accessing the DWC_otg ++ * core registers. ++ * ++ * The application interfaces with the HS OTG core by reading from and ++ * writing to the Control and Status Register (CSR) space through the ++ * AHB Slave interface. These registers are 32 bits wide, and the ++ * addresses are 32-bit-block aligned. ++ * CSRs are classified as follows: ++ * - Core Global Registers ++ * - Device Mode Registers ++ * - Device Global Registers ++ * - Device Endpoint Specific Registers ++ * - Host Mode Registers ++ * - Host Global Registers ++ * - Host Port CSRs ++ * - Host Channel Specific Registers ++ * ++ * Only the Core Global registers can be accessed in both Device and ++ * Host modes. When the HS OTG core is operating in one mode, either ++ * Device or Host, the application must not access registers from the ++ * other mode. When the core switches from one mode to another, the ++ * registers in the new mode of operation must be reprogrammed as they ++ * would be after a power-on reset. ++ */ ++ ++/****************************************************************************/ ++/* DWC_otg Core registers . ++ * The dwc_otg_core_global_regs structure defines the size ++ * and relative field offsets for the Core Global registers. ++ */ ++struct dwc_otg_core_global_regs { ++ /* OTG Control and Status Register. Offset: 000h */ ++ uint32_t gotgctl; ++ /* OTG Interrupt Register. Offset: 004h */ ++ uint32_t gotgint; ++ /* Core AHB Configuration Register. Offset: 008h */ ++ uint32_t gahbcfg; ++#define DWC_GLBINTRMASK 0x0001 ++#define DWC_DMAENABLE 0x0020 ++#define DWC_NPTXEMPTYLVL_EMPTY 0x0080 ++#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000 ++#define DWC_PTXEMPTYLVL_EMPTY 0x0100 ++#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000 ++ ++ /* Core USB Configuration Register. Offset: 00Ch */ ++ uint32_t gusbcfg; ++ /* Core Reset Register. Offset: 010h */ ++ uint32_t grstctl; ++ /* Core Interrupt Register. Offset: 014h */ ++ uint32_t gintsts; ++ /* Core Interrupt Mask Register. Offset: 018h */ ++ uint32_t gintmsk; ++ /* Receive Status Queue Read Register (Read Only). Offset: 01Ch */ ++ uint32_t grxstsr; ++ /* Receive Status Queue Read & POP Register (Read Only). Offset: 020h*/ ++ uint32_t grxstsp; ++ /* Receive FIFO Size Register. Offset: 024h */ ++ uint32_t grxfsiz; ++ /* Non Periodic Transmit FIFO Size Register. Offset: 028h */ ++ uint32_t gnptxfsiz; ++ /* ++ *Non Periodic Transmit FIFO/Queue Status Register (Read ++ * Only). Offset: 02Ch ++ */ ++ uint32_t gnptxsts; ++ /* I2C Access Register. Offset: 030h */ ++ uint32_t gi2cctl; ++ /* PHY Vendor Control Register. Offset: 034h */ ++ uint32_t gpvndctl; ++ /* General Purpose Input/Output Register. Offset: 038h */ ++ uint32_t ggpio; ++ /* User ID Register. Offset: 03Ch */ ++ uint32_t guid; ++ /* Synopsys ID Register (Read Only). Offset: 040h */ ++ uint32_t gsnpsid; ++ /* User HW Config1 Register (Read Only). Offset: 044h */ ++ uint32_t ghwcfg1; ++ /* User HW Config2 Register (Read Only). Offset: 048h */ ++ uint32_t ghwcfg2; ++#define DWC_SLAVE_ONLY_ARCH 0 ++#define DWC_EXT_DMA_ARCH 1 ++#define DWC_INT_DMA_ARCH 2 ++ ++#define DWC_MODE_HNP_SRP_CAPABLE 0 ++#define DWC_MODE_SRP_ONLY_CAPABLE 1 ++#define DWC_MODE_NO_HNP_SRP_CAPABLE 2 ++#define DWC_MODE_SRP_CAPABLE_DEVICE 3 ++#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define DWC_MODE_SRP_CAPABLE_HOST 5 ++#define DWC_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ /* User HW Config3 Register (Read Only). Offset: 04Ch */ ++ uint32_t ghwcfg3; ++ /* User HW Config4 Register (Read Only). Offset: 050h*/ ++ uint32_t ghwcfg4; ++ /* Reserved Offset: 054h-0FFh */ ++ uint32_t reserved[43]; ++ /* Host Periodic Transmit FIFO Size Register. Offset: 100h */ ++ uint32_t hptxfsiz; ++ /* ++ * Device Periodic Transmit FIFO#n Register. ++ * Offset: 104h + (FIFO_Number-1)*04h, ++ * 1 <= FIFO Number <= 15 (1<=n<=15). ++ */ ++ uint32_t dptxfsiz[15]; ++}; ++ ++/* ++ * This union represents the bit fields of the Core OTG Control ++ * and Status Register (GOTGCTL). Set the bits using the bit ++ * fields then write the d32 value to the register. ++ */ ++union gotgctl_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved21_31:11; ++ unsigned currmod:1; ++ unsigned bsesvld:1; ++ unsigned asesvld:1; ++ unsigned reserved17:1; ++ unsigned conidsts:1; ++ unsigned reserved12_15:4; ++ unsigned devhnpen:1; ++ unsigned hstsethnpen:1; ++ unsigned hnpreq:1; ++ unsigned hstnegscs:1; ++ unsigned reserved2_7:6; ++ unsigned sesreq:1; ++ unsigned sesreqscs:1; ++#else ++ unsigned sesreqscs:1; ++ unsigned sesreq:1; ++ unsigned reserved2_7:6; ++ unsigned hstnegscs:1; ++ unsigned hnpreq:1; ++ unsigned hstsethnpen:1; ++ unsigned devhnpen:1; ++ unsigned reserved12_15:4; ++ unsigned conidsts:1; ++ unsigned reserved17:1; ++ unsigned asesvld:1; ++ unsigned bsesvld:1; ++ unsigned currmod:1; ++ unsigned reserved21_31:11; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields of the Core OTG Interrupt Register ++ * (GOTGINT). Set/clear the bits using the bit fields then write the d32 ++ * value to the register. ++ */ ++union gotgint_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved31_20:12; ++ unsigned debdone:1; ++ unsigned adevtoutchng:1; ++ unsigned hstnegdet:1; ++ unsigned reserver10_16:7; ++ unsigned hstnegsucstschng:1; ++ unsigned sesreqsucstschng:1; ++ unsigned reserved3_7:5; ++ unsigned sesenddet:1; ++ unsigned reserved0_1:2; ++#else ++ ++ /* Current Mode */ ++ unsigned reserved0_1:2; ++ ++ /* Session End Detected */ ++ unsigned sesenddet:1; ++ ++ unsigned reserved3_7:5; ++ ++ /* Session Request Success Status Change */ ++ unsigned sesreqsucstschng:1; ++ /* Host Negotiation Success Status Change */ ++ unsigned hstnegsucstschng:1; ++ ++ unsigned reserver10_16:7; ++ ++ /* Host Negotiation Detected */ ++ unsigned hstnegdet:1; ++ /* A-Device Timeout Change */ ++ unsigned adevtoutchng:1; ++ /* Debounce Done */ ++ unsigned debdone:1; ++ ++ unsigned reserved31_20:12; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields of the Core AHB Configuration ++ * Register (GAHBCFG). Set/clear the bits using the bit fields then ++ * write the d32 value to the register. ++ */ ++union gahbcfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 ++#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1 ++#define DWC_GAHBCFG_DMAENABLE 1 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1 ++#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0 ++#define DWC_GAHBCFG_GLBINT_ENABLE 1 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved9_31:23; ++ unsigned ptxfemplvl:1; ++ unsigned nptxfemplvl:1; ++ unsigned reserved:1; ++ unsigned dmaenable:1; ++ unsigned hburstlen:4; ++ unsigned glblintrmsk:1; ++#else ++ unsigned glblintrmsk:1; ++ unsigned hburstlen:4; ++ unsigned dmaenable:1; ++ unsigned reserved:1; ++ unsigned nptxfemplvl:1; ++ unsigned ptxfemplvl:1; ++ unsigned reserved9_31:23; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields of the Core USB Configuration ++ * Register (GUSBCFG). Set the bits using the bit fields then write ++ * the d32 value to the register. ++ */ ++union gusbcfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:9; ++ unsigned term_sel_dl_pulse:1; ++ unsigned ulpi_int_vbus_indicator:1; ++ unsigned ulpi_ext_vbus_drv:1; ++ unsigned ulpi_clk_sus_m:1; ++ unsigned ulpi_auto_res:1; ++ unsigned ulpi_fsls:1; ++ unsigned otgutmifssel:1; ++ unsigned phylpwrclksel:1; ++ unsigned nptxfrwnden:1; ++ unsigned usbtrdtim:4; ++ unsigned hnpcap:1; ++ unsigned srpcap:1; ++ unsigned ddrsel:1; ++ unsigned physel:1; ++ unsigned fsintf:1; ++ unsigned ulpi_utmi_sel:1; ++ unsigned phyif:1; ++ unsigned toutcal:3; ++#else ++ unsigned toutcal:3; ++ unsigned phyif:1; ++ unsigned ulpi_utmi_sel:1; ++ unsigned fsintf:1; ++ unsigned physel:1; ++ unsigned ddrsel:1; ++ unsigned srpcap:1; ++ unsigned hnpcap:1; ++ unsigned usbtrdtim:4; ++ unsigned nptxfrwnden:1; ++ unsigned phylpwrclksel:1; ++ unsigned otgutmifssel:1; ++ unsigned ulpi_fsls:1; ++ unsigned ulpi_auto_res:1; ++ unsigned ulpi_clk_sus_m:1; ++ unsigned ulpi_ext_vbus_drv:1; ++ unsigned ulpi_int_vbus_indicator:1; ++ unsigned term_sel_dl_pulse:1; ++ unsigned reserved:9; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields of the Core Reset Register ++ * (GRSTCTL). Set/clear the bits using the bit fields then write the ++ * d32 value to the register. ++ */ ++union grstctl_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned ahbidle:1; ++ unsigned dmareq:1; ++ unsigned reserved11_29:19; ++ unsigned txfnum:5; ++ unsigned txfflsh:1; ++ unsigned rxfflsh:1; ++ unsigned intknqflsh:1; ++ unsigned hstfrm:1; ++ unsigned hsftrst:1; ++ unsigned csftrst:1; ++#else ++ ++ /* ++ * Core Soft Reset (CSftRst) (Device and Host) ++ * ++ * The application can flush the control logic in the ++ * entire core using this bit. This bit resets the ++ * pipelines in the AHB Clock domain as well as the ++ * PHY Clock domain. ++ * ++ * The state machines are reset to an IDLE state, the ++ * control bits in the CSRs are cleared, all the ++ * transmit FIFOs and the receive FIFO are flushed. ++ * ++ * The status mask bits that control the generation of ++ * the interrupt, are cleared, to clear the ++ * interrupt. The interrupt status bits are not ++ * cleared, so the application can get the status of ++ * any events that occurred in the core after it has ++ * set this bit. ++ * ++ * Any transactions on the AHB are terminated as soon ++ * as possible following the protocol. Any ++ * transactions on the USB are terminated immediately. ++ * ++ * The configuration settings in the CSRs are ++ * unchanged, so the software doesn't have to ++ * reprogram these registers (Device ++ * Configuration/Host Configuration/Core System ++ * Configuration/Core PHY Configuration). ++ * ++ * The application can write to this bit, any time it ++ * wants to reset the core. This is a self clearing ++ * bit and the core clears this bit after all the ++ * necessary logic is reset in the core, which may ++ * take several clocks, depending on the current state ++ * of the core. ++ */ ++ unsigned csftrst:1; ++ /* ++ * Hclk Soft Reset ++ * ++ * The application uses this bit to reset the control logic in ++ * the AHB clock domain. Only AHB clock domain pipelines are ++ * reset. ++ */ ++ unsigned hsftrst:1; ++ /* ++ * Host Frame Counter Reset (Host Only)
++ * ++ * The application can reset the (micro)frame number ++ * counter inside the core, using this bit. When the ++ * (micro)frame counter is reset, the subsequent SOF ++ * sent out by the core, will have a (micro)frame ++ * number of 0. ++ */ ++ unsigned hstfrm:1; ++ /* ++ * In Token Sequence Learning Queue Flush ++ * (INTknQFlsh) (Device Only) ++ */ ++ unsigned intknqflsh:1; ++ /* ++ * RxFIFO Flush (RxFFlsh) (Device and Host) ++ * ++ * The application can flush the entire Receive FIFO ++ * using this bit.

The application must first ++ * ensure that the core is not in the middle of a ++ * transaction.

The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is reading from the RxFIFO nor the MAC ++ * is writing the data in to the FIFO.

The ++ * application should wait until the bit is cleared ++ * before performing any other operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned rxfflsh:1; ++ /* ++ * TxFIFO Flush (TxFFlsh) (Device and Host). ++ * ++ * This bit is used to selectively flush a single or ++ * all transmit FIFOs. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction.

The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is writing into the TxFIFO nor the MAC ++ * is reading the data out of the FIFO.

The ++ * application should wait until the core clears this ++ * bit, before performing any operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned txfflsh:1; ++ ++ /* ++ * TxFIFO Number (TxFNum) (Device and Host). ++ * ++ * This is the FIFO number which needs to be flushed, ++ * using the TxFIFO Flush bit. This field should not ++ * be changed until the TxFIFO Flush bit is cleared by ++ * the core. ++ * - 0x0:Non Periodic TxFIFO Flush ++ * - 0x1:Periodic TxFIFO #1 Flush in device mode ++ * or Periodic TxFIFO in host mode ++ * - 0x2:Periodic TxFIFO #2 Flush in device mode. ++ * - ... ++ * - 0xF:Periodic TxFIFO #15 Flush in device mode ++ * - 0x10: Flush all the Transmit NonPeriodic and ++ * Transmit Periodic FIFOs in the core ++ */ ++ unsigned txfnum:5; ++ /* Reserved */ ++ unsigned reserved11_29:19; ++ /* ++ * DMA Request Signal. Indicated DMA request is in ++ * probress. Used for debug purpose. ++ */ ++ unsigned dmareq:1; ++ /* ++ * AHB Master Idle. Indicates the AHB Master State ++ * Machine is in IDLE condition. ++ */ ++ unsigned ahbidle:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields of the Core Interrupt Mask ++ * Register (GINTMSK). Set/clear the bits using the bit fields then ++ * write the d32 value to the register. ++ */ ++union gintmsk_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned wkupintr:1; ++ unsigned sessreqintr:1; ++ unsigned disconnect:1; ++ unsigned conidstschng:1; ++ unsigned reserved27:1; ++ unsigned ptxfempty:1; ++ unsigned hcintr:1; ++ unsigned portintr:1; ++ unsigned reserved22_23:2; ++ unsigned incomplisoout:1; ++ unsigned incomplisoin:1; ++ unsigned outepintr:1; ++ unsigned inepintr:1; ++ unsigned epmismatch:1; ++ unsigned reserved16:1; ++ unsigned eopframe:1; ++ unsigned isooutdrop:1; ++ unsigned enumdone:1; ++ unsigned usbreset:1; ++ unsigned usbsuspend:1; ++ unsigned erlysuspend:1; ++ unsigned i2cintr:1; ++ unsigned reserved8:1; ++ unsigned goutnakeff:1; ++ unsigned ginnakeff:1; ++ unsigned nptxfempty:1; ++ unsigned rxstsqlvl:1; ++ unsigned sofintr:1; ++ unsigned otgintr:1; ++ unsigned modemismatch:1; ++ unsigned reserved0:1; ++#else ++ unsigned reserved0:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned reserved8:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned reserved16:1; ++ unsigned epmismatch:1; ++ unsigned inepintr:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned reserved22_23:2; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned reserved27:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields of the Core Interrupt Register ++ * (GINTSTS). Set/clear the bits using the bit fields then write the ++ * d32 value to the register. ++ */ ++union gintsts_data { ++ /* raw register data */ ++ uint32_t d32; ++#define DWC_SOF_INTR_MASK 0x0008 ++ ++ /* register bits */ ++ struct { ++#define DWC_HOST_MODE 1 ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned wkupintr:1; ++ unsigned sessreqintr:1; ++ unsigned disconnect:1; ++ unsigned conidstschng:1; ++ unsigned reserved27:1; ++ unsigned ptxfempty:1; ++ unsigned hcintr:1; ++ unsigned portintr:1; ++ unsigned reserved22_23:2; ++ unsigned incomplisoout:1; ++ unsigned incomplisoin:1; ++ unsigned outepintr:1; ++ unsigned inepint:1; ++ unsigned epmismatch:1; ++ unsigned intokenrx:1; ++ unsigned eopframe:1; ++ unsigned isooutdrop:1; ++ unsigned enumdone:1; ++ unsigned usbreset:1; ++ unsigned usbsuspend:1; ++ unsigned erlysuspend:1; ++ unsigned i2cintr:1; ++ unsigned reserved8:1; ++ unsigned goutnakeff:1; ++ unsigned ginnakeff:1; ++ unsigned nptxfempty:1; ++ unsigned rxstsqlvl:1; ++ unsigned sofintr:1; ++ unsigned otgintr:1; ++ unsigned modemismatch:1; ++ unsigned curmode:1; ++#else ++ unsigned curmode:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned reserved8:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned intokenrx:1; ++ unsigned epmismatch:1; ++ unsigned inepint:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned reserved22_23:2; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned reserved27:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Device Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * element then read out the bits using the bit elements. ++ */ ++union device_grxsts_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_DSTS_SETUP_UPDT 0x6 /* SETUP Packet */ ++#define DWC_DSTS_SETUP_COMP 0x4 /* Setup Phase Complete */ ++#define DWC_DSTS_GOUT_NAK 0x1 /* Global OUT NAK */ ++#define DWC_STS_XFER_COMP 0x3 /* OUT Data Transfer Complete */ ++#define DWC_STS_DATA_UPDT 0x2 /* OUT Data Packet */ ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:7; ++ unsigned fn:4; ++ unsigned pktsts:4; ++ unsigned dpid:2; ++ unsigned bcnt:11; ++ unsigned epnum:4; ++#else ++ unsigned epnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ unsigned pktsts:4; ++ unsigned fn:4; ++ unsigned reserved:7; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Host Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * element then read out the bits using the bit elements. ++ */ ++union host_grxsts_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7 ++#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 ++#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3 ++#define DWC_GRXSTS_PKTSTS_IN 0x2 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:11; ++ unsigned pktsts:4; ++ unsigned dpid:2; ++ unsigned bcnt:11; ++ unsigned chnum:4; ++#else ++ unsigned chnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ unsigned pktsts:4; ++ unsigned reserved:11; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ, ++ * GNPTXFSIZ, DPTXFSIZn). Read the register into the d32 element then ++ * read out the bits using the bit elements. ++ */ ++union fifosize_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned depth:16; ++ unsigned startaddr:16; ++#else ++ unsigned startaddr:16; ++ unsigned depth:16; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Non-Periodic Transmit ++ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the ++ * d32 element then read out the bits using the bit ++ * elements. ++ */ ++union gnptxsts_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:1; ++ unsigned nptxqtop_chnep:4; ++ unsigned nptxqtop_token:2; ++ unsigned nptxqtop_terminate:1; ++ unsigned nptxqspcavail:8; ++ unsigned nptxfspcavail:16; ++#else ++ unsigned nptxfspcavail:16; ++ unsigned nptxqspcavail:8; ++ /* ++ * Top of the Non-Periodic Transmit Request Queue ++ * - bit 24 - Terminate (Last entry for the selected ++ * channel/EP) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - IN/OUT ++ * - 2'b01 - Zero Length OUT ++ * - 2'b10 - PING/Complete Split ++ * - 2'b11 - Channel Halt ++ * - bits 30:27 - Channel/EP Number ++ */ ++ unsigned nptxqtop_terminate:1; ++ unsigned nptxqtop_token:2; ++ unsigned nptxqtop_chnep:4; ++ unsigned reserved:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the I2C Control Register ++ * (I2CCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++union gi2cctl_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned bsydne:1; ++ unsigned rw:1; ++ unsigned reserved:2; ++ unsigned i2cdevaddr:2; ++ unsigned i2csuspctl:1; ++ unsigned ack:1; ++ unsigned i2cen:1; ++ unsigned addr:7; ++ unsigned regaddr:8; ++ unsigned rwdata:8; ++#else ++ unsigned rwdata:8; ++ unsigned regaddr:8; ++ unsigned addr:7; ++ unsigned i2cen:1; ++ unsigned ack:1; ++ unsigned i2csuspctl:1; ++ unsigned i2cdevaddr:2; ++ unsigned reserved:2; ++ unsigned rw:1; ++ unsigned bsydne:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the User HW Config1 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++union hwcfg1_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned ep_dir15:2; ++ unsigned ep_dir14:2; ++ unsigned ep_dir13:2; ++ unsigned ep_dir12:2; ++ unsigned ep_dir11:2; ++ unsigned ep_dir10:2; ++ unsigned ep_dir9:2; ++ unsigned ep_dir8:2; ++ unsigned ep_dir7:2; ++ unsigned ep_dir6:2; ++ unsigned ep_dir5:2; ++ unsigned ep_dir4:2; ++ unsigned ep_dir3:2; ++ unsigned ep_dir2:2; ++ unsigned ep_dir1:2; ++ unsigned ep_dir0:2; ++#else ++ unsigned ep_dir0:2; ++ unsigned ep_dir1:2; ++ unsigned ep_dir2:2; ++ unsigned ep_dir3:2; ++ unsigned ep_dir4:2; ++ unsigned ep_dir5:2; ++ unsigned ep_dir6:2; ++ unsigned ep_dir7:2; ++ unsigned ep_dir8:2; ++ unsigned ep_dir9:2; ++ unsigned ep_dir10:2; ++ unsigned ep_dir11:2; ++ unsigned ep_dir12:2; ++ unsigned ep_dir13:2; ++ unsigned ep_dir14:2; ++ unsigned ep_dir15:2; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the User HW Config2 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++union hwcfg2_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 ++#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2 ++#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1 ++#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 ++#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 ++#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 ++#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 ++#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2 ++#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1 ++#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved31:1; ++ unsigned dev_token_q_depth:5; ++ unsigned host_perio_tx_q_depth:2; ++ unsigned nonperio_tx_q_depth:2; ++ unsigned rx_status_q_depth:2; ++ unsigned dynamic_fifo:1; ++ unsigned perio_ep_supported:1; ++ unsigned num_host_chan:4; ++ unsigned num_dev_ep:4; ++ unsigned fs_phy_type:2; ++ unsigned hs_phy_type:2; ++ unsigned point2point:1; ++ unsigned architecture:2; ++ unsigned op_mode:3; ++#else ++ unsigned op_mode:3; ++ unsigned architecture:2; ++ unsigned point2point:1; ++ unsigned hs_phy_type:2; ++ unsigned fs_phy_type:2; ++ unsigned num_dev_ep:4; ++ unsigned num_host_chan:4; ++ unsigned perio_ep_supported:1; ++ unsigned dynamic_fifo:1; ++ unsigned rx_status_q_depth:2; ++ unsigned nonperio_tx_q_depth:2; ++ unsigned host_perio_tx_q_depth:2; ++ unsigned dev_token_q_depth:5; ++ unsigned reserved31:1; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the User HW Config3 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++union hwcfg3_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++ /* GHWCFG3 */ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned dfifo_depth:16; ++ unsigned reserved15_13:3; ++ unsigned ahb_phy_clock_synch:1; ++ unsigned synch_reset_type:1; ++ unsigned optional_features:1; ++ unsigned vendor_ctrl_if:1; ++ unsigned i2c:1; ++ unsigned otg_func:1; ++ unsigned packet_size_cntr_width:3; ++ unsigned xfer_size_cntr_width:4; ++#else ++ unsigned xfer_size_cntr_width:4; ++ unsigned packet_size_cntr_width:3; ++ unsigned otg_func:1; ++ unsigned i2c:1; ++ unsigned vendor_ctrl_if:1; ++ unsigned optional_features:1; ++ unsigned synch_reset_type:1; ++ unsigned ahb_phy_clock_synch:1; ++ unsigned reserved15_13:3; ++ unsigned dfifo_depth:16; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the User HW Config4 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++union hwcfg4_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved31_25:7; ++ unsigned session_end_filt_en:1; ++ unsigned b_valid_filt_en:1; ++ unsigned a_valid_filt_en:1; ++ unsigned vbus_valid_filt_en:1; ++ unsigned iddig_filt_en:1; ++ unsigned num_dev_mode_ctrl_ep:4; ++ unsigned utmi_phy_data_width:2; ++ unsigned min_ahb_freq:9; ++ unsigned power_optimiz:1; ++ unsigned num_dev_perio_in_ep:4; ++#else ++ unsigned num_dev_perio_in_ep:4; ++ unsigned power_optimiz:1; ++ unsigned min_ahb_freq:9; ++ unsigned utmi_phy_data_width:2; ++ unsigned num_dev_mode_ctrl_ep:4; ++ unsigned iddig_filt_en:1; ++ unsigned vbus_valid_filt_en:1; ++ unsigned a_valid_filt_en:1; ++ unsigned b_valid_filt_en:1; ++ unsigned session_end_filt_en:1; ++ unsigned reserved31_25:7; ++#endif ++ } b; ++}; ++ ++ ++/* ++ * Device Global Registers. Offsets 800h-BFFh ++ * ++ * The following structures define the size and relative field offsets ++ * for the Device Mode Registers. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++struct dwc_otg_dev_global_regs { ++ /* Device Configuration Register. Offset 800h */ ++ uint32_t dcfg; ++ /* Device Control Register. Offset: 804h */ ++ uint32_t dctl; ++ /* Device Status Register (Read Only). Offset: 808h */ ++ uint32_t dsts; ++ /* Reserved. Offset: 80Ch */ ++ uint32_t unused; ++ /* ++ * Device IN Endpoint Common Interrupt Mask Register. Offset: 810h ++ */ ++ uint32_t diepmsk; ++ /* ++ * Device OUT Endpoint Common Interrupt Mask ++ * Register. Offset: 814h ++ */ ++ uint32_t doepmsk; ++ /* ++ * Device All Endpoints Interrupt Register. Offset: 818h ++ */ ++ uint32_t daint; ++ /* ++ * Device All Endpoints Interrupt Mask Register. Offset: ++ * 81Ch ++ */ ++ uint32_t daintmsk; ++ /* ++ * Device IN Token Queue Read Register-1 (Read Only). ++ * Offset: 820h ++ */ ++ uint32_t dtknqr1; ++ /* ++ * Device IN Token Queue Read Register-2 (Read Only). ++ * Offset: 824h ++ */ ++ uint32_t dtknqr2; ++ /* ++ * Device VBUS discharge Register. Offset: 828h ++ */ ++ uint32_t dvbusdis; ++ /* ++ * Device VBUS Pulse Register. Offset: 82Ch ++ */ ++ uint32_t dvbuspulse; ++ /* ++ * Device IN Token Queue Read Register-3 (Read Only). ++ * Offset: 830h ++ */ ++ uint32_t dtknqr3; ++ /* ++ * Device IN Token Queue Read Register-4 (Read Only). ++ * Offset: 834h ++ */ ++ uint32_t dtknqr4; ++}; ++ ++/* ++ * This union represents the bit fields in the Device Configuration ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. Write the ++ * d32 member to the dcfg register. ++ */ ++union dcfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_DCFG_FRAME_INTERVAL_95 3 ++#define DWC_DCFG_FRAME_INTERVAL_90 2 ++#define DWC_DCFG_FRAME_INTERVAL_85 1 ++#define DWC_DCFG_FRAME_INTERVAL_80 0 ++#define DWC_DCFG_SEND_STALL 1 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved9:10; ++ unsigned epmscnt:4; ++ unsigned reserved13_17:5; ++ unsigned perfrint:2; ++ unsigned devaddr:7; ++ unsigned reserved3:1; ++ unsigned nzstsouthshk:1; ++ unsigned devspd:2; ++#else ++ ++ /* Device Speed */ ++ unsigned devspd:2; ++ /* Non Zero Length Status OUT Handshake */ ++ unsigned nzstsouthshk:1; ++ unsigned reserved3:1; ++ /* Device Addresses */ ++ unsigned devaddr:7; ++ /* Periodic Frame Interval */ ++ unsigned perfrint:2; ++ unsigned reserved13_17:5; ++ /* In Endpoint Mis-match count */ ++ unsigned epmscnt:4; ++ unsigned reserved9:10; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Device Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++union dctl_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:21; ++ unsigned cgoutnak:1; ++ unsigned sgoutnak:1; ++ unsigned cgnpinnak:1; ++ unsigned sgnpinnak:1; ++ unsigned tstctl:3; ++ unsigned goutnaksts:1; ++ unsigned gnpinnaksts:1; ++ unsigned sftdiscon:1; ++ unsigned rmtwkupsig:1; ++#else ++ ++ /* Remote Wakeup */ ++ unsigned rmtwkupsig:1; ++ /* Soft Disconnect */ ++ unsigned sftdiscon:1; ++ /* Global Non-Periodic IN NAK Status */ ++ unsigned gnpinnaksts:1; ++ /* Global OUT NAK Status */ ++ unsigned goutnaksts:1; ++ /* Test Control */ ++ unsigned tstctl:3; ++ /* Set Global Non-Periodic IN NAK */ ++ unsigned sgnpinnak:1; ++ /* Clear Global Non-Periodic IN NAK */ ++ unsigned cgnpinnak:1; ++ /* Set Global OUT NAK */ ++ unsigned sgoutnak:1; ++ /* Clear Global OUT NAK */ ++ unsigned cgoutnak:1; ++ ++ unsigned reserved:21; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Device Status ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++union dsts_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3 ++#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2 ++#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 ++#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved22_31:10; ++ unsigned soffn:14; ++ unsigned reserved4_7:4; ++ unsigned errticerr:1; ++ unsigned enumspd:2; ++ unsigned suspsts:1; ++#else ++ ++ /* Suspend Status */ ++ unsigned suspsts:1; ++ /* Enumerated Speed */ ++ unsigned enumspd:2; ++ /* Erratic Error */ ++ unsigned errticerr:1; ++ unsigned reserved4_7:4; ++ /* Frame or Microframe Number of the received SOF */ ++ unsigned soffn:14; ++ unsigned reserved22_31:10; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Device IN EP Interrupt ++ * Register and the Device IN EP Common Mask Register. ++ * ++ * It also represents the bit fields in the Device IN EP Common ++ * Interrupt Mask Register. ++ ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++union diepint_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved07_31:25; ++ unsigned inepnakeff:1; ++ unsigned intknepmis:1; ++ unsigned intktxfemp:1; ++ unsigned timeout:1; ++ unsigned ahberr:1; ++ unsigned epdisabled:1; ++ unsigned xfercompl:1; ++#else ++ ++y /* Transfer complete mask */ ++ unsigned xfercompl:1; ++ /* Endpoint disable mask */ ++ unsigned epdisabled:1; ++ /* AHB Error mask */ ++ unsigned ahberr:1; ++ /* TimeOUT Handshake mask (non-ISOC EPs) */ ++ unsigned timeout:1; ++ /* IN Token received with TxF Empty mask */ ++ unsigned intktxfemp:1; ++ /* IN Token Received with EP mismatch mask */ ++ unsigned intknepmis:1; ++ /* IN Endpoint HAK Effective mask */ ++ unsigned inepnakeff:1; ++ unsigned reserved07_31:25; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP Interrupt ++ * Registerand Device OUT EP Common Interrupt Mask Register. ++ * ++ * It also represents the bit fields in the Device OUT EP Common ++ * Interrupt Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++union doepint_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved04_31:28; ++ unsigned setup:1; ++ unsigned ahberr:1; ++ unsigned epdisabled:1; ++ unsigned xfercompl:1; ++#else ++ ++ /* Transfer complete */ ++ unsigned xfercompl:1; ++ /* Endpoint disable */ ++ unsigned epdisabled:1; ++ /* AHB Error */ ++ unsigned ahberr:1; ++ /* Setup Phase Done (contorl EPs) */ ++ unsigned setup:1; ++ unsigned reserved04_31:28; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Device All EP Interrupt ++ * and Mask Registers. ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++union daint_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned out:16; ++ unsigned in:16; ++#else ++ ++ /* IN Endpoint bits */ ++ unsigned in:16; ++ /* OUT Endpoint bits */ ++ unsigned out:16; ++#endif ++ } ep; ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned outep15:1; ++ unsigned outep14:1; ++ unsigned outep13:1; ++ unsigned outep12:1; ++ unsigned outep11:1; ++ unsigned outep10:1; ++ unsigned outep9:1; ++ unsigned outep8:1; ++ unsigned outep7:1; ++ unsigned outep6:1; ++ unsigned outep5:1; ++ unsigned outep4:1; ++ unsigned outep3:1; ++ unsigned outep2:1; ++ unsigned outep1:1; ++ unsigned outep0:1; ++ unsigned inep15:1; ++ unsigned inep14:1; ++ unsigned inep13:1; ++ unsigned inep12:1; ++ unsigned inep11:1; ++ unsigned inep10:1; ++ unsigned inep9:1; ++ unsigned inep8:1; ++ unsigned inep7:1; ++ unsigned inep6:1; ++ unsigned inep5:1; ++ unsigned inep4:1; ++ unsigned inep3:1; ++ unsigned inep2:1; ++ unsigned inep1:1; ++ unsigned inep0:1; ++#else ++ ++ /* IN Endpoint bits */ ++ unsigned inep0:1; ++ unsigned inep1:1; ++ unsigned inep2:1; ++ unsigned inep3:1; ++ unsigned inep4:1; ++ unsigned inep5:1; ++ unsigned inep6:1; ++ unsigned inep7:1; ++ unsigned inep8:1; ++ unsigned inep9:1; ++ unsigned inep10:1; ++ unsigned inep11:1; ++ unsigned inep12:1; ++ unsigned inep13:1; ++ unsigned inep14:1; ++ unsigned inep15:1; ++ /* OUT Endpoint bits */ ++ unsigned outep0:1; ++ unsigned outep1:1; ++ unsigned outep2:1; ++ unsigned outep3:1; ++ unsigned outep4:1; ++ unsigned outep5:1; ++ unsigned outep6:1; ++ unsigned outep7:1; ++ unsigned outep8:1; ++ unsigned outep9:1; ++ unsigned outep10:1; ++ unsigned outep11:1; ++ unsigned outep12:1; ++ unsigned outep13:1; ++ unsigned outep14:1; ++ unsigned outep15:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Device IN Token Queue ++ * Read Registers. ++ * - Read the register into the d32 member. ++ * - READ-ONLY Register ++ */ ++union dtknq1_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned epnums0_5:24; ++ unsigned wrap_bit:1; ++ unsigned reserved05_06:2; ++ unsigned intknwptr:5; ++#else ++ ++ /* In Token Queue Write Pointer */ ++ unsigned intknwptr:5; ++ /* Reserved */ ++ unsigned reserved05_06:2; ++ /* write pointer has wrapped. */ ++ unsigned wrap_bit:1; ++ /* EP Numbers of IN Tokens 0 ... 4 */ ++ unsigned epnums0_5:24; ++#endif ++ } b; ++}; ++ ++/* ++ * Device Logical IN Endpoint-Specific Registers. Offsets ++ * 900h-AFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++struct dwc_otg_dev_in_ep_regs { ++ /* ++ * Device IN Endpoint Control Register. Offset:900h + ++ * (ep_num * 20h) + 00h ++ */ ++ uint32_t diepctl; ++ /* Reserved. Offset:900h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /* ++ * Device IN Endpoint Interrupt Register. Offset:900h + ++ * (ep_num * 20h) + 08h ++ */ ++ uint32_t diepint; ++ /* Reserved. Offset:900h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /* ++ * Device IN Endpoint Transfer Size ++ * Register. Offset:900h + (ep_num * 20h) + 10h ++ */ ++ uint32_t dieptsiz; ++ /* ++ * Device IN Endpoint DMA Address Register. Offset:900h + ++ * (ep_num * 20h) + 14h ++ */ ++ uint32_t diepdma; ++ /* ++ * Reserved. Offset:900h + (ep_num * 20h) + 18h - 900h + ++ * (ep_num * 20h) + 1Ch ++ */ ++ uint32_t reserved18[2]; ++}; ++ ++/** ++ * Device Logical OUT Endpoint-Specific Registers. Offsets: ++ * B00h-CFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++struct dwc_otg_dev_out_ep_regs { ++ /* ++ * Device OUT Endpoint Control Register. Offset:B00h + ++ * (ep_num * 20h) + 00h ++ */ ++ uint32_t doepctl; ++ /* ++ * Device OUT Endpoint Frame number Register. Offset: ++ * B00h + (ep_num * 20h) + 04h ++ */ ++ uint32_t doepfn; ++ /* ++ * Device OUT Endpoint Interrupt Register. Offset:B00h + ++ * (ep_num * 20h) + 08h ++ */ ++ uint32_t doepint; ++ /* ++ * Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /* ++ * Device OUT Endpoint Transfer Size Register. Offset: ++ * B00h + (ep_num * 20h) + 10h ++ */ ++ uint32_t doeptsiz; ++ /* ++ * Device OUT Endpoint DMA Address Register. Offset:B00h ++ * + (ep_num * 20h) + 14h ++ */ ++ uint32_t doepdma; ++ /* ++ * Reserved. Offset:B00h + (ep_num * 20h) + 18h - B00h + ++ * (ep_num * 20h) + 1Ch ++ */ ++ uint32_t unused[2]; ++}; ++ ++/* ++ * This union represents the bit fields in the Device EP Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++union depctl_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#define DWC_DEP0CTL_MPS_64 0 ++#define DWC_DEP0CTL_MPS_32 1 ++#define DWC_DEP0CTL_MPS_16 2 ++#define DWC_DEP0CTL_MPS_8 3 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned mps:11; ++ unsigned epena:1; ++ unsigned epdis:1; ++ unsigned setd1pid:1; ++ unsigned setd0pid:1; ++ unsigned snak:1; ++ unsigned cnak:1; ++ unsigned txfnum:4; ++ unsigned stall:1; ++ unsigned snp:1; ++ unsigned eptype:2; ++ unsigned naksts:1; ++ unsigned dpid:1; ++ unsigned usbactep:1; ++ unsigned nextep:4; ++#else ++ ++ /* ++ * Maximum Packet Size ++ * IN/OUT EPn ++ * IN/OUT EP0 - 2 bits ++ * 2'b00: 64 Bytes ++ * 2'b01: 32 ++ * 2'b10: 16 ++ * 2'b11: 8 ++ */ ++ unsigned mps:11; ++ /* ++ * Next Endpoint ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved ++ */ ++ unsigned nextep:4; ++ ++ /* USB Active Endpoint */ ++ unsigned usbactep:1; ++ ++ /* ++ * Endpoint DPID (INTR/Bulk IN and OUT endpoints) ++ * This field contains the PID of the packet going to ++ * be received or transmitted on this endpoint. The ++ * application should program the PID of the first ++ * packet going to be received or transmitted on this ++ * endpoint , after the endpoint is ++ * activated. Application use the SetD1PID and ++ * SetD0PID fields of this register to program either ++ * D0 or D1 PID. ++ * ++ * The encoding for this field is ++ * - 0: D0 ++ * - 1: D1 ++ */ ++ unsigned dpid:1; ++ ++ /* NAK Status */ ++ unsigned naksts:1; ++ ++ /* ++ * Endpoint Type ++ * 2'b00: Control ++ * 2'b01: Isochronous ++ * 2'b10: Bulk ++ * 2'b11: Interrupt ++ */ ++ unsigned eptype:2; ++ ++ /* ++ * Snoop Mode ++ * OUT EPn/OUT EP0 ++ * IN EPn/IN EP0 - reserved ++ */ ++ unsigned snp:1; ++ ++ /* Stall Handshake */ ++ unsigned stall:1; ++ ++ /* ++ * Tx Fifo Number ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved ++ */ ++ unsigned txfnum:4; ++ ++ /* Clear NAK */ ++ unsigned cnak:1; ++ /* Set NAK */ ++ unsigned snak:1; ++ /* ++ * Set DATA0 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA0. Set Even ++ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to even (micro) ++ * frame. ++ */ ++ unsigned setd0pid:1; ++ /* ++ * Set DATA1 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA1 Set Odd ++ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to odd (micro) frame. ++ */ ++ unsigned setd1pid:1; ++ ++ /* Endpoint Disable */ ++ unsigned epdis:1; ++ /* Endpoint Enable */ ++ unsigned epena:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Device EP Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++union deptsiz_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:1; ++ unsigned mc:2; ++ unsigned pktcnt:10; ++ unsigned xfersize:19; ++#else ++ ++ /* Transfer size */ ++ unsigned xfersize:19; ++ /* Packet Count */ ++ unsigned pktcnt:10; ++ /* Multi Count - Periodic IN endpoints */ ++ unsigned mc:2; ++ unsigned reserved:1; ++#endif ++ } b; ++}; ++ ++/* ++ * This union represents the bit fields in the Device EP 0 Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++union deptsiz0_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved31:1; ++ unsigned supcnt:2; ++ unsigned reserved20_28:9; ++ unsigned pktcnt:1; ++ unsigned reserved7_18:12; ++ unsigned xfersize:7; ++#else ++ ++ /* Transfer size */ ++ unsigned xfersize:7; ++ /* Reserved */ ++ unsigned reserved7_18:12; ++ /* Packet Count */ ++ unsigned pktcnt:1; ++ /* Reserved */ ++ unsigned reserved20_28:9; ++ /* Setup Packet Count (DOEPTSIZ0 Only) */ ++ unsigned supcnt:2; ++ unsigned reserved31:1; ++#endif ++ } b; ++}; ++ ++/** Maximum number of Periodic FIFOs */ ++#define MAX_PERIO_FIFOS 15 ++ ++/** Maximum number of Endpoints/HostChannels */ ++#define MAX_EPS_CHANNELS 16 ++ ++/* ++ * The dwc_otg_dev_if structure contains information needed to manage ++ * the DWC_otg controller acting in device mode. It represents the ++ * programming view of the device-specific aspects of the controller. ++ */ ++struct dwc_otg_dev_if { ++ /* ++ * Pointer to device Global registers. ++ * Device Global Registers starting at offset 800h ++ */ ++ struct dwc_otg_dev_global_regs *dev_global_regs; ++#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 ++ ++ /* ++ * Device Logical IN Endpoint-Specific Registers 900h-AFCh ++ */ ++ struct dwc_otg_dev_in_ep_regs *in_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_IN_EP_REG_OFFSET 0x900 ++#define DWC_EP_REG_OFFSET 0x20 ++ ++ /* Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ ++ struct dwc_otg_dev_out_ep_regs *out_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00 ++ ++ /* Device configuration information */ ++ uint8_t speed; /* Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ ++ uint8_t num_eps; /* Number of EPs range: 1-16 (includes EP0) */ ++ uint8_t num_perio_eps; /* # of Periodic EP range: 0-15 */ ++ ++ /* Size of periodic FIFOs (Bytes) */ ++ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++}; ++ ++ ++/* Host Mode Register Structures */ ++ ++/* ++ * The Host Global Registers structure defines the size and relative ++ * field offsets for the Host Mode Global Registers. Host Global ++ * Registers offsets 400h-7FFh. ++ */ ++struct dwc_otg_host_global_regs { ++ /* Host Configuration Register. Offset: 400h */ ++ uint32_t hcfg; ++ /* Host Frame Interval Register. Offset: 404h */ ++ uint32_t hfir; ++ /* Host Frame Number / Frame Remaining Register. Offset: 408h */ ++ uint32_t hfnum; ++ /* Reserved. Offset: 40Ch */ ++ uint32_t reserved40C; ++ /* Host Periodic Transmit FIFO/ Queue Status Register. Offset: 410h */ ++ uint32_t hptxsts; ++ /* Host All Channels Interrupt Register. Offset: 414h */ ++ uint32_t haint; ++ /* Host All Channels Interrupt Mask Register. Offset: 418h */ ++ uint32_t haintmsk; ++}; ++ ++/* ++ * This union represents the bit fields in the Host Configuration Register. ++ * Read the register into the d32 member then set/clear the bits using ++ * the bit elements. Write the d32 member to the hcfg register. ++ */ ++union hcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++#define DWC_HCFG_6_MHZ 2 ++#define DWC_HCFG_48_MHZ 1 ++#define DWC_HCFG_30_60_MHZ 0 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:29; ++ unsigned fslssupp:1; ++ unsigned fslspclksel:2; ++#else ++ ++ /* FS/LS Phy Clock Select */ ++ unsigned fslspclksel:2; ++ /* FS/LS Only Support */ ++ unsigned fslssupp:1; ++ unsigned reserved:29; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++union hfir_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:16; ++ unsigned frint:16; ++#else ++ unsigned frint:16; ++ unsigned reserved:16; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++union hfnum_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /* register bits */ ++ struct { ++#define DWC_HFNUM_MAX_FRNUM 0x3FFF ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned frrem:16; ++ unsigned frnum:16; ++#else ++ unsigned frnum:16; ++ unsigned frrem:16; ++#endif ++ } b; ++}; ++ ++union hptxsts_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned ptxqtop_odd:1; ++ unsigned ptxqtop_chnum:4; ++ unsigned ptxqtop_token:2; ++ unsigned ptxqtop_terminate:1; ++ unsigned ptxqspcavail:8; ++ unsigned ptxfspcavail:16; ++#else ++ unsigned ptxfspcavail:16; ++ unsigned ptxqspcavail:8; ++ /* ++ * Top of the Periodic Transmit Request Queue ++ * - bit 24 - Terminate (last entry for the selected channel) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - Zero length ++ * - 2'b01 - Ping ++ * - 2'b10 - Disable ++ * - bits 30:27 - Channel Number ++ * - bit 31 - Odd/even microframe ++ */ ++ unsigned ptxqtop_terminate:1; ++ unsigned ptxqtop_token:2; ++ unsigned ptxqtop_chnum:4; ++ unsigned ptxqtop_odd:1; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host Port Control and Status ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hprt0 register. ++ */ ++union hprt0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++#define DWC_HPRT0_PRTSPD_LOW_SPEED 2 ++#define DWC_HPRT0_PRTSPD_FULL_SPEED 1 ++#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved19_31:13; ++ unsigned prtspd:2; ++ unsigned prttstctl:4; ++ unsigned prtpwr:1; ++ unsigned prtlnsts:2; ++ unsigned reserved9:1; ++ unsigned prtrst:1; ++ unsigned prtsusp:1; ++ unsigned prtres:1; ++ unsigned prtovrcurrchng:1; ++ unsigned prtovrcurract:1; ++ unsigned prtenchng:1; ++ unsigned prtena:1; ++ unsigned prtconndet:1; ++ unsigned prtconnsts:1; ++#else ++ unsigned prtconnsts:1; ++ unsigned prtconndet:1; ++ unsigned prtena:1; ++ unsigned prtenchng:1; ++ unsigned prtovrcurract:1; ++ unsigned prtovrcurrchng:1; ++ unsigned prtres:1; ++ unsigned prtsusp:1; ++ unsigned prtrst:1; ++ unsigned reserved9:1; ++ unsigned prtlnsts:2; ++ unsigned prtpwr:1; ++ unsigned prttstctl:4; ++ unsigned prtspd:2; ++ unsigned reserved19_31:13; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++union haint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:16; ++ unsigned ch15:1; ++ unsigned ch14:1; ++ unsigned ch13:1; ++ unsigned ch12:1; ++ unsigned ch11:1; ++ unsigned ch10:1; ++ unsigned ch9:1; ++ unsigned ch8:1; ++ unsigned ch7:1; ++ unsigned ch6:1; ++ unsigned ch5:1; ++ unsigned ch4:1; ++ unsigned ch3:1; ++ unsigned ch2:1; ++ unsigned ch1:1; ++ unsigned ch0:1; ++#else ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++#endif ++ } b; ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:16; ++ unsigned chint:16; ++#else ++ unsigned chint:16; ++ unsigned reserved:16; ++#endif ++ } b2; ++}; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++union haintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:16; ++ unsigned ch15:1; ++ unsigned ch14:1; ++ unsigned ch13:1; ++ unsigned ch12:1; ++ unsigned ch11:1; ++ unsigned ch10:1; ++ unsigned ch9:1; ++ unsigned ch8:1; ++ unsigned ch7:1; ++ unsigned ch6:1; ++ unsigned ch5:1; ++ unsigned ch4:1; ++ unsigned ch3:1; ++ unsigned ch2:1; ++ unsigned ch1:1; ++ unsigned ch0:1; ++#else ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++#endif ++ } b; ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:16; ++ unsigned chint:16; ++#else ++ unsigned chint:16; ++ unsigned reserved:16; ++#endif ++ } b2; ++}; ++ ++/* ++ * Host Channel Specific Registers. 500h-5FCh ++ */ ++struct dwc_otg_hc_regs { ++ /* ++ * Host Channel 0 Characteristic Register. ++ * Offset: 500h + (chan_num * 20h) + 00h ++ */ ++ uint32_t hcchar; ++ /* ++ * Host Channel 0 Split Control Register. ++ * Offset: 500h + (chan_num * 20h) + 04h ++ */ ++ uint32_t hcsplt; ++ /* ++ * Host Channel 0 Interrupt Register. ++ * Offset: 500h + (chan_num * 20h) + 08h ++ */ ++ uint32_t hcint; ++ /* ++ * Host Channel 0 Interrupt Mask Register. ++ * Offset: 500h + (chan_num * 20h) + 0Ch ++ */ ++ uint32_t hcintmsk; ++ /* ++ * Host Channel 0 Transfer Size Register. ++ * Offset: 500h + (chan_num * 20h) + 10h ++ */ ++ uint32_t hctsiz; ++ /* ++ * Host Channel 0 DMA Address Register. ++ * Offset: 500h + (chan_num * 20h) + 14h ++ */ ++ uint32_t hcdma; ++ /* ++ * Reserved. ++ * Offset: 500h + (chan_num * 20h) + 18h - ++ * 500h + (chan_num * 20h) + 1Ch ++ */ ++ uint32_t reserved[2]; ++}; ++ ++/** ++ * This union represents the bit fields in the Host Channel Characteristics ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcchar register. ++ */ ++union hcchar_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned chen:1; ++ unsigned chdis:1; ++ unsigned oddfrm:1; ++ unsigned devaddr:7; ++ unsigned multicnt:2; ++ unsigned eptype:2; ++ unsigned lspddev:1; ++ unsigned reserved:1; ++ unsigned epdir:1; ++ unsigned epnum:4; ++ unsigned mps:11; ++#else ++ ++ /* Maximum packet size in bytes */ ++ unsigned mps:11; ++ ++ /* Endpoint number */ ++ unsigned epnum:4; ++ ++ /* 0: OUT, 1: IN */ ++ unsigned epdir:1; ++ ++ unsigned reserved:1; ++ ++ /* 0: Full/high speed device, 1: Low speed device */ ++ unsigned lspddev:1; ++ ++ /* 0: Control, 1: Isoc, 2: Bulk, 3: Intr */ ++ unsigned eptype:2; ++ ++ /* Packets per frame for periodic transfers. 0 is reserved. */ ++ unsigned multicnt:2; ++ ++ /* Device address */ ++ unsigned devaddr:7; ++ ++ /* ++ * Frame to transmit periodic transaction. ++ * 0: even, 1: odd ++ */ ++ unsigned oddfrm:1; ++ ++ /* Channel disable */ ++ unsigned chdis:1; ++ ++ /* Channel enable */ ++ unsigned chen:1; ++#endif ++ } b; ++}; ++ ++union hcsplt_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /* register bits */ ++ struct { ++#define DWC_HCSPLIT_XACTPOS_ALL 3 ++#define DWC_HCSPLIT_XACTPOS_BEGIN 2 ++#define DWC_HCSPLIT_XACTPOS_END 1 ++#define DWC_HCSPLIT_XACTPOS_MID 0 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned spltena:1; ++ unsigned reserved:14; ++ unsigned compsplt:1; ++ unsigned xactpos:2; ++ unsigned hubaddr:7; ++ unsigned prtaddr:7; ++#else ++ ++ /* Port Address */ ++ unsigned prtaddr:7; ++ ++ /* Hub Address */ ++ unsigned hubaddr:7; ++ ++ /* Transaction Position */ ++ unsigned xactpos:2; ++ ++ /* Do Complete Split */ ++ unsigned compsplt:1; ++ ++ /* Reserved */ ++ unsigned reserved:14; ++ ++ /* Split Enble */ ++ unsigned spltena:1; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++union hcint_data { ++ /* raw register data */ ++ uint32_t d32; ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:21; ++ unsigned datatglerr:1; ++ unsigned frmovrun:1; ++ unsigned bblerr:1; ++ unsigned xacterr:1; ++ unsigned nyet:1; ++ unsigned ack:1; ++ unsigned nak:1; ++ unsigned stall:1; ++ unsigned ahberr:1; ++ unsigned chhltd:1; ++ unsigned xfercomp:1; ++#else ++ ++ /* Transfer Complete */ ++ unsigned xfercomp:1; ++ /* Channel Halted */ ++ unsigned chhltd:1; ++ /* AHB Error */ ++ unsigned ahberr:1; ++ /* STALL Response Received */ ++ unsigned stall:1; ++ /* NAK Response Received */ ++ unsigned nak:1; ++ /* ACK Response Received */ ++ unsigned ack:1; ++ /* NYET Response Received */ ++ unsigned nyet:1; ++ /* Transaction Err */ ++ unsigned xacterr:1; ++ /* Babble Error */ ++ unsigned bblerr:1; ++ /* Frame Overrun */ ++ unsigned frmovrun:1; ++ /* Data Toggle Error */ ++ unsigned datatglerr:1; ++ /* Reserved */ ++ unsigned reserved:21; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host Channel Transfer Size ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcchar register. ++ */ ++union hctsiz_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /* register bits */ ++ struct { ++#define DWC_HCTSIZ_SETUP 3 ++#define DWC_HCTSIZ_MDATA 3 ++#define DWC_HCTSIZ_DATA2 1 ++#define DWC_HCTSIZ_DATA1 2 ++#define DWC_HCTSIZ_DATA0 0 ++ ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned dopng:1; ++ unsigned pid:2; ++ unsigned pktcnt:10; ++ unsigned xfersize:19; ++#else ++ ++ /* Total transfer size in bytes */ ++ unsigned xfersize:19; ++ ++ /* Data packets to transfer */ ++ unsigned pktcnt:10; ++ ++ /* ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control), SETUP (Control) ++ */ ++ unsigned pid:2; ++ ++ /* Do PING protocol when 1 */ ++ unsigned dopng:1; ++#endif ++ } b; ++}; ++ ++/** ++ * This union represents the bit fields in the Host Channel Interrupt Mask ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcintmsk register. ++ */ ++union hcintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:21; ++ unsigned datatglerr:1; ++ unsigned frmovrun:1; ++ unsigned bblerr:1; ++ unsigned xacterr:1; ++ unsigned nyet:1; ++ unsigned ack:1; ++ unsigned nak:1; ++ unsigned stall:1; ++ unsigned ahberr:1; ++ unsigned chhltd:1; ++ unsigned xfercompl:1; ++#else ++ unsigned xfercompl:1; ++ unsigned chhltd:1; ++ unsigned ahberr:1; ++ unsigned stall:1; ++ unsigned nak:1; ++ unsigned ack:1; ++ unsigned nyet:1; ++ unsigned xacterr:1; ++ unsigned bblerr:1; ++ unsigned frmovrun:1; ++ unsigned datatglerr:1; ++ unsigned reserved:21; ++#endif ++ } b; ++}; ++ ++/** OTG Host Interface Structure. ++ * ++ * The OTG Host Interface Structure structure contains information ++ * needed to manage the DWC_otg controller acting in host mode. It ++ * represents the programming view of the host-specific aspects of the ++ * controller. ++ */ ++struct dwc_otg_host_if { ++ /* Host Global Registers starting at offset 400h.*/ ++ struct dwc_otg_host_global_regs *host_global_regs; ++#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400 ++ ++ /* Host Port 0 Control and Status Register */ ++ uint32_t *hprt0; ++#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440 ++ ++ /* Host Channel Specific Registers at offsets 500h-5FCh. */ ++ struct dwc_otg_hc_regs *hc_regs[MAX_EPS_CHANNELS]; ++#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500 ++#define DWC_OTG_CHAN_REGS_OFFSET 0x20 ++ ++ /* Host configuration information */ ++ /* Number of Host Channels (range: 1-16) */ ++ uint8_t num_host_channels; ++ /* Periodic EPs supported (0: no, 1: yes) */ ++ uint8_t perio_eps_supported; ++ /* Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */ ++ uint16_t perio_tx_fifo_size; ++ ++}; ++ ++/** ++ * This union represents the bit fields in the Power and Clock Gating Control ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++union pcgcctl_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /* register bits */ ++ struct { ++#ifdef __BIG_ENDIAN_BITFIELD ++ unsigned reserved:27; ++ unsigned physuspended:1; ++ unsigned rstpdwnmodule:1; ++ unsigned pwrclmp:1; ++ unsigned gatehclk:1; ++ unsigned stoppclk:1; ++#else ++ ++ /* Stop Pclk */ ++ unsigned stoppclk:1; ++ /* Gate Hclk */ ++ unsigned gatehclk:1; ++ /* Power Clamp */ ++ unsigned pwrclmp:1; ++ /* Reset Power Down Modules */ ++ unsigned rstpdwnmodule:1; ++ /* PHY Suspended */ ++ unsigned physuspended:1; ++ ++ unsigned reserved:27; ++#endif ++ } b; ++}; ++ ++#endif +-- +1.6.0.6 + diff --git a/target/linux/octeon/patches-2.6.30/100-wndap330_hacks.patch b/target/linux/octeon/patches-2.6.30/100-wndap330_hacks.patch new file mode 100644 index 0000000000..c4ca4217c0 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/100-wndap330_hacks.patch @@ -0,0 +1,77 @@ +--- a/drivers/staging/octeon/cvmx-helper-board.c ++++ b/drivers/staging/octeon/cvmx-helper-board.c +@@ -90,7 +90,7 @@ int cvmx_helper_board_get_mii_address(in + case CVMX_BOARD_TYPE_KODAMA: + case CVMX_BOARD_TYPE_EBH3100: + case CVMX_BOARD_TYPE_HIKARI: +- case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ //case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ + case CVMX_BOARD_TYPE_CN3005_EVB_HS5: + case CVMX_BOARD_TYPE_CN3020_EVB_HS5: + /* +@@ -103,6 +103,12 @@ int cvmx_helper_board_get_mii_address(in + return 9; + else + return -1; ++ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ ++ /* We have only one port, using GMII */ ++ if (ipd_port == 0) ++ return 9; ++ else ++ return -1; + case CVMX_BOARD_TYPE_NAC38: + /* Board has 8 RGMII ports PHYs are 0-7 */ + if ((ipd_port >= 0) && (ipd_port < 4)) +@@ -205,7 +211,7 @@ cvmx_helper_link_info_t __cvmx_helper_bo + result.s.speed = 1000; + return result; + case CVMX_BOARD_TYPE_EBH3100: +- case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ //case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ + case CVMX_BOARD_TYPE_CN3005_EVB_HS5: + case CVMX_BOARD_TYPE_CN3020_EVB_HS5: + /* Port 1 on these boards is always Gigabit */ +@@ -217,6 +223,9 @@ cvmx_helper_link_info_t __cvmx_helper_bo + } + /* Fall through to the generic code below */ + break; ++ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ ++ is_broadcom_phy = 1; ++ break; + case CVMX_BOARD_TYPE_CUST_NB5: + /* Port 1 on these boards is always Gigabit */ + if (ipd_port == 1) { +--- a/drivers/staging/octeon/cvmx-helper-rgmii.c ++++ b/drivers/staging/octeon/cvmx-helper-rgmii.c +@@ -66,13 +66,15 @@ int __cvmx_helper_rgmii_probe(int interf + cvmx_dprintf("ERROR: RGMII initialize called in " + "SPI interface\n"); + } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) +- || OCTEON_IS_MODEL(OCTEON_CN30XX) ++ //|| OCTEON_IS_MODEL(OCTEON_CN30XX) + || OCTEON_IS_MODEL(OCTEON_CN50XX)) { + /* + * On these chips "type" says we're in + * GMII/MII mode. This limits us to 2 ports + */ + num_ports = 2; ++ } else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) { ++ num_ports = 1; + } else { + cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", + __func__); +--- a/arch/mips/cavium-octeon/pci.c ++++ b/arch/mips/cavium-octeon/pci.c +@@ -95,9 +95,11 @@ const char *octeon_get_pci_interrupts(vo + case CVMX_BOARD_TYPE_EBH3000: + return ""; + case CVMX_BOARD_TYPE_EBH3100: +- case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ //case CVMX_BOARD_TYPE_CN3010_EVB_HS5: + case CVMX_BOARD_TYPE_CN3005_EVB_HS5: + return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; ++ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: ++ return "AAAAAAAAAAAAAABAAAAAAAAAAAAAAABA"; + case CVMX_BOARD_TYPE_BBGW_REF: + return "AABCD"; + default: diff --git a/target/linux/octeon/patches-2.6.30/105-nb5_fixup.patch b/target/linux/octeon/patches-2.6.30/105-nb5_fixup.patch new file mode 100644 index 0000000000..2165eb0a1b --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/105-nb5_fixup.patch @@ -0,0 +1,21 @@ +--- a/arch/mips/cavium-octeon/pci.c ++++ b/arch/mips/cavium-octeon/pci.c +@@ -102,6 +102,8 @@ const char *octeon_get_pci_interrupts(vo + return "AAAAAAAAAAAAAABAAAAAAAAAAAAAAABA"; + case CVMX_BOARD_TYPE_BBGW_REF: + return "AABCD"; ++ case CVMX_BOARD_TYPE_CUST_NB5: ++ return "ABDABAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + default: + return ""; + } +--- a/drivers/staging/octeon/cvmx-helper-board.c ++++ b/drivers/staging/octeon/cvmx-helper-board.c +@@ -699,6 +699,7 @@ cvmx_helper_board_usb_clock_types_t __cv + { + switch (cvmx_sysinfo_get()->board_type) { + case CVMX_BOARD_TYPE_BBGW_REF: ++ case CVMX_BOARD_TYPE_CUST_NB5: + return USB_CLOCK_TYPE_CRYSTAL_12; + } + return USB_CLOCK_TYPE_REF_48; diff --git a/target/linux/octeon/patches-2.6.30/106-no_module_reloc.patch b/target/linux/octeon/patches-2.6.30/106-no_module_reloc.patch new file mode 100644 index 0000000000..449bda7567 --- /dev/null +++ b/target/linux/octeon/patches-2.6.30/106-no_module_reloc.patch @@ -0,0 +1,372 @@ +diff -urN linux-2.6.30.10/arch/mips/Makefile linux-2.6.30.10.new//arch/mips/Makefile +--- linux-2.6.30.10/arch/mips/Makefile 2010-01-29 16:12:01.000000000 +0100 ++++ linux-2.6.30.10.new//arch/mips/Makefile 2009-12-04 07:00:07.000000000 +0100 +@@ -83,7 +83,7 @@ + cflags-y += -G 0 -mno-abicalls -fno-pic -pipe + cflags-y += -msoft-float + LDFLAGS_vmlinux += -G 0 -static -n -nostdlib +-MODFLAGS += -mno-long-calls ++MODFLAGS += -mlong-calls + + cflags-y += -ffreestanding + +diff -urN linux-2.6.30.10/arch/mips/include/asm/module.h linux-2.6.30.10.new//arch/mips/include/asm/module.h +--- linux-2.6.30.10/arch/mips/include/asm/module.h 2010-01-29 16:12:01.000000000 +0100 ++++ linux-2.6.30.10.new//arch/mips/include/asm/module.h 2009-12-04 07:00:07.000000000 +0100 +@@ -9,11 +9,6 @@ + struct list_head dbe_list; + const struct exception_table_entry *dbe_start; + const struct exception_table_entry *dbe_end; +- +- void *phys_plt_tbl; +- void *virt_plt_tbl; +- unsigned int phys_plt_offset; +- unsigned int virt_plt_offset; + }; + + typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ +diff -urN linux-2.6.30.10/arch/mips/kernel/module.c linux-2.6.30.10.new//arch/mips/kernel/module.c +--- linux-2.6.30.10/arch/mips/kernel/module.c 2010-01-29 16:12:01.000000000 +0100 ++++ linux-2.6.30.10.new//arch/mips/kernel/module.c 2009-12-04 07:00:07.000000000 +0100 +@@ -43,116 +43,6 @@ + static LIST_HEAD(dbe_list); + static DEFINE_SPINLOCK(dbe_lock); + +-/* +- * Get the potential max trampolines size required of the init and +- * non-init sections. Only used if we cannot find enough contiguous +- * physically mapped memory to put the module into. +- */ +-static unsigned int +-get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, +- const char *secstrings, unsigned int symindex, bool is_init) +-{ +- unsigned long ret = 0; +- unsigned int i, j; +- Elf_Sym *syms; +- +- /* Everything marked ALLOC (this includes the exported symbols) */ +- for (i = 1; i < hdr->e_shnum; ++i) { +- unsigned int info = sechdrs[i].sh_info; +- +- if (sechdrs[i].sh_type != SHT_REL +- && sechdrs[i].sh_type != SHT_RELA) +- continue; +- +- /* Not a valid relocation section? */ +- if (info >= hdr->e_shnum) +- continue; +- +- /* Don't bother with non-allocated sections */ +- if (!(sechdrs[info].sh_flags & SHF_ALLOC)) +- continue; +- +- /* If it's called *.init*, and we're not init, we're +- not interested */ +- if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) +- != is_init) +- continue; +- +- syms = (Elf_Sym *) sechdrs[symindex].sh_addr; +- if (sechdrs[i].sh_type == SHT_REL) { +- Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; +- unsigned int size = sechdrs[i].sh_size / sizeof(*rel); +- +- for (j = 0; j < size; ++j) { +- Elf_Sym *sym; +- +- if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) +- continue; +- +- sym = syms + ELF_MIPS_R_SYM(rel[j]); +- if (!is_init && sym->st_shndx != SHN_UNDEF) +- continue; +- +- ret += 4 * sizeof(int); +- } +- } else { +- Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; +- unsigned int size = sechdrs[i].sh_size / sizeof(*rela); +- +- for (j = 0; j < size; ++j) { +- Elf_Sym *sym; +- +- if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) +- continue; +- +- sym = syms + ELF_MIPS_R_SYM(rela[j]); +- if (!is_init && sym->st_shndx != SHN_UNDEF) +- continue; +- +- ret += 4 * sizeof(int); +- } +- } +- } +- +- return ret; +-} +- +-#ifndef MODULE_START +-static void *alloc_phys(unsigned long size) +-{ +- unsigned order; +- struct page *page; +- struct page *p; +- +- size = PAGE_ALIGN(size); +- order = get_order(size); +- +- page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | +- __GFP_THISNODE, order); +- if (!page) +- return NULL; +- +- split_page(page, order); +- +- for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) +- __free_page(p); +- +- return page_address(page); +-} +-#endif +- +-static void free_phys(void *ptr, unsigned long size) +-{ +- struct page *page; +- struct page *end; +- +- page = virt_to_page(ptr); +- end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT); +- +- for (; page < end; ++page) +- __free_page(page); +-} +- + void *module_alloc(unsigned long size) + { + #ifdef MODULE_START +@@ -168,101 +58,23 @@ + + return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); + #else +- void *ptr; +- + if (size == 0) + return NULL; +- +- ptr = alloc_phys(size); +- +- /* If we failed to allocate physically contiguous memory, +- * fall back to regular vmalloc. The module loader code will +- * create jump tables to handle long jumps */ +- if (!ptr) +- return vmalloc(size); +- +- return ptr; +-#endif +-} +- +-static inline bool is_phys_addr(void *ptr) +-{ +-#ifdef CONFIG_64BIT +- return (KSEGX((unsigned long)ptr) == CKSEG0); +-#else +- return (KSEGX(ptr) == KSEG0); ++ return vmalloc(size); + #endif + } + + /* Free memory returned from module_alloc */ + void module_free(struct module *mod, void *module_region) + { +- if (is_phys_addr(module_region)) { +- if (mod->module_init == module_region) +- free_phys(module_region, mod->init_size); +- else if (mod->module_core == module_region) +- free_phys(module_region, mod->core_size); +- else +- BUG(); +- } else { +- vfree(module_region); +- } ++ vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ + } + +-static void *__module_alloc(int size, bool phys) +-{ +- void *ptr; +- +- if (phys) +- ptr = kmalloc(size, GFP_KERNEL); +- else +- ptr = vmalloc(size); +- return ptr; +-} +- +-static void __module_free(void *ptr) +-{ +- if (is_phys_addr(ptr)) +- kfree(ptr); +- else +- vfree(ptr); +-} +- + int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) + { +- unsigned int symindex = 0; +- unsigned int core_size, init_size; +- int i; +- +- for (i = 1; i < hdr->e_shnum; i++) +- if (sechdrs[i].sh_type == SHT_SYMTAB) +- symindex = i; +- +- core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); +- init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); +- +- mod->arch.phys_plt_offset = 0; +- mod->arch.virt_plt_offset = 0; +- mod->arch.phys_plt_tbl = NULL; +- mod->arch.virt_plt_tbl = NULL; +- +- if ((core_size + init_size) == 0) +- return 0; +- +- mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); +- if (!mod->arch.phys_plt_tbl) +- return -ENOMEM; +- +- mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); +- if (!mod->arch.virt_plt_tbl) { +- __module_free(mod->arch.phys_plt_tbl); +- mod->arch.phys_plt_tbl = NULL; +- return -ENOMEM; +- } +- + return 0; + } + +@@ -285,37 +97,27 @@ + return 0; + } + +-static Elf_Addr add_plt_entry_to(unsigned *plt_offset, +- void *start, Elf_Addr v) ++static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) + { +- unsigned *tramp = start + *plt_offset; +- +- *plt_offset += 4 * sizeof(int); +- +- /* adjust carry for addiu */ +- if (v & 0x00008000) +- v += 0x10000; +- +- tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ +- tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ +- tramp[2] = 0x03200008; /* jr t9 */ +- tramp[3] = 0x00000000; /* nop */ ++ if (v % 4) { ++ printk(KERN_ERR "module %s: dangerous relocation\n", me->name); ++ return -ENOEXEC; ++ } + +- return (Elf_Addr) tramp; +-} ++ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { ++ printk(KERN_ERR ++ "module %s: relocation overflow\n", ++ me->name); ++ return -ENOEXEC; ++ } + +-static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) +-{ +- if (is_phys_addr(location)) +- return add_plt_entry_to(&me->arch.phys_plt_offset, +- me->arch.phys_plt_tbl, v); +- else +- return add_plt_entry_to(&me->arch.virt_plt_offset, +- me->arch.virt_plt_tbl, v); ++ *location = (*location & ~0x03ffffff) | ++ ((*location + (v >> 2)) & 0x03ffffff); + ++ return 0; + } + +-static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) ++static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) + { + if (v % 4) { + printk(KERN_ERR "module %s: dangerous relocation\n", me->name); +@@ -323,31 +125,17 @@ + } + + if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { +- v = add_plt_entry(me, location, v + (ofs << 2)); +- if (!v) { +- printk(KERN_ERR ++ printk(KERN_ERR + "module %s: relocation overflow\n", + me->name); +- return -ENOEXEC; +- } +- ofs = 0; ++ return -ENOEXEC; + } + +- *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff); ++ *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); + + return 0; + } + +-static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) +-{ +- return set_r_mips_26(me, location, *location & 0x03ffffff, v); +-} +- +-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) +-{ +- return set_r_mips_26(me, location, 0, v); +-} +- + static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) + { + struct mips_hi16 *n; +@@ -612,32 +400,11 @@ + list_add(&me->arch.dbe_list, &dbe_list); + spin_unlock_irq(&dbe_lock); + } +- +- /* Get rid of the fixup trampoline if we're running the module +- * from physically mapped address space */ +- if (me->arch.phys_plt_offset == 0) { +- __module_free(me->arch.phys_plt_tbl); +- me->arch.phys_plt_tbl = NULL; +- } +- if (me->arch.virt_plt_offset == 0) { +- __module_free(me->arch.virt_plt_tbl); +- me->arch.virt_plt_tbl = NULL; +- } +- + return 0; + } + + void module_arch_cleanup(struct module *mod) + { +- if (mod->arch.phys_plt_tbl) { +- __module_free(mod->arch.phys_plt_tbl); +- mod->arch.phys_plt_tbl = NULL; +- } +- if (mod->arch.virt_plt_tbl) { +- __module_free(mod->arch.virt_plt_tbl); +- mod->arch.virt_plt_tbl = NULL; +- } +- + spin_lock_irq(&dbe_lock); + list_del(&mod->arch.dbe_list); + spin_unlock_irq(&dbe_lock); diff --git a/target/linux/octeon/patches/001-handle_removal_h_constraint.patch b/target/linux/octeon/patches/001-handle_removal_h_constraint.patch deleted file mode 100644 index ea19508ce7..0000000000 --- a/target/linux/octeon/patches/001-handle_removal_h_constraint.patch +++ /dev/null @@ -1,25 +0,0 @@ -This is an incomplete proof of concept that I applied to be able to -build a 64 bit kernel with GCC-4.4. It doesn't handle the 32 bit case -or the R4000_WAR case. - -Comments welcome. - -Signed-off-by: David Daney ---- - arch/mips/include/asm/compiler.h | 7 +++++++ - 2 files changed, 11 insertions(+), 0 deletions(-) - ---- a/arch/mips/include/asm/compiler.h -+++ b/arch/mips/include/asm/compiler.h -@@ -16,4 +16,11 @@ - #define GCC_REG_ACCUM "accum" - #endif - -+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) -+#define GCC_NO_H_CONSTRAINT -+#ifdef CONFIG_64BIT -+typedef unsigned int uint128_t __attribute__((mode(TI))); -+#endif -+#endif -+ - #endif /* _ASM_COMPILER_H */ diff --git a/target/linux/octeon/patches/002-register_defs_pci.patch b/target/linux/octeon/patches/002-register_defs_pci.patch deleted file mode 100644 index 85a910dd94..0000000000 --- a/target/linux/octeon/patches/002-register_defs_pci.patch +++ /dev/null @@ -1,9383 +0,0 @@ -Here we add the register definitions for the processor blocks used by -the following PCI support patch. - -Signed-off-by: David Daney ---- - arch/mips/include/asm/octeon/cvmx-npei-defs.h | 2560 ++++++++++++++++++++++ - arch/mips/include/asm/octeon/cvmx-npi-defs.h | 1735 +++++++++++++++ - arch/mips/include/asm/octeon/cvmx-pci-defs.h | 1645 ++++++++++++++ - arch/mips/include/asm/octeon/cvmx-pcieep-defs.h | 1365 ++++++++++++ - arch/mips/include/asm/octeon/cvmx-pciercx-defs.h | 1397 ++++++++++++ - arch/mips/include/asm/octeon/cvmx-pescx-defs.h | 410 ++++ - arch/mips/include/asm/octeon/cvmx-pexp-defs.h | 229 ++ - 7 files changed, 9341 insertions(+), 0 deletions(-) - create mode 100644 arch/mips/include/asm/octeon/cvmx-npei-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-npi-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-pci-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-pcieep-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-pciercx-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-pescx-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-pexp-defs.h - ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-npei-defs.h -@@ -0,0 +1,2560 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_NPEI_DEFS_H__ -+#define __CVMX_NPEI_DEFS_H__ -+ -+#define CVMX_NPEI_BAR1_INDEXX(offset) \ -+ (0x0000000000000000ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_BIST_STATUS \ -+ (0x0000000000000580ull) -+#define CVMX_NPEI_BIST_STATUS2 \ -+ (0x0000000000000680ull) -+#define CVMX_NPEI_CTL_PORT0 \ -+ (0x0000000000000250ull) -+#define CVMX_NPEI_CTL_PORT1 \ -+ (0x0000000000000260ull) -+#define CVMX_NPEI_CTL_STATUS \ -+ (0x0000000000000570ull) -+#define CVMX_NPEI_CTL_STATUS2 \ -+ (0x0000000000003C00ull) -+#define CVMX_NPEI_DATA_OUT_CNT \ -+ (0x00000000000005F0ull) -+#define CVMX_NPEI_DBG_DATA \ -+ (0x0000000000000510ull) -+#define CVMX_NPEI_DBG_SELECT \ -+ (0x0000000000000500ull) -+#define CVMX_NPEI_DMA0_INT_LEVEL \ -+ (0x00000000000005C0ull) -+#define CVMX_NPEI_DMA1_INT_LEVEL \ -+ (0x00000000000005D0ull) -+#define CVMX_NPEI_DMAX_COUNTS(offset) \ -+ (0x0000000000000450ull + (((offset) & 7) * 16)) -+#define CVMX_NPEI_DMAX_DBELL(offset) \ -+ (0x00000000000003B0ull + (((offset) & 7) * 16)) -+#define CVMX_NPEI_DMAX_IBUFF_SADDR(offset) \ -+ (0x0000000000000400ull + (((offset) & 7) * 16)) -+#define CVMX_NPEI_DMAX_NADDR(offset) \ -+ (0x00000000000004A0ull + (((offset) & 7) * 16)) -+#define CVMX_NPEI_DMA_CNTS \ -+ (0x00000000000005E0ull) -+#define CVMX_NPEI_DMA_CONTROL \ -+ (0x00000000000003A0ull) -+#define CVMX_NPEI_INT_A_ENB \ -+ (0x0000000000000560ull) -+#define CVMX_NPEI_INT_A_ENB2 \ -+ (0x0000000000003CE0ull) -+#define CVMX_NPEI_INT_A_SUM \ -+ (0x0000000000000550ull) -+#define CVMX_NPEI_INT_ENB \ -+ (0x0000000000000540ull) -+#define CVMX_NPEI_INT_ENB2 \ -+ (0x0000000000003CD0ull) -+#define CVMX_NPEI_INT_INFO \ -+ (0x0000000000000590ull) -+#define CVMX_NPEI_INT_SUM \ -+ (0x0000000000000530ull) -+#define CVMX_NPEI_INT_SUM2 \ -+ (0x0000000000003CC0ull) -+#define CVMX_NPEI_LAST_WIN_RDATA0 \ -+ (0x0000000000000600ull) -+#define CVMX_NPEI_LAST_WIN_RDATA1 \ -+ (0x0000000000000610ull) -+#define CVMX_NPEI_MEM_ACCESS_CTL \ -+ (0x00000000000004F0ull) -+#define CVMX_NPEI_MEM_ACCESS_SUBIDX(offset) \ -+ (0x0000000000000340ull + (((offset) & 31) * 16) - 16 * 12) -+#define CVMX_NPEI_MSI_ENB0 \ -+ (0x0000000000003C50ull) -+#define CVMX_NPEI_MSI_ENB1 \ -+ (0x0000000000003C60ull) -+#define CVMX_NPEI_MSI_ENB2 \ -+ (0x0000000000003C70ull) -+#define CVMX_NPEI_MSI_ENB3 \ -+ (0x0000000000003C80ull) -+#define CVMX_NPEI_MSI_RCV0 \ -+ (0x0000000000003C10ull) -+#define CVMX_NPEI_MSI_RCV1 \ -+ (0x0000000000003C20ull) -+#define CVMX_NPEI_MSI_RCV2 \ -+ (0x0000000000003C30ull) -+#define CVMX_NPEI_MSI_RCV3 \ -+ (0x0000000000003C40ull) -+#define CVMX_NPEI_MSI_RD_MAP \ -+ (0x0000000000003CA0ull) -+#define CVMX_NPEI_MSI_W1C_ENB0 \ -+ (0x0000000000003CF0ull) -+#define CVMX_NPEI_MSI_W1C_ENB1 \ -+ (0x0000000000003D00ull) -+#define CVMX_NPEI_MSI_W1C_ENB2 \ -+ (0x0000000000003D10ull) -+#define CVMX_NPEI_MSI_W1C_ENB3 \ -+ (0x0000000000003D20ull) -+#define CVMX_NPEI_MSI_W1S_ENB0 \ -+ (0x0000000000003D30ull) -+#define CVMX_NPEI_MSI_W1S_ENB1 \ -+ (0x0000000000003D40ull) -+#define CVMX_NPEI_MSI_W1S_ENB2 \ -+ (0x0000000000003D50ull) -+#define CVMX_NPEI_MSI_W1S_ENB3 \ -+ (0x0000000000003D60ull) -+#define CVMX_NPEI_MSI_WR_MAP \ -+ (0x0000000000003C90ull) -+#define CVMX_NPEI_PCIE_CREDIT_CNT \ -+ (0x0000000000003D70ull) -+#define CVMX_NPEI_PCIE_MSI_RCV \ -+ (0x0000000000003CB0ull) -+#define CVMX_NPEI_PCIE_MSI_RCV_B1 \ -+ (0x0000000000000650ull) -+#define CVMX_NPEI_PCIE_MSI_RCV_B2 \ -+ (0x0000000000000660ull) -+#define CVMX_NPEI_PCIE_MSI_RCV_B3 \ -+ (0x0000000000000670ull) -+#define CVMX_NPEI_PKTX_CNTS(offset) \ -+ (0x0000000000002400ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_INSTR_BADDR(offset) \ -+ (0x0000000000002800ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \ -+ (0x0000000000002C00ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \ -+ (0x0000000000003000ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_INSTR_HEADER(offset) \ -+ (0x0000000000003400ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_IN_BP(offset) \ -+ (0x0000000000003800ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_SLIST_BADDR(offset) \ -+ (0x0000000000001400ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \ -+ (0x0000000000001800ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \ -+ (0x0000000000001C00ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKT_CNT_INT \ -+ (0x0000000000001110ull) -+#define CVMX_NPEI_PKT_CNT_INT_ENB \ -+ (0x0000000000001130ull) -+#define CVMX_NPEI_PKT_DATA_OUT_ES \ -+ (0x00000000000010B0ull) -+#define CVMX_NPEI_PKT_DATA_OUT_NS \ -+ (0x00000000000010A0ull) -+#define CVMX_NPEI_PKT_DATA_OUT_ROR \ -+ (0x0000000000001090ull) -+#define CVMX_NPEI_PKT_DPADDR \ -+ (0x0000000000001080ull) -+#define CVMX_NPEI_PKT_INPUT_CONTROL \ -+ (0x0000000000001150ull) -+#define CVMX_NPEI_PKT_INSTR_ENB \ -+ (0x0000000000001000ull) -+#define CVMX_NPEI_PKT_INSTR_RD_SIZE \ -+ (0x0000000000001190ull) -+#define CVMX_NPEI_PKT_INSTR_SIZE \ -+ (0x0000000000001020ull) -+#define CVMX_NPEI_PKT_INT_LEVELS \ -+ (0x0000000000001100ull) -+#define CVMX_NPEI_PKT_IN_BP \ -+ (0x00000000000006B0ull) -+#define CVMX_NPEI_PKT_IN_DONEX_CNTS(offset) \ -+ (0x0000000000002000ull + (((offset) & 31) * 16)) -+#define CVMX_NPEI_PKT_IN_INSTR_COUNTS \ -+ (0x00000000000006A0ull) -+#define CVMX_NPEI_PKT_IN_PCIE_PORT \ -+ (0x00000000000011A0ull) -+#define CVMX_NPEI_PKT_IPTR \ -+ (0x0000000000001070ull) -+#define CVMX_NPEI_PKT_OUTPUT_WMARK \ -+ (0x0000000000001160ull) -+#define CVMX_NPEI_PKT_OUT_BMODE \ -+ (0x00000000000010D0ull) -+#define CVMX_NPEI_PKT_OUT_ENB \ -+ (0x0000000000001010ull) -+#define CVMX_NPEI_PKT_PCIE_PORT \ -+ (0x00000000000010E0ull) -+#define CVMX_NPEI_PKT_PORT_IN_RST \ -+ (0x0000000000000690ull) -+#define CVMX_NPEI_PKT_SLIST_ES \ -+ (0x0000000000001050ull) -+#define CVMX_NPEI_PKT_SLIST_ID_SIZE \ -+ (0x0000000000001180ull) -+#define CVMX_NPEI_PKT_SLIST_NS \ -+ (0x0000000000001040ull) -+#define CVMX_NPEI_PKT_SLIST_ROR \ -+ (0x0000000000001030ull) -+#define CVMX_NPEI_PKT_TIME_INT \ -+ (0x0000000000001120ull) -+#define CVMX_NPEI_PKT_TIME_INT_ENB \ -+ (0x0000000000001140ull) -+#define CVMX_NPEI_RSL_INT_BLOCKS \ -+ (0x0000000000000520ull) -+#define CVMX_NPEI_SCRATCH_1 \ -+ (0x0000000000000270ull) -+#define CVMX_NPEI_STATE1 \ -+ (0x0000000000000620ull) -+#define CVMX_NPEI_STATE2 \ -+ (0x0000000000000630ull) -+#define CVMX_NPEI_STATE3 \ -+ (0x0000000000000640ull) -+#define CVMX_NPEI_WINDOW_CTL \ -+ (0x0000000000000380ull) -+#define CVMX_NPEI_WIN_RD_ADDR \ -+ (0x0000000000000210ull) -+#define CVMX_NPEI_WIN_RD_DATA \ -+ (0x0000000000000240ull) -+#define CVMX_NPEI_WIN_WR_ADDR \ -+ (0x0000000000000200ull) -+#define CVMX_NPEI_WIN_WR_DATA \ -+ (0x0000000000000220ull) -+#define CVMX_NPEI_WIN_WR_MASK \ -+ (0x0000000000000230ull) -+ -+union cvmx_npei_bar1_indexx { -+ uint32_t u32; -+ struct cvmx_npei_bar1_indexx_s { -+ uint32_t reserved_18_31:14; -+ uint32_t addr_idx:14; -+ uint32_t ca:1; -+ uint32_t end_swp:2; -+ uint32_t addr_v:1; -+ } s; -+ struct cvmx_npei_bar1_indexx_s cn52xx; -+ struct cvmx_npei_bar1_indexx_s cn52xxp1; -+ struct cvmx_npei_bar1_indexx_s cn56xx; -+ struct cvmx_npei_bar1_indexx_s cn56xxp1; -+}; -+ -+union cvmx_npei_bist_status { -+ uint64_t u64; -+ struct cvmx_npei_bist_status_s { -+ uint64_t pkt_rdf:1; -+ uint64_t pkt_pmem:1; -+ uint64_t pkt_p1:1; -+ uint64_t reserved_60_60:1; -+ uint64_t pcr_gim:1; -+ uint64_t pkt_pif:1; -+ uint64_t pcsr_int:1; -+ uint64_t pcsr_im:1; -+ uint64_t pcsr_cnt:1; -+ uint64_t pcsr_id:1; -+ uint64_t pcsr_sl:1; -+ uint64_t reserved_50_52:3; -+ uint64_t pkt_ind:1; -+ uint64_t pkt_slm:1; -+ uint64_t reserved_36_47:12; -+ uint64_t d0_pst:1; -+ uint64_t d1_pst:1; -+ uint64_t d2_pst:1; -+ uint64_t d3_pst:1; -+ uint64_t reserved_31_31:1; -+ uint64_t n2p0_c:1; -+ uint64_t n2p0_o:1; -+ uint64_t n2p1_c:1; -+ uint64_t n2p1_o:1; -+ uint64_t cpl_p0:1; -+ uint64_t cpl_p1:1; -+ uint64_t p2n1_po:1; -+ uint64_t p2n1_no:1; -+ uint64_t p2n1_co:1; -+ uint64_t p2n0_po:1; -+ uint64_t p2n0_no:1; -+ uint64_t p2n0_co:1; -+ uint64_t p2n0_c0:1; -+ uint64_t p2n0_c1:1; -+ uint64_t p2n0_n:1; -+ uint64_t p2n0_p0:1; -+ uint64_t p2n0_p1:1; -+ uint64_t p2n1_c0:1; -+ uint64_t p2n1_c1:1; -+ uint64_t p2n1_n:1; -+ uint64_t p2n1_p0:1; -+ uint64_t p2n1_p1:1; -+ uint64_t csm0:1; -+ uint64_t csm1:1; -+ uint64_t dif0:1; -+ uint64_t dif1:1; -+ uint64_t dif2:1; -+ uint64_t dif3:1; -+ uint64_t reserved_2_2:1; -+ uint64_t msi:1; -+ uint64_t ncb_cmd:1; -+ } s; -+ struct cvmx_npei_bist_status_cn52xx { -+ uint64_t pkt_rdf:1; -+ uint64_t pkt_pmem:1; -+ uint64_t pkt_p1:1; -+ uint64_t reserved_60_60:1; -+ uint64_t pcr_gim:1; -+ uint64_t pkt_pif:1; -+ uint64_t pcsr_int:1; -+ uint64_t pcsr_im:1; -+ uint64_t pcsr_cnt:1; -+ uint64_t pcsr_id:1; -+ uint64_t pcsr_sl:1; -+ uint64_t pkt_imem:1; -+ uint64_t pkt_pfm:1; -+ uint64_t pkt_pof:1; -+ uint64_t reserved_48_49:2; -+ uint64_t pkt_pop0:1; -+ uint64_t pkt_pop1:1; -+ uint64_t d0_mem:1; -+ uint64_t d1_mem:1; -+ uint64_t d2_mem:1; -+ uint64_t d3_mem:1; -+ uint64_t d4_mem:1; -+ uint64_t ds_mem:1; -+ uint64_t reserved_36_39:4; -+ uint64_t d0_pst:1; -+ uint64_t d1_pst:1; -+ uint64_t d2_pst:1; -+ uint64_t d3_pst:1; -+ uint64_t d4_pst:1; -+ uint64_t n2p0_c:1; -+ uint64_t n2p0_o:1; -+ uint64_t n2p1_c:1; -+ uint64_t n2p1_o:1; -+ uint64_t cpl_p0:1; -+ uint64_t cpl_p1:1; -+ uint64_t p2n1_po:1; -+ uint64_t p2n1_no:1; -+ uint64_t p2n1_co:1; -+ uint64_t p2n0_po:1; -+ uint64_t p2n0_no:1; -+ uint64_t p2n0_co:1; -+ uint64_t p2n0_c0:1; -+ uint64_t p2n0_c1:1; -+ uint64_t p2n0_n:1; -+ uint64_t p2n0_p0:1; -+ uint64_t p2n0_p1:1; -+ uint64_t p2n1_c0:1; -+ uint64_t p2n1_c1:1; -+ uint64_t p2n1_n:1; -+ uint64_t p2n1_p0:1; -+ uint64_t p2n1_p1:1; -+ uint64_t csm0:1; -+ uint64_t csm1:1; -+ uint64_t dif0:1; -+ uint64_t dif1:1; -+ uint64_t dif2:1; -+ uint64_t dif3:1; -+ uint64_t dif4:1; -+ uint64_t msi:1; -+ uint64_t ncb_cmd:1; -+ } cn52xx; -+ struct cvmx_npei_bist_status_cn52xxp1 { -+ uint64_t reserved_46_63:18; -+ uint64_t d0_mem0:1; -+ uint64_t d1_mem1:1; -+ uint64_t d2_mem2:1; -+ uint64_t d3_mem3:1; -+ uint64_t dr0_mem:1; -+ uint64_t d0_mem:1; -+ uint64_t d1_mem:1; -+ uint64_t d2_mem:1; -+ uint64_t d3_mem:1; -+ uint64_t dr1_mem:1; -+ uint64_t d0_pst:1; -+ uint64_t d1_pst:1; -+ uint64_t d2_pst:1; -+ uint64_t d3_pst:1; -+ uint64_t dr2_mem:1; -+ uint64_t n2p0_c:1; -+ uint64_t n2p0_o:1; -+ uint64_t n2p1_c:1; -+ uint64_t n2p1_o:1; -+ uint64_t cpl_p0:1; -+ uint64_t cpl_p1:1; -+ uint64_t p2n1_po:1; -+ uint64_t p2n1_no:1; -+ uint64_t p2n1_co:1; -+ uint64_t p2n0_po:1; -+ uint64_t p2n0_no:1; -+ uint64_t p2n0_co:1; -+ uint64_t p2n0_c0:1; -+ uint64_t p2n0_c1:1; -+ uint64_t p2n0_n:1; -+ uint64_t p2n0_p0:1; -+ uint64_t p2n0_p1:1; -+ uint64_t p2n1_c0:1; -+ uint64_t p2n1_c1:1; -+ uint64_t p2n1_n:1; -+ uint64_t p2n1_p0:1; -+ uint64_t p2n1_p1:1; -+ uint64_t csm0:1; -+ uint64_t csm1:1; -+ uint64_t dif0:1; -+ uint64_t dif1:1; -+ uint64_t dif2:1; -+ uint64_t dif3:1; -+ uint64_t dr3_mem:1; -+ uint64_t msi:1; -+ uint64_t ncb_cmd:1; -+ } cn52xxp1; -+ struct cvmx_npei_bist_status_cn56xx { -+ uint64_t pkt_rdf:1; -+ uint64_t reserved_60_62:3; -+ uint64_t pcr_gim:1; -+ uint64_t pkt_pif:1; -+ uint64_t pcsr_int:1; -+ uint64_t pcsr_im:1; -+ uint64_t pcsr_cnt:1; -+ uint64_t pcsr_id:1; -+ uint64_t pcsr_sl:1; -+ uint64_t pkt_imem:1; -+ uint64_t pkt_pfm:1; -+ uint64_t pkt_pof:1; -+ uint64_t reserved_48_49:2; -+ uint64_t pkt_pop0:1; -+ uint64_t pkt_pop1:1; -+ uint64_t d0_mem:1; -+ uint64_t d1_mem:1; -+ uint64_t d2_mem:1; -+ uint64_t d3_mem:1; -+ uint64_t d4_mem:1; -+ uint64_t ds_mem:1; -+ uint64_t reserved_36_39:4; -+ uint64_t d0_pst:1; -+ uint64_t d1_pst:1; -+ uint64_t d2_pst:1; -+ uint64_t d3_pst:1; -+ uint64_t d4_pst:1; -+ uint64_t n2p0_c:1; -+ uint64_t n2p0_o:1; -+ uint64_t n2p1_c:1; -+ uint64_t n2p1_o:1; -+ uint64_t cpl_p0:1; -+ uint64_t cpl_p1:1; -+ uint64_t p2n1_po:1; -+ uint64_t p2n1_no:1; -+ uint64_t p2n1_co:1; -+ uint64_t p2n0_po:1; -+ uint64_t p2n0_no:1; -+ uint64_t p2n0_co:1; -+ uint64_t p2n0_c0:1; -+ uint64_t p2n0_c1:1; -+ uint64_t p2n0_n:1; -+ uint64_t p2n0_p0:1; -+ uint64_t p2n0_p1:1; -+ uint64_t p2n1_c0:1; -+ uint64_t p2n1_c1:1; -+ uint64_t p2n1_n:1; -+ uint64_t p2n1_p0:1; -+ uint64_t p2n1_p1:1; -+ uint64_t csm0:1; -+ uint64_t csm1:1; -+ uint64_t dif0:1; -+ uint64_t dif1:1; -+ uint64_t dif2:1; -+ uint64_t dif3:1; -+ uint64_t dif4:1; -+ uint64_t msi:1; -+ uint64_t ncb_cmd:1; -+ } cn56xx; -+ struct cvmx_npei_bist_status_cn56xxp1 { -+ uint64_t reserved_58_63:6; -+ uint64_t pcsr_int:1; -+ uint64_t pcsr_im:1; -+ uint64_t pcsr_cnt:1; -+ uint64_t pcsr_id:1; -+ uint64_t pcsr_sl:1; -+ uint64_t pkt_pout:1; -+ uint64_t pkt_imem:1; -+ uint64_t pkt_cntm:1; -+ uint64_t pkt_ind:1; -+ uint64_t pkt_slm:1; -+ uint64_t pkt_odf:1; -+ uint64_t pkt_oif:1; -+ uint64_t pkt_out:1; -+ uint64_t pkt_i0:1; -+ uint64_t pkt_i1:1; -+ uint64_t pkt_s0:1; -+ uint64_t pkt_s1:1; -+ uint64_t d0_mem:1; -+ uint64_t d1_mem:1; -+ uint64_t d2_mem:1; -+ uint64_t d3_mem:1; -+ uint64_t d4_mem:1; -+ uint64_t d0_pst:1; -+ uint64_t d1_pst:1; -+ uint64_t d2_pst:1; -+ uint64_t d3_pst:1; -+ uint64_t d4_pst:1; -+ uint64_t n2p0_c:1; -+ uint64_t n2p0_o:1; -+ uint64_t n2p1_c:1; -+ uint64_t n2p1_o:1; -+ uint64_t cpl_p0:1; -+ uint64_t cpl_p1:1; -+ uint64_t p2n1_po:1; -+ uint64_t p2n1_no:1; -+ uint64_t p2n1_co:1; -+ uint64_t p2n0_po:1; -+ uint64_t p2n0_no:1; -+ uint64_t p2n0_co:1; -+ uint64_t p2n0_c0:1; -+ uint64_t p2n0_c1:1; -+ uint64_t p2n0_n:1; -+ uint64_t p2n0_p0:1; -+ uint64_t p2n0_p1:1; -+ uint64_t p2n1_c0:1; -+ uint64_t p2n1_c1:1; -+ uint64_t p2n1_n:1; -+ uint64_t p2n1_p0:1; -+ uint64_t p2n1_p1:1; -+ uint64_t csm0:1; -+ uint64_t csm1:1; -+ uint64_t dif0:1; -+ uint64_t dif1:1; -+ uint64_t dif2:1; -+ uint64_t dif3:1; -+ uint64_t dif4:1; -+ uint64_t msi:1; -+ uint64_t ncb_cmd:1; -+ } cn56xxp1; -+}; -+ -+union cvmx_npei_bist_status2 { -+ uint64_t u64; -+ struct cvmx_npei_bist_status2_s { -+ uint64_t reserved_5_63:59; -+ uint64_t psc_p0:1; -+ uint64_t psc_p1:1; -+ uint64_t pkt_gd:1; -+ uint64_t pkt_gl:1; -+ uint64_t pkt_blk:1; -+ } s; -+ struct cvmx_npei_bist_status2_s cn52xx; -+ struct cvmx_npei_bist_status2_s cn56xx; -+}; -+ -+union cvmx_npei_ctl_port0 { -+ uint64_t u64; -+ struct cvmx_npei_ctl_port0_s { -+ uint64_t reserved_21_63:43; -+ uint64_t waitl_com:1; -+ uint64_t intd:1; -+ uint64_t intc:1; -+ uint64_t intb:1; -+ uint64_t inta:1; -+ uint64_t intd_map:2; -+ uint64_t intc_map:2; -+ uint64_t intb_map:2; -+ uint64_t inta_map:2; -+ uint64_t ctlp_ro:1; -+ uint64_t reserved_6_6:1; -+ uint64_t ptlp_ro:1; -+ uint64_t bar2_enb:1; -+ uint64_t bar2_esx:2; -+ uint64_t bar2_cax:1; -+ uint64_t wait_com:1; -+ } s; -+ struct cvmx_npei_ctl_port0_s cn52xx; -+ struct cvmx_npei_ctl_port0_s cn52xxp1; -+ struct cvmx_npei_ctl_port0_s cn56xx; -+ struct cvmx_npei_ctl_port0_s cn56xxp1; -+}; -+ -+union cvmx_npei_ctl_port1 { -+ uint64_t u64; -+ struct cvmx_npei_ctl_port1_s { -+ uint64_t reserved_21_63:43; -+ uint64_t waitl_com:1; -+ uint64_t intd:1; -+ uint64_t intc:1; -+ uint64_t intb:1; -+ uint64_t inta:1; -+ uint64_t intd_map:2; -+ uint64_t intc_map:2; -+ uint64_t intb_map:2; -+ uint64_t inta_map:2; -+ uint64_t ctlp_ro:1; -+ uint64_t reserved_6_6:1; -+ uint64_t ptlp_ro:1; -+ uint64_t bar2_enb:1; -+ uint64_t bar2_esx:2; -+ uint64_t bar2_cax:1; -+ uint64_t wait_com:1; -+ } s; -+ struct cvmx_npei_ctl_port1_s cn52xx; -+ struct cvmx_npei_ctl_port1_s cn52xxp1; -+ struct cvmx_npei_ctl_port1_s cn56xx; -+ struct cvmx_npei_ctl_port1_s cn56xxp1; -+}; -+ -+union cvmx_npei_ctl_status { -+ uint64_t u64; -+ struct cvmx_npei_ctl_status_s { -+ uint64_t reserved_44_63:20; -+ uint64_t p1_ntags:6; -+ uint64_t p0_ntags:6; -+ uint64_t cfg_rtry:16; -+ uint64_t ring_en:1; -+ uint64_t lnk_rst:1; -+ uint64_t arb:1; -+ uint64_t pkt_bp:4; -+ uint64_t host_mode:1; -+ uint64_t chip_rev:8; -+ } s; -+ struct cvmx_npei_ctl_status_s cn52xx; -+ struct cvmx_npei_ctl_status_cn52xxp1 { -+ uint64_t reserved_44_63:20; -+ uint64_t p1_ntags:6; -+ uint64_t p0_ntags:6; -+ uint64_t cfg_rtry:16; -+ uint64_t reserved_15_15:1; -+ uint64_t lnk_rst:1; -+ uint64_t arb:1; -+ uint64_t reserved_9_12:4; -+ uint64_t host_mode:1; -+ uint64_t chip_rev:8; -+ } cn52xxp1; -+ struct cvmx_npei_ctl_status_s cn56xx; -+ struct cvmx_npei_ctl_status_cn56xxp1 { -+ uint64_t reserved_16_63:48; -+ uint64_t ring_en:1; -+ uint64_t lnk_rst:1; -+ uint64_t arb:1; -+ uint64_t pkt_bp:4; -+ uint64_t host_mode:1; -+ uint64_t chip_rev:8; -+ } cn56xxp1; -+}; -+ -+union cvmx_npei_ctl_status2 { -+ uint64_t u64; -+ struct cvmx_npei_ctl_status2_s { -+ uint64_t reserved_16_63:48; -+ uint64_t mps:1; -+ uint64_t mrrs:3; -+ uint64_t c1_w_flt:1; -+ uint64_t c0_w_flt:1; -+ uint64_t c1_b1_s:3; -+ uint64_t c0_b1_s:3; -+ uint64_t c1_wi_d:1; -+ uint64_t c1_b0_d:1; -+ uint64_t c0_wi_d:1; -+ uint64_t c0_b0_d:1; -+ } s; -+ struct cvmx_npei_ctl_status2_s cn52xx; -+ struct cvmx_npei_ctl_status2_s cn52xxp1; -+ struct cvmx_npei_ctl_status2_s cn56xx; -+ struct cvmx_npei_ctl_status2_s cn56xxp1; -+}; -+ -+union cvmx_npei_data_out_cnt { -+ uint64_t u64; -+ struct cvmx_npei_data_out_cnt_s { -+ uint64_t reserved_44_63:20; -+ uint64_t p1_ucnt:16; -+ uint64_t p1_fcnt:6; -+ uint64_t p0_ucnt:16; -+ uint64_t p0_fcnt:6; -+ } s; -+ struct cvmx_npei_data_out_cnt_s cn52xx; -+ struct cvmx_npei_data_out_cnt_s cn52xxp1; -+ struct cvmx_npei_data_out_cnt_s cn56xx; -+ struct cvmx_npei_data_out_cnt_s cn56xxp1; -+}; -+ -+union cvmx_npei_dbg_data { -+ uint64_t u64; -+ struct cvmx_npei_dbg_data_s { -+ uint64_t reserved_28_63:36; -+ uint64_t qlm0_rev_lanes:1; -+ uint64_t reserved_25_26:2; -+ uint64_t qlm1_spd:2; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } s; -+ struct cvmx_npei_dbg_data_cn52xx { -+ uint64_t reserved_29_63:35; -+ uint64_t qlm0_link_width:1; -+ uint64_t qlm0_rev_lanes:1; -+ uint64_t qlm1_mode:2; -+ uint64_t qlm1_spd:2; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } cn52xx; -+ struct cvmx_npei_dbg_data_cn52xx cn52xxp1; -+ struct cvmx_npei_dbg_data_cn56xx { -+ uint64_t reserved_29_63:35; -+ uint64_t qlm2_rev_lanes:1; -+ uint64_t qlm0_rev_lanes:1; -+ uint64_t qlm3_spd:2; -+ uint64_t qlm1_spd:2; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } cn56xx; -+ struct cvmx_npei_dbg_data_cn56xx cn56xxp1; -+}; -+ -+union cvmx_npei_dbg_select { -+ uint64_t u64; -+ struct cvmx_npei_dbg_select_s { -+ uint64_t reserved_16_63:48; -+ uint64_t dbg_sel:16; -+ } s; -+ struct cvmx_npei_dbg_select_s cn52xx; -+ struct cvmx_npei_dbg_select_s cn52xxp1; -+ struct cvmx_npei_dbg_select_s cn56xx; -+ struct cvmx_npei_dbg_select_s cn56xxp1; -+}; -+ -+union cvmx_npei_dmax_counts { -+ uint64_t u64; -+ struct cvmx_npei_dmax_counts_s { -+ uint64_t reserved_39_63:25; -+ uint64_t fcnt:7; -+ uint64_t dbell:32; -+ } s; -+ struct cvmx_npei_dmax_counts_s cn52xx; -+ struct cvmx_npei_dmax_counts_s cn52xxp1; -+ struct cvmx_npei_dmax_counts_s cn56xx; -+ struct cvmx_npei_dmax_counts_s cn56xxp1; -+}; -+ -+union cvmx_npei_dmax_dbell { -+ uint32_t u32; -+ struct cvmx_npei_dmax_dbell_s { -+ uint32_t reserved_16_31:16; -+ uint32_t dbell:16; -+ } s; -+ struct cvmx_npei_dmax_dbell_s cn52xx; -+ struct cvmx_npei_dmax_dbell_s cn52xxp1; -+ struct cvmx_npei_dmax_dbell_s cn56xx; -+ struct cvmx_npei_dmax_dbell_s cn56xxp1; -+}; -+ -+union cvmx_npei_dmax_ibuff_saddr { -+ uint64_t u64; -+ struct cvmx_npei_dmax_ibuff_saddr_s { -+ uint64_t reserved_37_63:27; -+ uint64_t idle:1; -+ uint64_t saddr:29; -+ uint64_t reserved_0_6:7; -+ } s; -+ struct cvmx_npei_dmax_ibuff_saddr_cn52xx { -+ uint64_t reserved_36_63:28; -+ uint64_t saddr:29; -+ uint64_t reserved_0_6:7; -+ } cn52xx; -+ struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn52xxp1; -+ struct cvmx_npei_dmax_ibuff_saddr_s cn56xx; -+ struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn56xxp1; -+}; -+ -+union cvmx_npei_dmax_naddr { -+ uint64_t u64; -+ struct cvmx_npei_dmax_naddr_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_npei_dmax_naddr_s cn52xx; -+ struct cvmx_npei_dmax_naddr_s cn52xxp1; -+ struct cvmx_npei_dmax_naddr_s cn56xx; -+ struct cvmx_npei_dmax_naddr_s cn56xxp1; -+}; -+ -+union cvmx_npei_dma0_int_level { -+ uint64_t u64; -+ struct cvmx_npei_dma0_int_level_s { -+ uint64_t time:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_npei_dma0_int_level_s cn52xx; -+ struct cvmx_npei_dma0_int_level_s cn52xxp1; -+ struct cvmx_npei_dma0_int_level_s cn56xx; -+ struct cvmx_npei_dma0_int_level_s cn56xxp1; -+}; -+ -+union cvmx_npei_dma1_int_level { -+ uint64_t u64; -+ struct cvmx_npei_dma1_int_level_s { -+ uint64_t time:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_npei_dma1_int_level_s cn52xx; -+ struct cvmx_npei_dma1_int_level_s cn52xxp1; -+ struct cvmx_npei_dma1_int_level_s cn56xx; -+ struct cvmx_npei_dma1_int_level_s cn56xxp1; -+}; -+ -+union cvmx_npei_dma_cnts { -+ uint64_t u64; -+ struct cvmx_npei_dma_cnts_s { -+ uint64_t dma1:32; -+ uint64_t dma0:32; -+ } s; -+ struct cvmx_npei_dma_cnts_s cn52xx; -+ struct cvmx_npei_dma_cnts_s cn52xxp1; -+ struct cvmx_npei_dma_cnts_s cn56xx; -+ struct cvmx_npei_dma_cnts_s cn56xxp1; -+}; -+ -+union cvmx_npei_dma_control { -+ uint64_t u64; -+ struct cvmx_npei_dma_control_s { -+ uint64_t reserved_39_63:25; -+ uint64_t dma4_enb:1; -+ uint64_t dma3_enb:1; -+ uint64_t dma2_enb:1; -+ uint64_t dma1_enb:1; -+ uint64_t dma0_enb:1; -+ uint64_t b0_lend:1; -+ uint64_t dwb_denb:1; -+ uint64_t dwb_ichk:9; -+ uint64_t fpa_que:3; -+ uint64_t o_add1:1; -+ uint64_t o_ro:1; -+ uint64_t o_ns:1; -+ uint64_t o_es:2; -+ uint64_t o_mode:1; -+ uint64_t csize:14; -+ } s; -+ struct cvmx_npei_dma_control_s cn52xx; -+ struct cvmx_npei_dma_control_cn52xxp1 { -+ uint64_t reserved_38_63:26; -+ uint64_t dma3_enb:1; -+ uint64_t dma2_enb:1; -+ uint64_t dma1_enb:1; -+ uint64_t dma0_enb:1; -+ uint64_t b0_lend:1; -+ uint64_t dwb_denb:1; -+ uint64_t dwb_ichk:9; -+ uint64_t fpa_que:3; -+ uint64_t o_add1:1; -+ uint64_t o_ro:1; -+ uint64_t o_ns:1; -+ uint64_t o_es:2; -+ uint64_t o_mode:1; -+ uint64_t csize:14; -+ } cn52xxp1; -+ struct cvmx_npei_dma_control_s cn56xx; -+ struct cvmx_npei_dma_control_s cn56xxp1; -+}; -+ -+union cvmx_npei_int_a_enb { -+ uint64_t u64; -+ struct cvmx_npei_int_a_enb_s { -+ uint64_t reserved_10_63:54; -+ uint64_t pout_err:1; -+ uint64_t pin_bp:1; -+ uint64_t p1_rdlk:1; -+ uint64_t p0_rdlk:1; -+ uint64_t pgl_err:1; -+ uint64_t pdi_err:1; -+ uint64_t pop_err:1; -+ uint64_t pins_err:1; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } s; -+ struct cvmx_npei_int_a_enb_cn52xx { -+ uint64_t reserved_8_63:56; -+ uint64_t p1_rdlk:1; -+ uint64_t p0_rdlk:1; -+ uint64_t pgl_err:1; -+ uint64_t pdi_err:1; -+ uint64_t pop_err:1; -+ uint64_t pins_err:1; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } cn52xx; -+ struct cvmx_npei_int_a_enb_cn52xxp1 { -+ uint64_t reserved_2_63:62; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } cn52xxp1; -+ struct cvmx_npei_int_a_enb_s cn56xx; -+}; -+ -+union cvmx_npei_int_a_enb2 { -+ uint64_t u64; -+ struct cvmx_npei_int_a_enb2_s { -+ uint64_t reserved_10_63:54; -+ uint64_t pout_err:1; -+ uint64_t pin_bp:1; -+ uint64_t p1_rdlk:1; -+ uint64_t p0_rdlk:1; -+ uint64_t pgl_err:1; -+ uint64_t pdi_err:1; -+ uint64_t pop_err:1; -+ uint64_t pins_err:1; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } s; -+ struct cvmx_npei_int_a_enb2_cn52xx { -+ uint64_t reserved_8_63:56; -+ uint64_t p1_rdlk:1; -+ uint64_t p0_rdlk:1; -+ uint64_t pgl_err:1; -+ uint64_t pdi_err:1; -+ uint64_t pop_err:1; -+ uint64_t pins_err:1; -+ uint64_t reserved_0_1:2; -+ } cn52xx; -+ struct cvmx_npei_int_a_enb2_cn52xxp1 { -+ uint64_t reserved_2_63:62; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } cn52xxp1; -+ struct cvmx_npei_int_a_enb2_s cn56xx; -+}; -+ -+union cvmx_npei_int_a_sum { -+ uint64_t u64; -+ struct cvmx_npei_int_a_sum_s { -+ uint64_t reserved_10_63:54; -+ uint64_t pout_err:1; -+ uint64_t pin_bp:1; -+ uint64_t p1_rdlk:1; -+ uint64_t p0_rdlk:1; -+ uint64_t pgl_err:1; -+ uint64_t pdi_err:1; -+ uint64_t pop_err:1; -+ uint64_t pins_err:1; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } s; -+ struct cvmx_npei_int_a_sum_cn52xx { -+ uint64_t reserved_8_63:56; -+ uint64_t p1_rdlk:1; -+ uint64_t p0_rdlk:1; -+ uint64_t pgl_err:1; -+ uint64_t pdi_err:1; -+ uint64_t pop_err:1; -+ uint64_t pins_err:1; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } cn52xx; -+ struct cvmx_npei_int_a_sum_cn52xxp1 { -+ uint64_t reserved_2_63:62; -+ uint64_t dma1_cpl:1; -+ uint64_t dma0_cpl:1; -+ } cn52xxp1; -+ struct cvmx_npei_int_a_sum_s cn56xx; -+}; -+ -+union cvmx_npei_int_enb { -+ uint64_t u64; -+ struct cvmx_npei_int_enb_s { -+ uint64_t mio_inta:1; -+ uint64_t reserved_62_62:1; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t dma4dbo:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } s; -+ struct cvmx_npei_int_enb_s cn52xx; -+ struct cvmx_npei_int_enb_cn52xxp1 { -+ uint64_t mio_inta:1; -+ uint64_t reserved_62_62:1; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t reserved_8_8:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn52xxp1; -+ struct cvmx_npei_int_enb_s cn56xx; -+ struct cvmx_npei_int_enb_cn56xxp1 { -+ uint64_t mio_inta:1; -+ uint64_t reserved_61_62:2; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t reserved_29_29:1; -+ uint64_t c1_se:1; -+ uint64_t reserved_27_27:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t reserved_22_22:1; -+ uint64_t c0_se:1; -+ uint64_t reserved_20_20:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t dma4dbo:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn56xxp1; -+}; -+ -+union cvmx_npei_int_enb2 { -+ uint64_t u64; -+ struct cvmx_npei_int_enb2_s { -+ uint64_t reserved_62_63:2; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t dma4dbo:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } s; -+ struct cvmx_npei_int_enb2_s cn52xx; -+ struct cvmx_npei_int_enb2_cn52xxp1 { -+ uint64_t reserved_62_63:2; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t reserved_8_8:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn52xxp1; -+ struct cvmx_npei_int_enb2_s cn56xx; -+ struct cvmx_npei_int_enb2_cn56xxp1 { -+ uint64_t reserved_61_63:3; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t reserved_29_29:1; -+ uint64_t c1_se:1; -+ uint64_t reserved_27_27:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t reserved_22_22:1; -+ uint64_t c0_se:1; -+ uint64_t reserved_20_20:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t dma4dbo:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn56xxp1; -+}; -+ -+union cvmx_npei_int_info { -+ uint64_t u64; -+ struct cvmx_npei_int_info_s { -+ uint64_t reserved_12_63:52; -+ uint64_t pidbof:6; -+ uint64_t psldbof:6; -+ } s; -+ struct cvmx_npei_int_info_s cn52xx; -+ struct cvmx_npei_int_info_s cn56xx; -+ struct cvmx_npei_int_info_s cn56xxp1; -+}; -+ -+union cvmx_npei_int_sum { -+ uint64_t u64; -+ struct cvmx_npei_int_sum_s { -+ uint64_t mio_inta:1; -+ uint64_t reserved_62_62:1; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t dma4dbo:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } s; -+ struct cvmx_npei_int_sum_s cn52xx; -+ struct cvmx_npei_int_sum_cn52xxp1 { -+ uint64_t mio_inta:1; -+ uint64_t reserved_62_62:1; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t reserved_15_18:4; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t reserved_8_8:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn52xxp1; -+ struct cvmx_npei_int_sum_s cn56xx; -+ struct cvmx_npei_int_sum_cn56xxp1 { -+ uint64_t mio_inta:1; -+ uint64_t reserved_61_62:2; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t reserved_29_29:1; -+ uint64_t c1_se:1; -+ uint64_t reserved_27_27:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t reserved_22_22:1; -+ uint64_t c0_se:1; -+ uint64_t reserved_20_20:1; -+ uint64_t c0_aeri:1; -+ uint64_t ptime:1; -+ uint64_t pcnt:1; -+ uint64_t pidbof:1; -+ uint64_t psldbof:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t dma4dbo:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn56xxp1; -+}; -+ -+union cvmx_npei_int_sum2 { -+ uint64_t u64; -+ struct cvmx_npei_int_sum2_s { -+ uint64_t mio_inta:1; -+ uint64_t reserved_62_62:1; -+ uint64_t int_a:1; -+ uint64_t c1_ldwn:1; -+ uint64_t c0_ldwn:1; -+ uint64_t c1_exc:1; -+ uint64_t c0_exc:1; -+ uint64_t c1_up_wf:1; -+ uint64_t c0_up_wf:1; -+ uint64_t c1_un_wf:1; -+ uint64_t c0_un_wf:1; -+ uint64_t c1_un_bx:1; -+ uint64_t c1_un_wi:1; -+ uint64_t c1_un_b2:1; -+ uint64_t c1_un_b1:1; -+ uint64_t c1_un_b0:1; -+ uint64_t c1_up_bx:1; -+ uint64_t c1_up_wi:1; -+ uint64_t c1_up_b2:1; -+ uint64_t c1_up_b1:1; -+ uint64_t c1_up_b0:1; -+ uint64_t c0_un_bx:1; -+ uint64_t c0_un_wi:1; -+ uint64_t c0_un_b2:1; -+ uint64_t c0_un_b1:1; -+ uint64_t c0_un_b0:1; -+ uint64_t c0_up_bx:1; -+ uint64_t c0_up_wi:1; -+ uint64_t c0_up_b2:1; -+ uint64_t c0_up_b1:1; -+ uint64_t c0_up_b0:1; -+ uint64_t c1_hpint:1; -+ uint64_t c1_pmei:1; -+ uint64_t c1_wake:1; -+ uint64_t crs1_dr:1; -+ uint64_t c1_se:1; -+ uint64_t crs1_er:1; -+ uint64_t c1_aeri:1; -+ uint64_t c0_hpint:1; -+ uint64_t c0_pmei:1; -+ uint64_t c0_wake:1; -+ uint64_t crs0_dr:1; -+ uint64_t c0_se:1; -+ uint64_t crs0_er:1; -+ uint64_t c0_aeri:1; -+ uint64_t reserved_15_18:4; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t dma1fi:1; -+ uint64_t dma0fi:1; -+ uint64_t reserved_8_8:1; -+ uint64_t dma3dbo:1; -+ uint64_t dma2dbo:1; -+ uint64_t dma1dbo:1; -+ uint64_t dma0dbo:1; -+ uint64_t iob2big:1; -+ uint64_t bar0_to:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } s; -+ struct cvmx_npei_int_sum2_s cn52xx; -+ struct cvmx_npei_int_sum2_s cn52xxp1; -+ struct cvmx_npei_int_sum2_s cn56xx; -+}; -+ -+union cvmx_npei_last_win_rdata0 { -+ uint64_t u64; -+ struct cvmx_npei_last_win_rdata0_s { -+ uint64_t data:64; -+ } s; -+ struct cvmx_npei_last_win_rdata0_s cn52xx; -+ struct cvmx_npei_last_win_rdata0_s cn52xxp1; -+ struct cvmx_npei_last_win_rdata0_s cn56xx; -+ struct cvmx_npei_last_win_rdata0_s cn56xxp1; -+}; -+ -+union cvmx_npei_last_win_rdata1 { -+ uint64_t u64; -+ struct cvmx_npei_last_win_rdata1_s { -+ uint64_t data:64; -+ } s; -+ struct cvmx_npei_last_win_rdata1_s cn52xx; -+ struct cvmx_npei_last_win_rdata1_s cn52xxp1; -+ struct cvmx_npei_last_win_rdata1_s cn56xx; -+ struct cvmx_npei_last_win_rdata1_s cn56xxp1; -+}; -+ -+union cvmx_npei_mem_access_ctl { -+ uint64_t u64; -+ struct cvmx_npei_mem_access_ctl_s { -+ uint64_t reserved_14_63:50; -+ uint64_t max_word:4; -+ uint64_t timer:10; -+ } s; -+ struct cvmx_npei_mem_access_ctl_s cn52xx; -+ struct cvmx_npei_mem_access_ctl_s cn52xxp1; -+ struct cvmx_npei_mem_access_ctl_s cn56xx; -+ struct cvmx_npei_mem_access_ctl_s cn56xxp1; -+}; -+ -+union cvmx_npei_mem_access_subidx { -+ uint64_t u64; -+ struct cvmx_npei_mem_access_subidx_s { -+ uint64_t reserved_42_63:22; -+ uint64_t zero:1; -+ uint64_t port:2; -+ uint64_t nmerge:1; -+ uint64_t esr:2; -+ uint64_t esw:2; -+ uint64_t nsr:1; -+ uint64_t nsw:1; -+ uint64_t ror:1; -+ uint64_t row:1; -+ uint64_t ba:30; -+ } s; -+ struct cvmx_npei_mem_access_subidx_s cn52xx; -+ struct cvmx_npei_mem_access_subidx_s cn52xxp1; -+ struct cvmx_npei_mem_access_subidx_s cn56xx; -+ struct cvmx_npei_mem_access_subidx_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_enb0 { -+ uint64_t u64; -+ struct cvmx_npei_msi_enb0_s { -+ uint64_t enb:64; -+ } s; -+ struct cvmx_npei_msi_enb0_s cn52xx; -+ struct cvmx_npei_msi_enb0_s cn52xxp1; -+ struct cvmx_npei_msi_enb0_s cn56xx; -+ struct cvmx_npei_msi_enb0_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_enb1 { -+ uint64_t u64; -+ struct cvmx_npei_msi_enb1_s { -+ uint64_t enb:64; -+ } s; -+ struct cvmx_npei_msi_enb1_s cn52xx; -+ struct cvmx_npei_msi_enb1_s cn52xxp1; -+ struct cvmx_npei_msi_enb1_s cn56xx; -+ struct cvmx_npei_msi_enb1_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_enb2 { -+ uint64_t u64; -+ struct cvmx_npei_msi_enb2_s { -+ uint64_t enb:64; -+ } s; -+ struct cvmx_npei_msi_enb2_s cn52xx; -+ struct cvmx_npei_msi_enb2_s cn52xxp1; -+ struct cvmx_npei_msi_enb2_s cn56xx; -+ struct cvmx_npei_msi_enb2_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_enb3 { -+ uint64_t u64; -+ struct cvmx_npei_msi_enb3_s { -+ uint64_t enb:64; -+ } s; -+ struct cvmx_npei_msi_enb3_s cn52xx; -+ struct cvmx_npei_msi_enb3_s cn52xxp1; -+ struct cvmx_npei_msi_enb3_s cn56xx; -+ struct cvmx_npei_msi_enb3_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_rcv0 { -+ uint64_t u64; -+ struct cvmx_npei_msi_rcv0_s { -+ uint64_t intr:64; -+ } s; -+ struct cvmx_npei_msi_rcv0_s cn52xx; -+ struct cvmx_npei_msi_rcv0_s cn52xxp1; -+ struct cvmx_npei_msi_rcv0_s cn56xx; -+ struct cvmx_npei_msi_rcv0_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_rcv1 { -+ uint64_t u64; -+ struct cvmx_npei_msi_rcv1_s { -+ uint64_t intr:64; -+ } s; -+ struct cvmx_npei_msi_rcv1_s cn52xx; -+ struct cvmx_npei_msi_rcv1_s cn52xxp1; -+ struct cvmx_npei_msi_rcv1_s cn56xx; -+ struct cvmx_npei_msi_rcv1_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_rcv2 { -+ uint64_t u64; -+ struct cvmx_npei_msi_rcv2_s { -+ uint64_t intr:64; -+ } s; -+ struct cvmx_npei_msi_rcv2_s cn52xx; -+ struct cvmx_npei_msi_rcv2_s cn52xxp1; -+ struct cvmx_npei_msi_rcv2_s cn56xx; -+ struct cvmx_npei_msi_rcv2_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_rcv3 { -+ uint64_t u64; -+ struct cvmx_npei_msi_rcv3_s { -+ uint64_t intr:64; -+ } s; -+ struct cvmx_npei_msi_rcv3_s cn52xx; -+ struct cvmx_npei_msi_rcv3_s cn52xxp1; -+ struct cvmx_npei_msi_rcv3_s cn56xx; -+ struct cvmx_npei_msi_rcv3_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_rd_map { -+ uint64_t u64; -+ struct cvmx_npei_msi_rd_map_s { -+ uint64_t reserved_16_63:48; -+ uint64_t rd_int:8; -+ uint64_t msi_int:8; -+ } s; -+ struct cvmx_npei_msi_rd_map_s cn52xx; -+ struct cvmx_npei_msi_rd_map_s cn52xxp1; -+ struct cvmx_npei_msi_rd_map_s cn56xx; -+ struct cvmx_npei_msi_rd_map_s cn56xxp1; -+}; -+ -+union cvmx_npei_msi_w1c_enb0 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1c_enb0_s { -+ uint64_t clr:64; -+ } s; -+ struct cvmx_npei_msi_w1c_enb0_s cn52xx; -+ struct cvmx_npei_msi_w1c_enb0_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1c_enb1 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1c_enb1_s { -+ uint64_t clr:64; -+ } s; -+ struct cvmx_npei_msi_w1c_enb1_s cn52xx; -+ struct cvmx_npei_msi_w1c_enb1_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1c_enb2 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1c_enb2_s { -+ uint64_t clr:64; -+ } s; -+ struct cvmx_npei_msi_w1c_enb2_s cn52xx; -+ struct cvmx_npei_msi_w1c_enb2_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1c_enb3 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1c_enb3_s { -+ uint64_t clr:64; -+ } s; -+ struct cvmx_npei_msi_w1c_enb3_s cn52xx; -+ struct cvmx_npei_msi_w1c_enb3_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1s_enb0 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1s_enb0_s { -+ uint64_t set:64; -+ } s; -+ struct cvmx_npei_msi_w1s_enb0_s cn52xx; -+ struct cvmx_npei_msi_w1s_enb0_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1s_enb1 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1s_enb1_s { -+ uint64_t set:64; -+ } s; -+ struct cvmx_npei_msi_w1s_enb1_s cn52xx; -+ struct cvmx_npei_msi_w1s_enb1_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1s_enb2 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1s_enb2_s { -+ uint64_t set:64; -+ } s; -+ struct cvmx_npei_msi_w1s_enb2_s cn52xx; -+ struct cvmx_npei_msi_w1s_enb2_s cn56xx; -+}; -+ -+union cvmx_npei_msi_w1s_enb3 { -+ uint64_t u64; -+ struct cvmx_npei_msi_w1s_enb3_s { -+ uint64_t set:64; -+ } s; -+ struct cvmx_npei_msi_w1s_enb3_s cn52xx; -+ struct cvmx_npei_msi_w1s_enb3_s cn56xx; -+}; -+ -+union cvmx_npei_msi_wr_map { -+ uint64_t u64; -+ struct cvmx_npei_msi_wr_map_s { -+ uint64_t reserved_16_63:48; -+ uint64_t ciu_int:8; -+ uint64_t msi_int:8; -+ } s; -+ struct cvmx_npei_msi_wr_map_s cn52xx; -+ struct cvmx_npei_msi_wr_map_s cn52xxp1; -+ struct cvmx_npei_msi_wr_map_s cn56xx; -+ struct cvmx_npei_msi_wr_map_s cn56xxp1; -+}; -+ -+union cvmx_npei_pcie_credit_cnt { -+ uint64_t u64; -+ struct cvmx_npei_pcie_credit_cnt_s { -+ uint64_t reserved_48_63:16; -+ uint64_t p1_ccnt:8; -+ uint64_t p1_ncnt:8; -+ uint64_t p1_pcnt:8; -+ uint64_t p0_ccnt:8; -+ uint64_t p0_ncnt:8; -+ uint64_t p0_pcnt:8; -+ } s; -+ struct cvmx_npei_pcie_credit_cnt_s cn52xx; -+ struct cvmx_npei_pcie_credit_cnt_s cn56xx; -+}; -+ -+union cvmx_npei_pcie_msi_rcv { -+ uint64_t u64; -+ struct cvmx_npei_pcie_msi_rcv_s { -+ uint64_t reserved_8_63:56; -+ uint64_t intr:8; -+ } s; -+ struct cvmx_npei_pcie_msi_rcv_s cn52xx; -+ struct cvmx_npei_pcie_msi_rcv_s cn52xxp1; -+ struct cvmx_npei_pcie_msi_rcv_s cn56xx; -+ struct cvmx_npei_pcie_msi_rcv_s cn56xxp1; -+}; -+ -+union cvmx_npei_pcie_msi_rcv_b1 { -+ uint64_t u64; -+ struct cvmx_npei_pcie_msi_rcv_b1_s { -+ uint64_t reserved_16_63:48; -+ uint64_t intr:8; -+ uint64_t reserved_0_7:8; -+ } s; -+ struct cvmx_npei_pcie_msi_rcv_b1_s cn52xx; -+ struct cvmx_npei_pcie_msi_rcv_b1_s cn52xxp1; -+ struct cvmx_npei_pcie_msi_rcv_b1_s cn56xx; -+ struct cvmx_npei_pcie_msi_rcv_b1_s cn56xxp1; -+}; -+ -+union cvmx_npei_pcie_msi_rcv_b2 { -+ uint64_t u64; -+ struct cvmx_npei_pcie_msi_rcv_b2_s { -+ uint64_t reserved_24_63:40; -+ uint64_t intr:8; -+ uint64_t reserved_0_15:16; -+ } s; -+ struct cvmx_npei_pcie_msi_rcv_b2_s cn52xx; -+ struct cvmx_npei_pcie_msi_rcv_b2_s cn52xxp1; -+ struct cvmx_npei_pcie_msi_rcv_b2_s cn56xx; -+ struct cvmx_npei_pcie_msi_rcv_b2_s cn56xxp1; -+}; -+ -+union cvmx_npei_pcie_msi_rcv_b3 { -+ uint64_t u64; -+ struct cvmx_npei_pcie_msi_rcv_b3_s { -+ uint64_t reserved_32_63:32; -+ uint64_t intr:8; -+ uint64_t reserved_0_23:24; -+ } s; -+ struct cvmx_npei_pcie_msi_rcv_b3_s cn52xx; -+ struct cvmx_npei_pcie_msi_rcv_b3_s cn52xxp1; -+ struct cvmx_npei_pcie_msi_rcv_b3_s cn56xx; -+ struct cvmx_npei_pcie_msi_rcv_b3_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_cnts { -+ uint64_t u64; -+ struct cvmx_npei_pktx_cnts_s { -+ uint64_t reserved_54_63:10; -+ uint64_t timer:22; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_npei_pktx_cnts_s cn52xx; -+ struct cvmx_npei_pktx_cnts_s cn56xx; -+ struct cvmx_npei_pktx_cnts_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_in_bp { -+ uint64_t u64; -+ struct cvmx_npei_pktx_in_bp_s { -+ uint64_t wmark:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_npei_pktx_in_bp_s cn52xx; -+ struct cvmx_npei_pktx_in_bp_s cn56xx; -+ struct cvmx_npei_pktx_in_bp_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_instr_baddr { -+ uint64_t u64; -+ struct cvmx_npei_pktx_instr_baddr_s { -+ uint64_t addr:61; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_npei_pktx_instr_baddr_s cn52xx; -+ struct cvmx_npei_pktx_instr_baddr_s cn56xx; -+ struct cvmx_npei_pktx_instr_baddr_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_instr_baoff_dbell { -+ uint64_t u64; -+ struct cvmx_npei_pktx_instr_baoff_dbell_s { -+ uint64_t aoff:32; -+ uint64_t dbell:32; -+ } s; -+ struct cvmx_npei_pktx_instr_baoff_dbell_s cn52xx; -+ struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xx; -+ struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_instr_fifo_rsize { -+ uint64_t u64; -+ struct cvmx_npei_pktx_instr_fifo_rsize_s { -+ uint64_t max:9; -+ uint64_t rrp:9; -+ uint64_t wrp:9; -+ uint64_t fcnt:5; -+ uint64_t rsize:32; -+ } s; -+ struct cvmx_npei_pktx_instr_fifo_rsize_s cn52xx; -+ struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xx; -+ struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_instr_header { -+ uint64_t u64; -+ struct cvmx_npei_pktx_instr_header_s { -+ uint64_t reserved_44_63:20; -+ uint64_t pbp:1; -+ uint64_t rsv_f:5; -+ uint64_t rparmode:2; -+ uint64_t rsv_e:1; -+ uint64_t rskp_len:7; -+ uint64_t rsv_d:6; -+ uint64_t use_ihdr:1; -+ uint64_t rsv_c:5; -+ uint64_t par_mode:2; -+ uint64_t rsv_b:1; -+ uint64_t skp_len:7; -+ uint64_t rsv_a:6; -+ } s; -+ struct cvmx_npei_pktx_instr_header_s cn52xx; -+ struct cvmx_npei_pktx_instr_header_s cn56xx; -+ struct cvmx_npei_pktx_instr_header_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_slist_baddr { -+ uint64_t u64; -+ struct cvmx_npei_pktx_slist_baddr_s { -+ uint64_t addr:60; -+ uint64_t reserved_0_3:4; -+ } s; -+ struct cvmx_npei_pktx_slist_baddr_s cn52xx; -+ struct cvmx_npei_pktx_slist_baddr_s cn56xx; -+ struct cvmx_npei_pktx_slist_baddr_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_slist_baoff_dbell { -+ uint64_t u64; -+ struct cvmx_npei_pktx_slist_baoff_dbell_s { -+ uint64_t aoff:32; -+ uint64_t dbell:32; -+ } s; -+ struct cvmx_npei_pktx_slist_baoff_dbell_s cn52xx; -+ struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xx; -+ struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xxp1; -+}; -+ -+union cvmx_npei_pktx_slist_fifo_rsize { -+ uint64_t u64; -+ struct cvmx_npei_pktx_slist_fifo_rsize_s { -+ uint64_t reserved_32_63:32; -+ uint64_t rsize:32; -+ } s; -+ struct cvmx_npei_pktx_slist_fifo_rsize_s cn52xx; -+ struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xx; -+ struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_cnt_int { -+ uint64_t u64; -+ struct cvmx_npei_pkt_cnt_int_s { -+ uint64_t reserved_32_63:32; -+ uint64_t port:32; -+ } s; -+ struct cvmx_npei_pkt_cnt_int_s cn52xx; -+ struct cvmx_npei_pkt_cnt_int_s cn56xx; -+ struct cvmx_npei_pkt_cnt_int_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_cnt_int_enb { -+ uint64_t u64; -+ struct cvmx_npei_pkt_cnt_int_enb_s { -+ uint64_t reserved_32_63:32; -+ uint64_t port:32; -+ } s; -+ struct cvmx_npei_pkt_cnt_int_enb_s cn52xx; -+ struct cvmx_npei_pkt_cnt_int_enb_s cn56xx; -+ struct cvmx_npei_pkt_cnt_int_enb_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_data_out_es { -+ uint64_t u64; -+ struct cvmx_npei_pkt_data_out_es_s { -+ uint64_t es:64; -+ } s; -+ struct cvmx_npei_pkt_data_out_es_s cn52xx; -+ struct cvmx_npei_pkt_data_out_es_s cn56xx; -+ struct cvmx_npei_pkt_data_out_es_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_data_out_ns { -+ uint64_t u64; -+ struct cvmx_npei_pkt_data_out_ns_s { -+ uint64_t reserved_32_63:32; -+ uint64_t nsr:32; -+ } s; -+ struct cvmx_npei_pkt_data_out_ns_s cn52xx; -+ struct cvmx_npei_pkt_data_out_ns_s cn56xx; -+ struct cvmx_npei_pkt_data_out_ns_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_data_out_ror { -+ uint64_t u64; -+ struct cvmx_npei_pkt_data_out_ror_s { -+ uint64_t reserved_32_63:32; -+ uint64_t ror:32; -+ } s; -+ struct cvmx_npei_pkt_data_out_ror_s cn52xx; -+ struct cvmx_npei_pkt_data_out_ror_s cn56xx; -+ struct cvmx_npei_pkt_data_out_ror_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_dpaddr { -+ uint64_t u64; -+ struct cvmx_npei_pkt_dpaddr_s { -+ uint64_t reserved_32_63:32; -+ uint64_t dptr:32; -+ } s; -+ struct cvmx_npei_pkt_dpaddr_s cn52xx; -+ struct cvmx_npei_pkt_dpaddr_s cn56xx; -+ struct cvmx_npei_pkt_dpaddr_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_in_bp { -+ uint64_t u64; -+ struct cvmx_npei_pkt_in_bp_s { -+ uint64_t reserved_32_63:32; -+ uint64_t bp:32; -+ } s; -+ struct cvmx_npei_pkt_in_bp_s cn56xx; -+}; -+ -+union cvmx_npei_pkt_in_donex_cnts { -+ uint64_t u64; -+ struct cvmx_npei_pkt_in_donex_cnts_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_npei_pkt_in_donex_cnts_s cn52xx; -+ struct cvmx_npei_pkt_in_donex_cnts_s cn56xx; -+ struct cvmx_npei_pkt_in_donex_cnts_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_in_instr_counts { -+ uint64_t u64; -+ struct cvmx_npei_pkt_in_instr_counts_s { -+ uint64_t wr_cnt:32; -+ uint64_t rd_cnt:32; -+ } s; -+ struct cvmx_npei_pkt_in_instr_counts_s cn52xx; -+ struct cvmx_npei_pkt_in_instr_counts_s cn56xx; -+}; -+ -+union cvmx_npei_pkt_in_pcie_port { -+ uint64_t u64; -+ struct cvmx_npei_pkt_in_pcie_port_s { -+ uint64_t pp:64; -+ } s; -+ struct cvmx_npei_pkt_in_pcie_port_s cn52xx; -+ struct cvmx_npei_pkt_in_pcie_port_s cn56xx; -+}; -+ -+union cvmx_npei_pkt_input_control { -+ uint64_t u64; -+ struct cvmx_npei_pkt_input_control_s { -+ uint64_t reserved_23_63:41; -+ uint64_t pkt_rr:1; -+ uint64_t pbp_dhi:13; -+ uint64_t d_nsr:1; -+ uint64_t d_esr:2; -+ uint64_t d_ror:1; -+ uint64_t use_csr:1; -+ uint64_t nsr:1; -+ uint64_t esr:2; -+ uint64_t ror:1; -+ } s; -+ struct cvmx_npei_pkt_input_control_s cn52xx; -+ struct cvmx_npei_pkt_input_control_s cn56xx; -+ struct cvmx_npei_pkt_input_control_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_instr_enb { -+ uint64_t u64; -+ struct cvmx_npei_pkt_instr_enb_s { -+ uint64_t reserved_32_63:32; -+ uint64_t enb:32; -+ } s; -+ struct cvmx_npei_pkt_instr_enb_s cn52xx; -+ struct cvmx_npei_pkt_instr_enb_s cn56xx; -+ struct cvmx_npei_pkt_instr_enb_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_instr_rd_size { -+ uint64_t u64; -+ struct cvmx_npei_pkt_instr_rd_size_s { -+ uint64_t rdsize:64; -+ } s; -+ struct cvmx_npei_pkt_instr_rd_size_s cn52xx; -+ struct cvmx_npei_pkt_instr_rd_size_s cn56xx; -+}; -+ -+union cvmx_npei_pkt_instr_size { -+ uint64_t u64; -+ struct cvmx_npei_pkt_instr_size_s { -+ uint64_t reserved_32_63:32; -+ uint64_t is_64b:32; -+ } s; -+ struct cvmx_npei_pkt_instr_size_s cn52xx; -+ struct cvmx_npei_pkt_instr_size_s cn56xx; -+ struct cvmx_npei_pkt_instr_size_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_int_levels { -+ uint64_t u64; -+ struct cvmx_npei_pkt_int_levels_s { -+ uint64_t reserved_54_63:10; -+ uint64_t time:22; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_npei_pkt_int_levels_s cn52xx; -+ struct cvmx_npei_pkt_int_levels_s cn56xx; -+ struct cvmx_npei_pkt_int_levels_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_iptr { -+ uint64_t u64; -+ struct cvmx_npei_pkt_iptr_s { -+ uint64_t reserved_32_63:32; -+ uint64_t iptr:32; -+ } s; -+ struct cvmx_npei_pkt_iptr_s cn52xx; -+ struct cvmx_npei_pkt_iptr_s cn56xx; -+ struct cvmx_npei_pkt_iptr_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_out_bmode { -+ uint64_t u64; -+ struct cvmx_npei_pkt_out_bmode_s { -+ uint64_t reserved_32_63:32; -+ uint64_t bmode:32; -+ } s; -+ struct cvmx_npei_pkt_out_bmode_s cn52xx; -+ struct cvmx_npei_pkt_out_bmode_s cn56xx; -+ struct cvmx_npei_pkt_out_bmode_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_out_enb { -+ uint64_t u64; -+ struct cvmx_npei_pkt_out_enb_s { -+ uint64_t reserved_32_63:32; -+ uint64_t enb:32; -+ } s; -+ struct cvmx_npei_pkt_out_enb_s cn52xx; -+ struct cvmx_npei_pkt_out_enb_s cn56xx; -+ struct cvmx_npei_pkt_out_enb_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_output_wmark { -+ uint64_t u64; -+ struct cvmx_npei_pkt_output_wmark_s { -+ uint64_t reserved_32_63:32; -+ uint64_t wmark:32; -+ } s; -+ struct cvmx_npei_pkt_output_wmark_s cn52xx; -+ struct cvmx_npei_pkt_output_wmark_s cn56xx; -+}; -+ -+union cvmx_npei_pkt_pcie_port { -+ uint64_t u64; -+ struct cvmx_npei_pkt_pcie_port_s { -+ uint64_t pp:64; -+ } s; -+ struct cvmx_npei_pkt_pcie_port_s cn52xx; -+ struct cvmx_npei_pkt_pcie_port_s cn56xx; -+ struct cvmx_npei_pkt_pcie_port_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_port_in_rst { -+ uint64_t u64; -+ struct cvmx_npei_pkt_port_in_rst_s { -+ uint64_t in_rst:32; -+ uint64_t out_rst:32; -+ } s; -+ struct cvmx_npei_pkt_port_in_rst_s cn52xx; -+ struct cvmx_npei_pkt_port_in_rst_s cn56xx; -+}; -+ -+union cvmx_npei_pkt_slist_es { -+ uint64_t u64; -+ struct cvmx_npei_pkt_slist_es_s { -+ uint64_t es:64; -+ } s; -+ struct cvmx_npei_pkt_slist_es_s cn52xx; -+ struct cvmx_npei_pkt_slist_es_s cn56xx; -+ struct cvmx_npei_pkt_slist_es_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_slist_id_size { -+ uint64_t u64; -+ struct cvmx_npei_pkt_slist_id_size_s { -+ uint64_t reserved_23_63:41; -+ uint64_t isize:7; -+ uint64_t bsize:16; -+ } s; -+ struct cvmx_npei_pkt_slist_id_size_s cn52xx; -+ struct cvmx_npei_pkt_slist_id_size_s cn56xx; -+ struct cvmx_npei_pkt_slist_id_size_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_slist_ns { -+ uint64_t u64; -+ struct cvmx_npei_pkt_slist_ns_s { -+ uint64_t reserved_32_63:32; -+ uint64_t nsr:32; -+ } s; -+ struct cvmx_npei_pkt_slist_ns_s cn52xx; -+ struct cvmx_npei_pkt_slist_ns_s cn56xx; -+ struct cvmx_npei_pkt_slist_ns_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_slist_ror { -+ uint64_t u64; -+ struct cvmx_npei_pkt_slist_ror_s { -+ uint64_t reserved_32_63:32; -+ uint64_t ror:32; -+ } s; -+ struct cvmx_npei_pkt_slist_ror_s cn52xx; -+ struct cvmx_npei_pkt_slist_ror_s cn56xx; -+ struct cvmx_npei_pkt_slist_ror_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_time_int { -+ uint64_t u64; -+ struct cvmx_npei_pkt_time_int_s { -+ uint64_t reserved_32_63:32; -+ uint64_t port:32; -+ } s; -+ struct cvmx_npei_pkt_time_int_s cn52xx; -+ struct cvmx_npei_pkt_time_int_s cn56xx; -+ struct cvmx_npei_pkt_time_int_s cn56xxp1; -+}; -+ -+union cvmx_npei_pkt_time_int_enb { -+ uint64_t u64; -+ struct cvmx_npei_pkt_time_int_enb_s { -+ uint64_t reserved_32_63:32; -+ uint64_t port:32; -+ } s; -+ struct cvmx_npei_pkt_time_int_enb_s cn52xx; -+ struct cvmx_npei_pkt_time_int_enb_s cn56xx; -+ struct cvmx_npei_pkt_time_int_enb_s cn56xxp1; -+}; -+ -+union cvmx_npei_rsl_int_blocks { -+ uint64_t u64; -+ struct cvmx_npei_rsl_int_blocks_s { -+ uint64_t reserved_31_63:33; -+ uint64_t iob:1; -+ uint64_t lmc1:1; -+ uint64_t agl:1; -+ uint64_t reserved_24_27:4; -+ uint64_t asxpcs1:1; -+ uint64_t asxpcs0:1; -+ uint64_t reserved_21_21:1; -+ uint64_t pip:1; -+ uint64_t reserved_18_19:2; -+ uint64_t lmc0:1; -+ uint64_t l2c:1; -+ uint64_t usb1:1; -+ uint64_t rad:1; -+ uint64_t usb:1; -+ uint64_t pow:1; -+ uint64_t tim:1; -+ uint64_t pko:1; -+ uint64_t ipd:1; -+ uint64_t reserved_8_8:1; -+ uint64_t zip:1; -+ uint64_t reserved_6_6:1; -+ uint64_t fpa:1; -+ uint64_t key:1; -+ uint64_t npei:1; -+ uint64_t gmx1:1; -+ uint64_t gmx0:1; -+ uint64_t mio:1; -+ } s; -+ struct cvmx_npei_rsl_int_blocks_s cn52xx; -+ struct cvmx_npei_rsl_int_blocks_s cn52xxp1; -+ struct cvmx_npei_rsl_int_blocks_cn56xx { -+ uint64_t reserved_31_63:33; -+ uint64_t iob:1; -+ uint64_t lmc1:1; -+ uint64_t agl:1; -+ uint64_t reserved_24_27:4; -+ uint64_t asxpcs1:1; -+ uint64_t asxpcs0:1; -+ uint64_t reserved_21_21:1; -+ uint64_t pip:1; -+ uint64_t reserved_18_19:2; -+ uint64_t lmc0:1; -+ uint64_t l2c:1; -+ uint64_t reserved_15_15:1; -+ uint64_t rad:1; -+ uint64_t usb:1; -+ uint64_t pow:1; -+ uint64_t tim:1; -+ uint64_t pko:1; -+ uint64_t ipd:1; -+ uint64_t reserved_8_8:1; -+ uint64_t zip:1; -+ uint64_t reserved_6_6:1; -+ uint64_t fpa:1; -+ uint64_t key:1; -+ uint64_t npei:1; -+ uint64_t gmx1:1; -+ uint64_t gmx0:1; -+ uint64_t mio:1; -+ } cn56xx; -+ struct cvmx_npei_rsl_int_blocks_cn56xx cn56xxp1; -+}; -+ -+union cvmx_npei_scratch_1 { -+ uint64_t u64; -+ struct cvmx_npei_scratch_1_s { -+ uint64_t data:64; -+ } s; -+ struct cvmx_npei_scratch_1_s cn52xx; -+ struct cvmx_npei_scratch_1_s cn52xxp1; -+ struct cvmx_npei_scratch_1_s cn56xx; -+ struct cvmx_npei_scratch_1_s cn56xxp1; -+}; -+ -+union cvmx_npei_state1 { -+ uint64_t u64; -+ struct cvmx_npei_state1_s { -+ uint64_t cpl1:12; -+ uint64_t cpl0:12; -+ uint64_t arb:1; -+ uint64_t csr:39; -+ } s; -+ struct cvmx_npei_state1_s cn52xx; -+ struct cvmx_npei_state1_s cn52xxp1; -+ struct cvmx_npei_state1_s cn56xx; -+ struct cvmx_npei_state1_s cn56xxp1; -+}; -+ -+union cvmx_npei_state2 { -+ uint64_t u64; -+ struct cvmx_npei_state2_s { -+ uint64_t reserved_48_63:16; -+ uint64_t npei:1; -+ uint64_t rac:1; -+ uint64_t csm1:15; -+ uint64_t csm0:15; -+ uint64_t nnp0:8; -+ uint64_t nnd:8; -+ } s; -+ struct cvmx_npei_state2_s cn52xx; -+ struct cvmx_npei_state2_s cn52xxp1; -+ struct cvmx_npei_state2_s cn56xx; -+ struct cvmx_npei_state2_s cn56xxp1; -+}; -+ -+union cvmx_npei_state3 { -+ uint64_t u64; -+ struct cvmx_npei_state3_s { -+ uint64_t reserved_56_63:8; -+ uint64_t psm1:15; -+ uint64_t psm0:15; -+ uint64_t nsm1:13; -+ uint64_t nsm0:13; -+ } s; -+ struct cvmx_npei_state3_s cn52xx; -+ struct cvmx_npei_state3_s cn52xxp1; -+ struct cvmx_npei_state3_s cn56xx; -+ struct cvmx_npei_state3_s cn56xxp1; -+}; -+ -+union cvmx_npei_win_rd_addr { -+ uint64_t u64; -+ struct cvmx_npei_win_rd_addr_s { -+ uint64_t reserved_51_63:13; -+ uint64_t ld_cmd:2; -+ uint64_t iobit:1; -+ uint64_t rd_addr:48; -+ } s; -+ struct cvmx_npei_win_rd_addr_s cn52xx; -+ struct cvmx_npei_win_rd_addr_s cn52xxp1; -+ struct cvmx_npei_win_rd_addr_s cn56xx; -+ struct cvmx_npei_win_rd_addr_s cn56xxp1; -+}; -+ -+union cvmx_npei_win_rd_data { -+ uint64_t u64; -+ struct cvmx_npei_win_rd_data_s { -+ uint64_t rd_data:64; -+ } s; -+ struct cvmx_npei_win_rd_data_s cn52xx; -+ struct cvmx_npei_win_rd_data_s cn52xxp1; -+ struct cvmx_npei_win_rd_data_s cn56xx; -+ struct cvmx_npei_win_rd_data_s cn56xxp1; -+}; -+ -+union cvmx_npei_win_wr_addr { -+ uint64_t u64; -+ struct cvmx_npei_win_wr_addr_s { -+ uint64_t reserved_49_63:15; -+ uint64_t iobit:1; -+ uint64_t wr_addr:46; -+ uint64_t reserved_0_1:2; -+ } s; -+ struct cvmx_npei_win_wr_addr_s cn52xx; -+ struct cvmx_npei_win_wr_addr_s cn52xxp1; -+ struct cvmx_npei_win_wr_addr_s cn56xx; -+ struct cvmx_npei_win_wr_addr_s cn56xxp1; -+}; -+ -+union cvmx_npei_win_wr_data { -+ uint64_t u64; -+ struct cvmx_npei_win_wr_data_s { -+ uint64_t wr_data:64; -+ } s; -+ struct cvmx_npei_win_wr_data_s cn52xx; -+ struct cvmx_npei_win_wr_data_s cn52xxp1; -+ struct cvmx_npei_win_wr_data_s cn56xx; -+ struct cvmx_npei_win_wr_data_s cn56xxp1; -+}; -+ -+union cvmx_npei_win_wr_mask { -+ uint64_t u64; -+ struct cvmx_npei_win_wr_mask_s { -+ uint64_t reserved_8_63:56; -+ uint64_t wr_mask:8; -+ } s; -+ struct cvmx_npei_win_wr_mask_s cn52xx; -+ struct cvmx_npei_win_wr_mask_s cn52xxp1; -+ struct cvmx_npei_win_wr_mask_s cn56xx; -+ struct cvmx_npei_win_wr_mask_s cn56xxp1; -+}; -+ -+union cvmx_npei_window_ctl { -+ uint64_t u64; -+ struct cvmx_npei_window_ctl_s { -+ uint64_t reserved_32_63:32; -+ uint64_t time:32; -+ } s; -+ struct cvmx_npei_window_ctl_s cn52xx; -+ struct cvmx_npei_window_ctl_s cn52xxp1; -+ struct cvmx_npei_window_ctl_s cn56xx; -+ struct cvmx_npei_window_ctl_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-npi-defs.h -@@ -0,0 +1,1735 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_NPI_DEFS_H__ -+#define __CVMX_NPI_DEFS_H__ -+ -+#define CVMX_NPI_BASE_ADDR_INPUT0 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000070ull) -+#define CVMX_NPI_BASE_ADDR_INPUT1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000080ull) -+#define CVMX_NPI_BASE_ADDR_INPUT2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000090ull) -+#define CVMX_NPI_BASE_ADDR_INPUT3 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000A0ull) -+#define CVMX_NPI_BASE_ADDR_INPUTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000000070ull + (((offset) & 3) * 16)) -+#define CVMX_NPI_BASE_ADDR_OUTPUT0 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000B8ull) -+#define CVMX_NPI_BASE_ADDR_OUTPUT1 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000C0ull) -+#define CVMX_NPI_BASE_ADDR_OUTPUT2 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000C8ull) -+#define CVMX_NPI_BASE_ADDR_OUTPUT3 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000D0ull) -+#define CVMX_NPI_BASE_ADDR_OUTPUTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F00000000B8ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_BIST_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011F00000003F8ull) -+#define CVMX_NPI_BUFF_SIZE_OUTPUT0 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000E0ull) -+#define CVMX_NPI_BUFF_SIZE_OUTPUT1 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000E8ull) -+#define CVMX_NPI_BUFF_SIZE_OUTPUT2 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000F0ull) -+#define CVMX_NPI_BUFF_SIZE_OUTPUT3 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000F8ull) -+#define CVMX_NPI_BUFF_SIZE_OUTPUTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F00000000E0ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_COMP_CTL \ -+ CVMX_ADD_IO_SEG(0x00011F0000000218ull) -+#define CVMX_NPI_CTL_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000010ull) -+#define CVMX_NPI_DBG_SELECT \ -+ CVMX_ADD_IO_SEG(0x00011F0000000008ull) -+#define CVMX_NPI_DMA_CONTROL \ -+ CVMX_ADD_IO_SEG(0x00011F0000000128ull) -+#define CVMX_NPI_DMA_HIGHP_COUNTS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000148ull) -+#define CVMX_NPI_DMA_HIGHP_NADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000158ull) -+#define CVMX_NPI_DMA_LOWP_COUNTS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000140ull) -+#define CVMX_NPI_DMA_LOWP_NADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000150ull) -+#define CVMX_NPI_HIGHP_DBELL \ -+ CVMX_ADD_IO_SEG(0x00011F0000000120ull) -+#define CVMX_NPI_HIGHP_IBUFF_SADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000110ull) -+#define CVMX_NPI_INPUT_CONTROL \ -+ CVMX_ADD_IO_SEG(0x00011F0000000138ull) -+#define CVMX_NPI_INT_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000000020ull) -+#define CVMX_NPI_INT_SUM \ -+ CVMX_ADD_IO_SEG(0x00011F0000000018ull) -+#define CVMX_NPI_LOWP_DBELL \ -+ CVMX_ADD_IO_SEG(0x00011F0000000118ull) -+#define CVMX_NPI_LOWP_IBUFF_SADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000108ull) -+#define CVMX_NPI_MEM_ACCESS_SUBID3 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000028ull) -+#define CVMX_NPI_MEM_ACCESS_SUBID4 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000030ull) -+#define CVMX_NPI_MEM_ACCESS_SUBID5 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000038ull) -+#define CVMX_NPI_MEM_ACCESS_SUBID6 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000040ull) -+#define CVMX_NPI_MEM_ACCESS_SUBIDX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000000028ull + (((offset) & 7) * 8) - 8 * 3) -+#define CVMX_NPI_MSI_RCV \ -+ (0x0000000000000190ull) -+#define CVMX_NPI_NPI_MSI_RCV \ -+ CVMX_ADD_IO_SEG(0x00011F0000001190ull) -+#define CVMX_NPI_NUM_DESC_OUTPUT0 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000050ull) -+#define CVMX_NPI_NUM_DESC_OUTPUT1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000058ull) -+#define CVMX_NPI_NUM_DESC_OUTPUT2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000060ull) -+#define CVMX_NPI_NUM_DESC_OUTPUT3 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000068ull) -+#define CVMX_NPI_NUM_DESC_OUTPUTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000000050ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_OUTPUT_CONTROL \ -+ CVMX_ADD_IO_SEG(0x00011F0000000100ull) -+#define CVMX_NPI_P0_DBPAIR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000180ull) -+#define CVMX_NPI_P0_INSTR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F00000001C0ull) -+#define CVMX_NPI_P0_INSTR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F00000001A0ull) -+#define CVMX_NPI_P0_PAIR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000160ull) -+#define CVMX_NPI_P1_DBPAIR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000188ull) -+#define CVMX_NPI_P1_INSTR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F00000001C8ull) -+#define CVMX_NPI_P1_INSTR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F00000001A8ull) -+#define CVMX_NPI_P1_PAIR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000168ull) -+#define CVMX_NPI_P2_DBPAIR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000190ull) -+#define CVMX_NPI_P2_INSTR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F00000001D0ull) -+#define CVMX_NPI_P2_INSTR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F00000001B0ull) -+#define CVMX_NPI_P2_PAIR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000170ull) -+#define CVMX_NPI_P3_DBPAIR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000198ull) -+#define CVMX_NPI_P3_INSTR_ADDR \ -+ CVMX_ADD_IO_SEG(0x00011F00000001D8ull) -+#define CVMX_NPI_P3_INSTR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F00000001B8ull) -+#define CVMX_NPI_P3_PAIR_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000178ull) -+#define CVMX_NPI_PCI_BAR1_INDEXX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000001100ull + (((offset) & 31) * 4)) -+#define CVMX_NPI_PCI_BIST_REG \ -+ CVMX_ADD_IO_SEG(0x00011F00000011C0ull) -+#define CVMX_NPI_PCI_BURST_SIZE \ -+ CVMX_ADD_IO_SEG(0x00011F00000000D8ull) -+#define CVMX_NPI_PCI_CFG00 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001800ull) -+#define CVMX_NPI_PCI_CFG01 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001804ull) -+#define CVMX_NPI_PCI_CFG02 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001808ull) -+#define CVMX_NPI_PCI_CFG03 \ -+ CVMX_ADD_IO_SEG(0x00011F000000180Cull) -+#define CVMX_NPI_PCI_CFG04 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001810ull) -+#define CVMX_NPI_PCI_CFG05 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001814ull) -+#define CVMX_NPI_PCI_CFG06 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001818ull) -+#define CVMX_NPI_PCI_CFG07 \ -+ CVMX_ADD_IO_SEG(0x00011F000000181Cull) -+#define CVMX_NPI_PCI_CFG08 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001820ull) -+#define CVMX_NPI_PCI_CFG09 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001824ull) -+#define CVMX_NPI_PCI_CFG10 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001828ull) -+#define CVMX_NPI_PCI_CFG11 \ -+ CVMX_ADD_IO_SEG(0x00011F000000182Cull) -+#define CVMX_NPI_PCI_CFG12 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001830ull) -+#define CVMX_NPI_PCI_CFG13 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001834ull) -+#define CVMX_NPI_PCI_CFG15 \ -+ CVMX_ADD_IO_SEG(0x00011F000000183Cull) -+#define CVMX_NPI_PCI_CFG16 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001840ull) -+#define CVMX_NPI_PCI_CFG17 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001844ull) -+#define CVMX_NPI_PCI_CFG18 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001848ull) -+#define CVMX_NPI_PCI_CFG19 \ -+ CVMX_ADD_IO_SEG(0x00011F000000184Cull) -+#define CVMX_NPI_PCI_CFG20 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001850ull) -+#define CVMX_NPI_PCI_CFG21 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001854ull) -+#define CVMX_NPI_PCI_CFG22 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001858ull) -+#define CVMX_NPI_PCI_CFG56 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018E0ull) -+#define CVMX_NPI_PCI_CFG57 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018E4ull) -+#define CVMX_NPI_PCI_CFG58 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018E8ull) -+#define CVMX_NPI_PCI_CFG59 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018ECull) -+#define CVMX_NPI_PCI_CFG60 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018F0ull) -+#define CVMX_NPI_PCI_CFG61 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018F4ull) -+#define CVMX_NPI_PCI_CFG62 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018F8ull) -+#define CVMX_NPI_PCI_CFG63 \ -+ CVMX_ADD_IO_SEG(0x00011F00000018FCull) -+#define CVMX_NPI_PCI_CNT_REG \ -+ CVMX_ADD_IO_SEG(0x00011F00000011B8ull) -+#define CVMX_NPI_PCI_CTL_STATUS_2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000118Cull) -+#define CVMX_NPI_PCI_INT_ARB_CFG \ -+ CVMX_ADD_IO_SEG(0x00011F0000000130ull) -+#define CVMX_NPI_PCI_INT_ENB2 \ -+ CVMX_ADD_IO_SEG(0x00011F00000011A0ull) -+#define CVMX_NPI_PCI_INT_SUM2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001198ull) -+#define CVMX_NPI_PCI_READ_CMD \ -+ CVMX_ADD_IO_SEG(0x00011F0000000048ull) -+#define CVMX_NPI_PCI_READ_CMD_6 \ -+ CVMX_ADD_IO_SEG(0x00011F0000001180ull) -+#define CVMX_NPI_PCI_READ_CMD_C \ -+ CVMX_ADD_IO_SEG(0x00011F0000001184ull) -+#define CVMX_NPI_PCI_READ_CMD_E \ -+ CVMX_ADD_IO_SEG(0x00011F0000001188ull) -+#define CVMX_NPI_PCI_SCM_REG \ -+ CVMX_ADD_IO_SEG(0x00011F00000011A8ull) -+#define CVMX_NPI_PCI_TSR_REG \ -+ CVMX_ADD_IO_SEG(0x00011F00000011B0ull) -+#define CVMX_NPI_PORT32_INSTR_HDR \ -+ CVMX_ADD_IO_SEG(0x00011F00000001F8ull) -+#define CVMX_NPI_PORT33_INSTR_HDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000200ull) -+#define CVMX_NPI_PORT34_INSTR_HDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000208ull) -+#define CVMX_NPI_PORT35_INSTR_HDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000000210ull) -+#define CVMX_NPI_PORT_BP_CONTROL \ -+ CVMX_ADD_IO_SEG(0x00011F00000001F0ull) -+#define CVMX_NPI_PX_DBPAIR_ADDR(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000000180ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_PX_INSTR_ADDR(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F00000001C0ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_PX_INSTR_CNTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F00000001A0ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_PX_PAIR_CNTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000000160ull + (((offset) & 3) * 8)) -+#define CVMX_NPI_RSL_INT_BLOCKS \ -+ CVMX_ADD_IO_SEG(0x00011F0000000000ull) -+#define CVMX_NPI_SIZE_INPUT0 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000078ull) -+#define CVMX_NPI_SIZE_INPUT1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000088ull) -+#define CVMX_NPI_SIZE_INPUT2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000000098ull) -+#define CVMX_NPI_SIZE_INPUT3 \ -+ CVMX_ADD_IO_SEG(0x00011F00000000A8ull) -+#define CVMX_NPI_SIZE_INPUTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000000078ull + (((offset) & 3) * 16)) -+#define CVMX_NPI_WIN_READ_TO \ -+ CVMX_ADD_IO_SEG(0x00011F00000001E0ull) -+ -+union cvmx_npi_base_addr_inputx { -+ uint64_t u64; -+ struct cvmx_npi_base_addr_inputx_s { -+ uint64_t baddr:61; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_npi_base_addr_inputx_s cn30xx; -+ struct cvmx_npi_base_addr_inputx_s cn31xx; -+ struct cvmx_npi_base_addr_inputx_s cn38xx; -+ struct cvmx_npi_base_addr_inputx_s cn38xxp2; -+ struct cvmx_npi_base_addr_inputx_s cn50xx; -+ struct cvmx_npi_base_addr_inputx_s cn58xx; -+ struct cvmx_npi_base_addr_inputx_s cn58xxp1; -+}; -+ -+union cvmx_npi_base_addr_outputx { -+ uint64_t u64; -+ struct cvmx_npi_base_addr_outputx_s { -+ uint64_t baddr:61; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_npi_base_addr_outputx_s cn30xx; -+ struct cvmx_npi_base_addr_outputx_s cn31xx; -+ struct cvmx_npi_base_addr_outputx_s cn38xx; -+ struct cvmx_npi_base_addr_outputx_s cn38xxp2; -+ struct cvmx_npi_base_addr_outputx_s cn50xx; -+ struct cvmx_npi_base_addr_outputx_s cn58xx; -+ struct cvmx_npi_base_addr_outputx_s cn58xxp1; -+}; -+ -+union cvmx_npi_bist_status { -+ uint64_t u64; -+ struct cvmx_npi_bist_status_s { -+ uint64_t reserved_20_63:44; -+ uint64_t csr_bs:1; -+ uint64_t dif_bs:1; -+ uint64_t rdp_bs:1; -+ uint64_t pcnc_bs:1; -+ uint64_t pcn_bs:1; -+ uint64_t rdn_bs:1; -+ uint64_t pcac_bs:1; -+ uint64_t pcad_bs:1; -+ uint64_t rdnl_bs:1; -+ uint64_t pgf_bs:1; -+ uint64_t pig_bs:1; -+ uint64_t pof0_bs:1; -+ uint64_t pof1_bs:1; -+ uint64_t pof2_bs:1; -+ uint64_t pof3_bs:1; -+ uint64_t pos_bs:1; -+ uint64_t nus_bs:1; -+ uint64_t dob_bs:1; -+ uint64_t pdf_bs:1; -+ uint64_t dpi_bs:1; -+ } s; -+ struct cvmx_npi_bist_status_cn30xx { -+ uint64_t reserved_20_63:44; -+ uint64_t csr_bs:1; -+ uint64_t dif_bs:1; -+ uint64_t rdp_bs:1; -+ uint64_t pcnc_bs:1; -+ uint64_t pcn_bs:1; -+ uint64_t rdn_bs:1; -+ uint64_t pcac_bs:1; -+ uint64_t pcad_bs:1; -+ uint64_t rdnl_bs:1; -+ uint64_t pgf_bs:1; -+ uint64_t pig_bs:1; -+ uint64_t pof0_bs:1; -+ uint64_t reserved_5_7:3; -+ uint64_t pos_bs:1; -+ uint64_t nus_bs:1; -+ uint64_t dob_bs:1; -+ uint64_t pdf_bs:1; -+ uint64_t dpi_bs:1; -+ } cn30xx; -+ struct cvmx_npi_bist_status_s cn31xx; -+ struct cvmx_npi_bist_status_s cn38xx; -+ struct cvmx_npi_bist_status_s cn38xxp2; -+ struct cvmx_npi_bist_status_cn50xx { -+ uint64_t reserved_20_63:44; -+ uint64_t csr_bs:1; -+ uint64_t dif_bs:1; -+ uint64_t rdp_bs:1; -+ uint64_t pcnc_bs:1; -+ uint64_t pcn_bs:1; -+ uint64_t rdn_bs:1; -+ uint64_t pcac_bs:1; -+ uint64_t pcad_bs:1; -+ uint64_t rdnl_bs:1; -+ uint64_t pgf_bs:1; -+ uint64_t pig_bs:1; -+ uint64_t pof0_bs:1; -+ uint64_t pof1_bs:1; -+ uint64_t reserved_5_6:2; -+ uint64_t pos_bs:1; -+ uint64_t nus_bs:1; -+ uint64_t dob_bs:1; -+ uint64_t pdf_bs:1; -+ uint64_t dpi_bs:1; -+ } cn50xx; -+ struct cvmx_npi_bist_status_s cn58xx; -+ struct cvmx_npi_bist_status_s cn58xxp1; -+}; -+ -+union cvmx_npi_buff_size_outputx { -+ uint64_t u64; -+ struct cvmx_npi_buff_size_outputx_s { -+ uint64_t reserved_23_63:41; -+ uint64_t isize:7; -+ uint64_t bsize:16; -+ } s; -+ struct cvmx_npi_buff_size_outputx_s cn30xx; -+ struct cvmx_npi_buff_size_outputx_s cn31xx; -+ struct cvmx_npi_buff_size_outputx_s cn38xx; -+ struct cvmx_npi_buff_size_outputx_s cn38xxp2; -+ struct cvmx_npi_buff_size_outputx_s cn50xx; -+ struct cvmx_npi_buff_size_outputx_s cn58xx; -+ struct cvmx_npi_buff_size_outputx_s cn58xxp1; -+}; -+ -+union cvmx_npi_comp_ctl { -+ uint64_t u64; -+ struct cvmx_npi_comp_ctl_s { -+ uint64_t reserved_10_63:54; -+ uint64_t pctl:5; -+ uint64_t nctl:5; -+ } s; -+ struct cvmx_npi_comp_ctl_s cn50xx; -+ struct cvmx_npi_comp_ctl_s cn58xx; -+ struct cvmx_npi_comp_ctl_s cn58xxp1; -+}; -+ -+union cvmx_npi_ctl_status { -+ uint64_t u64; -+ struct cvmx_npi_ctl_status_s { -+ uint64_t reserved_63_63:1; -+ uint64_t chip_rev:8; -+ uint64_t dis_pniw:1; -+ uint64_t out3_enb:1; -+ uint64_t out2_enb:1; -+ uint64_t out1_enb:1; -+ uint64_t out0_enb:1; -+ uint64_t ins3_enb:1; -+ uint64_t ins2_enb:1; -+ uint64_t ins1_enb:1; -+ uint64_t ins0_enb:1; -+ uint64_t ins3_64b:1; -+ uint64_t ins2_64b:1; -+ uint64_t ins1_64b:1; -+ uint64_t ins0_64b:1; -+ uint64_t pci_wdis:1; -+ uint64_t wait_com:1; -+ uint64_t reserved_37_39:3; -+ uint64_t max_word:5; -+ uint64_t reserved_10_31:22; -+ uint64_t timer:10; -+ } s; -+ struct cvmx_npi_ctl_status_cn30xx { -+ uint64_t reserved_63_63:1; -+ uint64_t chip_rev:8; -+ uint64_t dis_pniw:1; -+ uint64_t reserved_51_53:3; -+ uint64_t out0_enb:1; -+ uint64_t reserved_47_49:3; -+ uint64_t ins0_enb:1; -+ uint64_t reserved_43_45:3; -+ uint64_t ins0_64b:1; -+ uint64_t pci_wdis:1; -+ uint64_t wait_com:1; -+ uint64_t reserved_37_39:3; -+ uint64_t max_word:5; -+ uint64_t reserved_10_31:22; -+ uint64_t timer:10; -+ } cn30xx; -+ struct cvmx_npi_ctl_status_cn31xx { -+ uint64_t reserved_63_63:1; -+ uint64_t chip_rev:8; -+ uint64_t dis_pniw:1; -+ uint64_t reserved_52_53:2; -+ uint64_t out1_enb:1; -+ uint64_t out0_enb:1; -+ uint64_t reserved_48_49:2; -+ uint64_t ins1_enb:1; -+ uint64_t ins0_enb:1; -+ uint64_t reserved_44_45:2; -+ uint64_t ins1_64b:1; -+ uint64_t ins0_64b:1; -+ uint64_t pci_wdis:1; -+ uint64_t wait_com:1; -+ uint64_t reserved_37_39:3; -+ uint64_t max_word:5; -+ uint64_t reserved_10_31:22; -+ uint64_t timer:10; -+ } cn31xx; -+ struct cvmx_npi_ctl_status_s cn38xx; -+ struct cvmx_npi_ctl_status_s cn38xxp2; -+ struct cvmx_npi_ctl_status_cn31xx cn50xx; -+ struct cvmx_npi_ctl_status_s cn58xx; -+ struct cvmx_npi_ctl_status_s cn58xxp1; -+}; -+ -+union cvmx_npi_dbg_select { -+ uint64_t u64; -+ struct cvmx_npi_dbg_select_s { -+ uint64_t reserved_16_63:48; -+ uint64_t dbg_sel:16; -+ } s; -+ struct cvmx_npi_dbg_select_s cn30xx; -+ struct cvmx_npi_dbg_select_s cn31xx; -+ struct cvmx_npi_dbg_select_s cn38xx; -+ struct cvmx_npi_dbg_select_s cn38xxp2; -+ struct cvmx_npi_dbg_select_s cn50xx; -+ struct cvmx_npi_dbg_select_s cn58xx; -+ struct cvmx_npi_dbg_select_s cn58xxp1; -+}; -+ -+union cvmx_npi_dma_control { -+ uint64_t u64; -+ struct cvmx_npi_dma_control_s { -+ uint64_t reserved_36_63:28; -+ uint64_t b0_lend:1; -+ uint64_t dwb_denb:1; -+ uint64_t dwb_ichk:9; -+ uint64_t fpa_que:3; -+ uint64_t o_add1:1; -+ uint64_t o_ro:1; -+ uint64_t o_ns:1; -+ uint64_t o_es:2; -+ uint64_t o_mode:1; -+ uint64_t hp_enb:1; -+ uint64_t lp_enb:1; -+ uint64_t csize:14; -+ } s; -+ struct cvmx_npi_dma_control_s cn30xx; -+ struct cvmx_npi_dma_control_s cn31xx; -+ struct cvmx_npi_dma_control_s cn38xx; -+ struct cvmx_npi_dma_control_s cn38xxp2; -+ struct cvmx_npi_dma_control_s cn50xx; -+ struct cvmx_npi_dma_control_s cn58xx; -+ struct cvmx_npi_dma_control_s cn58xxp1; -+}; -+ -+union cvmx_npi_dma_highp_counts { -+ uint64_t u64; -+ struct cvmx_npi_dma_highp_counts_s { -+ uint64_t reserved_39_63:25; -+ uint64_t fcnt:7; -+ uint64_t dbell:32; -+ } s; -+ struct cvmx_npi_dma_highp_counts_s cn30xx; -+ struct cvmx_npi_dma_highp_counts_s cn31xx; -+ struct cvmx_npi_dma_highp_counts_s cn38xx; -+ struct cvmx_npi_dma_highp_counts_s cn38xxp2; -+ struct cvmx_npi_dma_highp_counts_s cn50xx; -+ struct cvmx_npi_dma_highp_counts_s cn58xx; -+ struct cvmx_npi_dma_highp_counts_s cn58xxp1; -+}; -+ -+union cvmx_npi_dma_highp_naddr { -+ uint64_t u64; -+ struct cvmx_npi_dma_highp_naddr_s { -+ uint64_t reserved_40_63:24; -+ uint64_t state:4; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_npi_dma_highp_naddr_s cn30xx; -+ struct cvmx_npi_dma_highp_naddr_s cn31xx; -+ struct cvmx_npi_dma_highp_naddr_s cn38xx; -+ struct cvmx_npi_dma_highp_naddr_s cn38xxp2; -+ struct cvmx_npi_dma_highp_naddr_s cn50xx; -+ struct cvmx_npi_dma_highp_naddr_s cn58xx; -+ struct cvmx_npi_dma_highp_naddr_s cn58xxp1; -+}; -+ -+union cvmx_npi_dma_lowp_counts { -+ uint64_t u64; -+ struct cvmx_npi_dma_lowp_counts_s { -+ uint64_t reserved_39_63:25; -+ uint64_t fcnt:7; -+ uint64_t dbell:32; -+ } s; -+ struct cvmx_npi_dma_lowp_counts_s cn30xx; -+ struct cvmx_npi_dma_lowp_counts_s cn31xx; -+ struct cvmx_npi_dma_lowp_counts_s cn38xx; -+ struct cvmx_npi_dma_lowp_counts_s cn38xxp2; -+ struct cvmx_npi_dma_lowp_counts_s cn50xx; -+ struct cvmx_npi_dma_lowp_counts_s cn58xx; -+ struct cvmx_npi_dma_lowp_counts_s cn58xxp1; -+}; -+ -+union cvmx_npi_dma_lowp_naddr { -+ uint64_t u64; -+ struct cvmx_npi_dma_lowp_naddr_s { -+ uint64_t reserved_40_63:24; -+ uint64_t state:4; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_npi_dma_lowp_naddr_s cn30xx; -+ struct cvmx_npi_dma_lowp_naddr_s cn31xx; -+ struct cvmx_npi_dma_lowp_naddr_s cn38xx; -+ struct cvmx_npi_dma_lowp_naddr_s cn38xxp2; -+ struct cvmx_npi_dma_lowp_naddr_s cn50xx; -+ struct cvmx_npi_dma_lowp_naddr_s cn58xx; -+ struct cvmx_npi_dma_lowp_naddr_s cn58xxp1; -+}; -+ -+union cvmx_npi_highp_dbell { -+ uint64_t u64; -+ struct cvmx_npi_highp_dbell_s { -+ uint64_t reserved_16_63:48; -+ uint64_t dbell:16; -+ } s; -+ struct cvmx_npi_highp_dbell_s cn30xx; -+ struct cvmx_npi_highp_dbell_s cn31xx; -+ struct cvmx_npi_highp_dbell_s cn38xx; -+ struct cvmx_npi_highp_dbell_s cn38xxp2; -+ struct cvmx_npi_highp_dbell_s cn50xx; -+ struct cvmx_npi_highp_dbell_s cn58xx; -+ struct cvmx_npi_highp_dbell_s cn58xxp1; -+}; -+ -+union cvmx_npi_highp_ibuff_saddr { -+ uint64_t u64; -+ struct cvmx_npi_highp_ibuff_saddr_s { -+ uint64_t reserved_36_63:28; -+ uint64_t saddr:36; -+ } s; -+ struct cvmx_npi_highp_ibuff_saddr_s cn30xx; -+ struct cvmx_npi_highp_ibuff_saddr_s cn31xx; -+ struct cvmx_npi_highp_ibuff_saddr_s cn38xx; -+ struct cvmx_npi_highp_ibuff_saddr_s cn38xxp2; -+ struct cvmx_npi_highp_ibuff_saddr_s cn50xx; -+ struct cvmx_npi_highp_ibuff_saddr_s cn58xx; -+ struct cvmx_npi_highp_ibuff_saddr_s cn58xxp1; -+}; -+ -+union cvmx_npi_input_control { -+ uint64_t u64; -+ struct cvmx_npi_input_control_s { -+ uint64_t reserved_23_63:41; -+ uint64_t pkt_rr:1; -+ uint64_t pbp_dhi:13; -+ uint64_t d_nsr:1; -+ uint64_t d_esr:2; -+ uint64_t d_ror:1; -+ uint64_t use_csr:1; -+ uint64_t nsr:1; -+ uint64_t esr:2; -+ uint64_t ror:1; -+ } s; -+ struct cvmx_npi_input_control_cn30xx { -+ uint64_t reserved_22_63:42; -+ uint64_t pbp_dhi:13; -+ uint64_t d_nsr:1; -+ uint64_t d_esr:2; -+ uint64_t d_ror:1; -+ uint64_t use_csr:1; -+ uint64_t nsr:1; -+ uint64_t esr:2; -+ uint64_t ror:1; -+ } cn30xx; -+ struct cvmx_npi_input_control_cn30xx cn31xx; -+ struct cvmx_npi_input_control_s cn38xx; -+ struct cvmx_npi_input_control_cn30xx cn38xxp2; -+ struct cvmx_npi_input_control_s cn50xx; -+ struct cvmx_npi_input_control_s cn58xx; -+ struct cvmx_npi_input_control_s cn58xxp1; -+}; -+ -+union cvmx_npi_int_enb { -+ uint64_t u64; -+ struct cvmx_npi_int_enb_s { -+ uint64_t reserved_62_63:2; -+ uint64_t q1_a_f:1; -+ uint64_t q1_s_e:1; -+ uint64_t pdf_p_f:1; -+ uint64_t pdf_p_e:1; -+ uint64_t pcf_p_f:1; -+ uint64_t pcf_p_e:1; -+ uint64_t rdx_s_e:1; -+ uint64_t rwx_s_e:1; -+ uint64_t pnc_a_f:1; -+ uint64_t pnc_s_e:1; -+ uint64_t com_a_f:1; -+ uint64_t com_s_e:1; -+ uint64_t q3_a_f:1; -+ uint64_t q3_s_e:1; -+ uint64_t q2_a_f:1; -+ uint64_t q2_s_e:1; -+ uint64_t pcr_a_f:1; -+ uint64_t pcr_s_e:1; -+ uint64_t fcr_a_f:1; -+ uint64_t fcr_s_e:1; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t i3_pperr:1; -+ uint64_t i2_pperr:1; -+ uint64_t i1_pperr:1; -+ uint64_t i0_pperr:1; -+ uint64_t p3_ptout:1; -+ uint64_t p2_ptout:1; -+ uint64_t p1_ptout:1; -+ uint64_t p0_ptout:1; -+ uint64_t p3_pperr:1; -+ uint64_t p2_pperr:1; -+ uint64_t p1_pperr:1; -+ uint64_t p0_pperr:1; -+ uint64_t g3_rtout:1; -+ uint64_t g2_rtout:1; -+ uint64_t g1_rtout:1; -+ uint64_t g0_rtout:1; -+ uint64_t p3_perr:1; -+ uint64_t p2_perr:1; -+ uint64_t p1_perr:1; -+ uint64_t p0_perr:1; -+ uint64_t p3_rtout:1; -+ uint64_t p2_rtout:1; -+ uint64_t p1_rtout:1; -+ uint64_t p0_rtout:1; -+ uint64_t i3_overf:1; -+ uint64_t i2_overf:1; -+ uint64_t i1_overf:1; -+ uint64_t i0_overf:1; -+ uint64_t i3_rtout:1; -+ uint64_t i2_rtout:1; -+ uint64_t i1_rtout:1; -+ uint64_t i0_rtout:1; -+ uint64_t po3_2sml:1; -+ uint64_t po2_2sml:1; -+ uint64_t po1_2sml:1; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } s; -+ struct cvmx_npi_int_enb_cn30xx { -+ uint64_t reserved_62_63:2; -+ uint64_t q1_a_f:1; -+ uint64_t q1_s_e:1; -+ uint64_t pdf_p_f:1; -+ uint64_t pdf_p_e:1; -+ uint64_t pcf_p_f:1; -+ uint64_t pcf_p_e:1; -+ uint64_t rdx_s_e:1; -+ uint64_t rwx_s_e:1; -+ uint64_t pnc_a_f:1; -+ uint64_t pnc_s_e:1; -+ uint64_t com_a_f:1; -+ uint64_t com_s_e:1; -+ uint64_t q3_a_f:1; -+ uint64_t q3_s_e:1; -+ uint64_t q2_a_f:1; -+ uint64_t q2_s_e:1; -+ uint64_t pcr_a_f:1; -+ uint64_t pcr_s_e:1; -+ uint64_t fcr_a_f:1; -+ uint64_t fcr_s_e:1; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t reserved_36_38:3; -+ uint64_t i0_pperr:1; -+ uint64_t reserved_32_34:3; -+ uint64_t p0_ptout:1; -+ uint64_t reserved_28_30:3; -+ uint64_t p0_pperr:1; -+ uint64_t reserved_24_26:3; -+ uint64_t g0_rtout:1; -+ uint64_t reserved_20_22:3; -+ uint64_t p0_perr:1; -+ uint64_t reserved_16_18:3; -+ uint64_t p0_rtout:1; -+ uint64_t reserved_12_14:3; -+ uint64_t i0_overf:1; -+ uint64_t reserved_8_10:3; -+ uint64_t i0_rtout:1; -+ uint64_t reserved_4_6:3; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn30xx; -+ struct cvmx_npi_int_enb_cn31xx { -+ uint64_t reserved_62_63:2; -+ uint64_t q1_a_f:1; -+ uint64_t q1_s_e:1; -+ uint64_t pdf_p_f:1; -+ uint64_t pdf_p_e:1; -+ uint64_t pcf_p_f:1; -+ uint64_t pcf_p_e:1; -+ uint64_t rdx_s_e:1; -+ uint64_t rwx_s_e:1; -+ uint64_t pnc_a_f:1; -+ uint64_t pnc_s_e:1; -+ uint64_t com_a_f:1; -+ uint64_t com_s_e:1; -+ uint64_t q3_a_f:1; -+ uint64_t q3_s_e:1; -+ uint64_t q2_a_f:1; -+ uint64_t q2_s_e:1; -+ uint64_t pcr_a_f:1; -+ uint64_t pcr_s_e:1; -+ uint64_t fcr_a_f:1; -+ uint64_t fcr_s_e:1; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t reserved_37_38:2; -+ uint64_t i1_pperr:1; -+ uint64_t i0_pperr:1; -+ uint64_t reserved_33_34:2; -+ uint64_t p1_ptout:1; -+ uint64_t p0_ptout:1; -+ uint64_t reserved_29_30:2; -+ uint64_t p1_pperr:1; -+ uint64_t p0_pperr:1; -+ uint64_t reserved_25_26:2; -+ uint64_t g1_rtout:1; -+ uint64_t g0_rtout:1; -+ uint64_t reserved_21_22:2; -+ uint64_t p1_perr:1; -+ uint64_t p0_perr:1; -+ uint64_t reserved_17_18:2; -+ uint64_t p1_rtout:1; -+ uint64_t p0_rtout:1; -+ uint64_t reserved_13_14:2; -+ uint64_t i1_overf:1; -+ uint64_t i0_overf:1; -+ uint64_t reserved_9_10:2; -+ uint64_t i1_rtout:1; -+ uint64_t i0_rtout:1; -+ uint64_t reserved_5_6:2; -+ uint64_t po1_2sml:1; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn31xx; -+ struct cvmx_npi_int_enb_s cn38xx; -+ struct cvmx_npi_int_enb_cn38xxp2 { -+ uint64_t reserved_42_63:22; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t i3_pperr:1; -+ uint64_t i2_pperr:1; -+ uint64_t i1_pperr:1; -+ uint64_t i0_pperr:1; -+ uint64_t p3_ptout:1; -+ uint64_t p2_ptout:1; -+ uint64_t p1_ptout:1; -+ uint64_t p0_ptout:1; -+ uint64_t p3_pperr:1; -+ uint64_t p2_pperr:1; -+ uint64_t p1_pperr:1; -+ uint64_t p0_pperr:1; -+ uint64_t g3_rtout:1; -+ uint64_t g2_rtout:1; -+ uint64_t g1_rtout:1; -+ uint64_t g0_rtout:1; -+ uint64_t p3_perr:1; -+ uint64_t p2_perr:1; -+ uint64_t p1_perr:1; -+ uint64_t p0_perr:1; -+ uint64_t p3_rtout:1; -+ uint64_t p2_rtout:1; -+ uint64_t p1_rtout:1; -+ uint64_t p0_rtout:1; -+ uint64_t i3_overf:1; -+ uint64_t i2_overf:1; -+ uint64_t i1_overf:1; -+ uint64_t i0_overf:1; -+ uint64_t i3_rtout:1; -+ uint64_t i2_rtout:1; -+ uint64_t i1_rtout:1; -+ uint64_t i0_rtout:1; -+ uint64_t po3_2sml:1; -+ uint64_t po2_2sml:1; -+ uint64_t po1_2sml:1; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn38xxp2; -+ struct cvmx_npi_int_enb_cn31xx cn50xx; -+ struct cvmx_npi_int_enb_s cn58xx; -+ struct cvmx_npi_int_enb_s cn58xxp1; -+}; -+ -+union cvmx_npi_int_sum { -+ uint64_t u64; -+ struct cvmx_npi_int_sum_s { -+ uint64_t reserved_62_63:2; -+ uint64_t q1_a_f:1; -+ uint64_t q1_s_e:1; -+ uint64_t pdf_p_f:1; -+ uint64_t pdf_p_e:1; -+ uint64_t pcf_p_f:1; -+ uint64_t pcf_p_e:1; -+ uint64_t rdx_s_e:1; -+ uint64_t rwx_s_e:1; -+ uint64_t pnc_a_f:1; -+ uint64_t pnc_s_e:1; -+ uint64_t com_a_f:1; -+ uint64_t com_s_e:1; -+ uint64_t q3_a_f:1; -+ uint64_t q3_s_e:1; -+ uint64_t q2_a_f:1; -+ uint64_t q2_s_e:1; -+ uint64_t pcr_a_f:1; -+ uint64_t pcr_s_e:1; -+ uint64_t fcr_a_f:1; -+ uint64_t fcr_s_e:1; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t i3_pperr:1; -+ uint64_t i2_pperr:1; -+ uint64_t i1_pperr:1; -+ uint64_t i0_pperr:1; -+ uint64_t p3_ptout:1; -+ uint64_t p2_ptout:1; -+ uint64_t p1_ptout:1; -+ uint64_t p0_ptout:1; -+ uint64_t p3_pperr:1; -+ uint64_t p2_pperr:1; -+ uint64_t p1_pperr:1; -+ uint64_t p0_pperr:1; -+ uint64_t g3_rtout:1; -+ uint64_t g2_rtout:1; -+ uint64_t g1_rtout:1; -+ uint64_t g0_rtout:1; -+ uint64_t p3_perr:1; -+ uint64_t p2_perr:1; -+ uint64_t p1_perr:1; -+ uint64_t p0_perr:1; -+ uint64_t p3_rtout:1; -+ uint64_t p2_rtout:1; -+ uint64_t p1_rtout:1; -+ uint64_t p0_rtout:1; -+ uint64_t i3_overf:1; -+ uint64_t i2_overf:1; -+ uint64_t i1_overf:1; -+ uint64_t i0_overf:1; -+ uint64_t i3_rtout:1; -+ uint64_t i2_rtout:1; -+ uint64_t i1_rtout:1; -+ uint64_t i0_rtout:1; -+ uint64_t po3_2sml:1; -+ uint64_t po2_2sml:1; -+ uint64_t po1_2sml:1; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } s; -+ struct cvmx_npi_int_sum_cn30xx { -+ uint64_t reserved_62_63:2; -+ uint64_t q1_a_f:1; -+ uint64_t q1_s_e:1; -+ uint64_t pdf_p_f:1; -+ uint64_t pdf_p_e:1; -+ uint64_t pcf_p_f:1; -+ uint64_t pcf_p_e:1; -+ uint64_t rdx_s_e:1; -+ uint64_t rwx_s_e:1; -+ uint64_t pnc_a_f:1; -+ uint64_t pnc_s_e:1; -+ uint64_t com_a_f:1; -+ uint64_t com_s_e:1; -+ uint64_t q3_a_f:1; -+ uint64_t q3_s_e:1; -+ uint64_t q2_a_f:1; -+ uint64_t q2_s_e:1; -+ uint64_t pcr_a_f:1; -+ uint64_t pcr_s_e:1; -+ uint64_t fcr_a_f:1; -+ uint64_t fcr_s_e:1; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t reserved_36_38:3; -+ uint64_t i0_pperr:1; -+ uint64_t reserved_32_34:3; -+ uint64_t p0_ptout:1; -+ uint64_t reserved_28_30:3; -+ uint64_t p0_pperr:1; -+ uint64_t reserved_24_26:3; -+ uint64_t g0_rtout:1; -+ uint64_t reserved_20_22:3; -+ uint64_t p0_perr:1; -+ uint64_t reserved_16_18:3; -+ uint64_t p0_rtout:1; -+ uint64_t reserved_12_14:3; -+ uint64_t i0_overf:1; -+ uint64_t reserved_8_10:3; -+ uint64_t i0_rtout:1; -+ uint64_t reserved_4_6:3; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn30xx; -+ struct cvmx_npi_int_sum_cn31xx { -+ uint64_t reserved_62_63:2; -+ uint64_t q1_a_f:1; -+ uint64_t q1_s_e:1; -+ uint64_t pdf_p_f:1; -+ uint64_t pdf_p_e:1; -+ uint64_t pcf_p_f:1; -+ uint64_t pcf_p_e:1; -+ uint64_t rdx_s_e:1; -+ uint64_t rwx_s_e:1; -+ uint64_t pnc_a_f:1; -+ uint64_t pnc_s_e:1; -+ uint64_t com_a_f:1; -+ uint64_t com_s_e:1; -+ uint64_t q3_a_f:1; -+ uint64_t q3_s_e:1; -+ uint64_t q2_a_f:1; -+ uint64_t q2_s_e:1; -+ uint64_t pcr_a_f:1; -+ uint64_t pcr_s_e:1; -+ uint64_t fcr_a_f:1; -+ uint64_t fcr_s_e:1; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t reserved_37_38:2; -+ uint64_t i1_pperr:1; -+ uint64_t i0_pperr:1; -+ uint64_t reserved_33_34:2; -+ uint64_t p1_ptout:1; -+ uint64_t p0_ptout:1; -+ uint64_t reserved_29_30:2; -+ uint64_t p1_pperr:1; -+ uint64_t p0_pperr:1; -+ uint64_t reserved_25_26:2; -+ uint64_t g1_rtout:1; -+ uint64_t g0_rtout:1; -+ uint64_t reserved_21_22:2; -+ uint64_t p1_perr:1; -+ uint64_t p0_perr:1; -+ uint64_t reserved_17_18:2; -+ uint64_t p1_rtout:1; -+ uint64_t p0_rtout:1; -+ uint64_t reserved_13_14:2; -+ uint64_t i1_overf:1; -+ uint64_t i0_overf:1; -+ uint64_t reserved_9_10:2; -+ uint64_t i1_rtout:1; -+ uint64_t i0_rtout:1; -+ uint64_t reserved_5_6:2; -+ uint64_t po1_2sml:1; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn31xx; -+ struct cvmx_npi_int_sum_s cn38xx; -+ struct cvmx_npi_int_sum_cn38xxp2 { -+ uint64_t reserved_42_63:22; -+ uint64_t iobdma:1; -+ uint64_t p_dperr:1; -+ uint64_t win_rto:1; -+ uint64_t i3_pperr:1; -+ uint64_t i2_pperr:1; -+ uint64_t i1_pperr:1; -+ uint64_t i0_pperr:1; -+ uint64_t p3_ptout:1; -+ uint64_t p2_ptout:1; -+ uint64_t p1_ptout:1; -+ uint64_t p0_ptout:1; -+ uint64_t p3_pperr:1; -+ uint64_t p2_pperr:1; -+ uint64_t p1_pperr:1; -+ uint64_t p0_pperr:1; -+ uint64_t g3_rtout:1; -+ uint64_t g2_rtout:1; -+ uint64_t g1_rtout:1; -+ uint64_t g0_rtout:1; -+ uint64_t p3_perr:1; -+ uint64_t p2_perr:1; -+ uint64_t p1_perr:1; -+ uint64_t p0_perr:1; -+ uint64_t p3_rtout:1; -+ uint64_t p2_rtout:1; -+ uint64_t p1_rtout:1; -+ uint64_t p0_rtout:1; -+ uint64_t i3_overf:1; -+ uint64_t i2_overf:1; -+ uint64_t i1_overf:1; -+ uint64_t i0_overf:1; -+ uint64_t i3_rtout:1; -+ uint64_t i2_rtout:1; -+ uint64_t i1_rtout:1; -+ uint64_t i0_rtout:1; -+ uint64_t po3_2sml:1; -+ uint64_t po2_2sml:1; -+ uint64_t po1_2sml:1; -+ uint64_t po0_2sml:1; -+ uint64_t pci_rsl:1; -+ uint64_t rml_wto:1; -+ uint64_t rml_rto:1; -+ } cn38xxp2; -+ struct cvmx_npi_int_sum_cn31xx cn50xx; -+ struct cvmx_npi_int_sum_s cn58xx; -+ struct cvmx_npi_int_sum_s cn58xxp1; -+}; -+ -+union cvmx_npi_lowp_dbell { -+ uint64_t u64; -+ struct cvmx_npi_lowp_dbell_s { -+ uint64_t reserved_16_63:48; -+ uint64_t dbell:16; -+ } s; -+ struct cvmx_npi_lowp_dbell_s cn30xx; -+ struct cvmx_npi_lowp_dbell_s cn31xx; -+ struct cvmx_npi_lowp_dbell_s cn38xx; -+ struct cvmx_npi_lowp_dbell_s cn38xxp2; -+ struct cvmx_npi_lowp_dbell_s cn50xx; -+ struct cvmx_npi_lowp_dbell_s cn58xx; -+ struct cvmx_npi_lowp_dbell_s cn58xxp1; -+}; -+ -+union cvmx_npi_lowp_ibuff_saddr { -+ uint64_t u64; -+ struct cvmx_npi_lowp_ibuff_saddr_s { -+ uint64_t reserved_36_63:28; -+ uint64_t saddr:36; -+ } s; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn30xx; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn31xx; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn38xx; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn38xxp2; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn50xx; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn58xx; -+ struct cvmx_npi_lowp_ibuff_saddr_s cn58xxp1; -+}; -+ -+union cvmx_npi_mem_access_subidx { -+ uint64_t u64; -+ struct cvmx_npi_mem_access_subidx_s { -+ uint64_t reserved_38_63:26; -+ uint64_t shortl:1; -+ uint64_t nmerge:1; -+ uint64_t esr:2; -+ uint64_t esw:2; -+ uint64_t nsr:1; -+ uint64_t nsw:1; -+ uint64_t ror:1; -+ uint64_t row:1; -+ uint64_t ba:28; -+ } s; -+ struct cvmx_npi_mem_access_subidx_s cn30xx; -+ struct cvmx_npi_mem_access_subidx_cn31xx { -+ uint64_t reserved_36_63:28; -+ uint64_t esr:2; -+ uint64_t esw:2; -+ uint64_t nsr:1; -+ uint64_t nsw:1; -+ uint64_t ror:1; -+ uint64_t row:1; -+ uint64_t ba:28; -+ } cn31xx; -+ struct cvmx_npi_mem_access_subidx_s cn38xx; -+ struct cvmx_npi_mem_access_subidx_cn31xx cn38xxp2; -+ struct cvmx_npi_mem_access_subidx_s cn50xx; -+ struct cvmx_npi_mem_access_subidx_s cn58xx; -+ struct cvmx_npi_mem_access_subidx_s cn58xxp1; -+}; -+ -+union cvmx_npi_msi_rcv { -+ uint64_t u64; -+ struct cvmx_npi_msi_rcv_s { -+ uint64_t int_vec:64; -+ } s; -+ struct cvmx_npi_msi_rcv_s cn30xx; -+ struct cvmx_npi_msi_rcv_s cn31xx; -+ struct cvmx_npi_msi_rcv_s cn38xx; -+ struct cvmx_npi_msi_rcv_s cn38xxp2; -+ struct cvmx_npi_msi_rcv_s cn50xx; -+ struct cvmx_npi_msi_rcv_s cn58xx; -+ struct cvmx_npi_msi_rcv_s cn58xxp1; -+}; -+ -+union cvmx_npi_num_desc_outputx { -+ uint64_t u64; -+ struct cvmx_npi_num_desc_outputx_s { -+ uint64_t reserved_32_63:32; -+ uint64_t size:32; -+ } s; -+ struct cvmx_npi_num_desc_outputx_s cn30xx; -+ struct cvmx_npi_num_desc_outputx_s cn31xx; -+ struct cvmx_npi_num_desc_outputx_s cn38xx; -+ struct cvmx_npi_num_desc_outputx_s cn38xxp2; -+ struct cvmx_npi_num_desc_outputx_s cn50xx; -+ struct cvmx_npi_num_desc_outputx_s cn58xx; -+ struct cvmx_npi_num_desc_outputx_s cn58xxp1; -+}; -+ -+union cvmx_npi_output_control { -+ uint64_t u64; -+ struct cvmx_npi_output_control_s { -+ uint64_t reserved_49_63:15; -+ uint64_t pkt_rr:1; -+ uint64_t p3_bmode:1; -+ uint64_t p2_bmode:1; -+ uint64_t p1_bmode:1; -+ uint64_t p0_bmode:1; -+ uint64_t o3_es:2; -+ uint64_t o3_ns:1; -+ uint64_t o3_ro:1; -+ uint64_t o2_es:2; -+ uint64_t o2_ns:1; -+ uint64_t o2_ro:1; -+ uint64_t o1_es:2; -+ uint64_t o1_ns:1; -+ uint64_t o1_ro:1; -+ uint64_t o0_es:2; -+ uint64_t o0_ns:1; -+ uint64_t o0_ro:1; -+ uint64_t o3_csrm:1; -+ uint64_t o2_csrm:1; -+ uint64_t o1_csrm:1; -+ uint64_t o0_csrm:1; -+ uint64_t reserved_20_23:4; -+ uint64_t iptr_o3:1; -+ uint64_t iptr_o2:1; -+ uint64_t iptr_o1:1; -+ uint64_t iptr_o0:1; -+ uint64_t esr_sl3:2; -+ uint64_t nsr_sl3:1; -+ uint64_t ror_sl3:1; -+ uint64_t esr_sl2:2; -+ uint64_t nsr_sl2:1; -+ uint64_t ror_sl2:1; -+ uint64_t esr_sl1:2; -+ uint64_t nsr_sl1:1; -+ uint64_t ror_sl1:1; -+ uint64_t esr_sl0:2; -+ uint64_t nsr_sl0:1; -+ uint64_t ror_sl0:1; -+ } s; -+ struct cvmx_npi_output_control_cn30xx { -+ uint64_t reserved_45_63:19; -+ uint64_t p0_bmode:1; -+ uint64_t reserved_32_43:12; -+ uint64_t o0_es:2; -+ uint64_t o0_ns:1; -+ uint64_t o0_ro:1; -+ uint64_t reserved_25_27:3; -+ uint64_t o0_csrm:1; -+ uint64_t reserved_17_23:7; -+ uint64_t iptr_o0:1; -+ uint64_t reserved_4_15:12; -+ uint64_t esr_sl0:2; -+ uint64_t nsr_sl0:1; -+ uint64_t ror_sl0:1; -+ } cn30xx; -+ struct cvmx_npi_output_control_cn31xx { -+ uint64_t reserved_46_63:18; -+ uint64_t p1_bmode:1; -+ uint64_t p0_bmode:1; -+ uint64_t reserved_36_43:8; -+ uint64_t o1_es:2; -+ uint64_t o1_ns:1; -+ uint64_t o1_ro:1; -+ uint64_t o0_es:2; -+ uint64_t o0_ns:1; -+ uint64_t o0_ro:1; -+ uint64_t reserved_26_27:2; -+ uint64_t o1_csrm:1; -+ uint64_t o0_csrm:1; -+ uint64_t reserved_18_23:6; -+ uint64_t iptr_o1:1; -+ uint64_t iptr_o0:1; -+ uint64_t reserved_8_15:8; -+ uint64_t esr_sl1:2; -+ uint64_t nsr_sl1:1; -+ uint64_t ror_sl1:1; -+ uint64_t esr_sl0:2; -+ uint64_t nsr_sl0:1; -+ uint64_t ror_sl0:1; -+ } cn31xx; -+ struct cvmx_npi_output_control_s cn38xx; -+ struct cvmx_npi_output_control_cn38xxp2 { -+ uint64_t reserved_48_63:16; -+ uint64_t p3_bmode:1; -+ uint64_t p2_bmode:1; -+ uint64_t p1_bmode:1; -+ uint64_t p0_bmode:1; -+ uint64_t o3_es:2; -+ uint64_t o3_ns:1; -+ uint64_t o3_ro:1; -+ uint64_t o2_es:2; -+ uint64_t o2_ns:1; -+ uint64_t o2_ro:1; -+ uint64_t o1_es:2; -+ uint64_t o1_ns:1; -+ uint64_t o1_ro:1; -+ uint64_t o0_es:2; -+ uint64_t o0_ns:1; -+ uint64_t o0_ro:1; -+ uint64_t o3_csrm:1; -+ uint64_t o2_csrm:1; -+ uint64_t o1_csrm:1; -+ uint64_t o0_csrm:1; -+ uint64_t reserved_20_23:4; -+ uint64_t iptr_o3:1; -+ uint64_t iptr_o2:1; -+ uint64_t iptr_o1:1; -+ uint64_t iptr_o0:1; -+ uint64_t esr_sl3:2; -+ uint64_t nsr_sl3:1; -+ uint64_t ror_sl3:1; -+ uint64_t esr_sl2:2; -+ uint64_t nsr_sl2:1; -+ uint64_t ror_sl2:1; -+ uint64_t esr_sl1:2; -+ uint64_t nsr_sl1:1; -+ uint64_t ror_sl1:1; -+ uint64_t esr_sl0:2; -+ uint64_t nsr_sl0:1; -+ uint64_t ror_sl0:1; -+ } cn38xxp2; -+ struct cvmx_npi_output_control_cn50xx { -+ uint64_t reserved_49_63:15; -+ uint64_t pkt_rr:1; -+ uint64_t reserved_46_47:2; -+ uint64_t p1_bmode:1; -+ uint64_t p0_bmode:1; -+ uint64_t reserved_36_43:8; -+ uint64_t o1_es:2; -+ uint64_t o1_ns:1; -+ uint64_t o1_ro:1; -+ uint64_t o0_es:2; -+ uint64_t o0_ns:1; -+ uint64_t o0_ro:1; -+ uint64_t reserved_26_27:2; -+ uint64_t o1_csrm:1; -+ uint64_t o0_csrm:1; -+ uint64_t reserved_18_23:6; -+ uint64_t iptr_o1:1; -+ uint64_t iptr_o0:1; -+ uint64_t reserved_8_15:8; -+ uint64_t esr_sl1:2; -+ uint64_t nsr_sl1:1; -+ uint64_t ror_sl1:1; -+ uint64_t esr_sl0:2; -+ uint64_t nsr_sl0:1; -+ uint64_t ror_sl0:1; -+ } cn50xx; -+ struct cvmx_npi_output_control_s cn58xx; -+ struct cvmx_npi_output_control_s cn58xxp1; -+}; -+ -+union cvmx_npi_px_dbpair_addr { -+ uint64_t u64; -+ struct cvmx_npi_px_dbpair_addr_s { -+ uint64_t reserved_63_63:1; -+ uint64_t state:2; -+ uint64_t naddr:61; -+ } s; -+ struct cvmx_npi_px_dbpair_addr_s cn30xx; -+ struct cvmx_npi_px_dbpair_addr_s cn31xx; -+ struct cvmx_npi_px_dbpair_addr_s cn38xx; -+ struct cvmx_npi_px_dbpair_addr_s cn38xxp2; -+ struct cvmx_npi_px_dbpair_addr_s cn50xx; -+ struct cvmx_npi_px_dbpair_addr_s cn58xx; -+ struct cvmx_npi_px_dbpair_addr_s cn58xxp1; -+}; -+ -+union cvmx_npi_px_instr_addr { -+ uint64_t u64; -+ struct cvmx_npi_px_instr_addr_s { -+ uint64_t state:3; -+ uint64_t naddr:61; -+ } s; -+ struct cvmx_npi_px_instr_addr_s cn30xx; -+ struct cvmx_npi_px_instr_addr_s cn31xx; -+ struct cvmx_npi_px_instr_addr_s cn38xx; -+ struct cvmx_npi_px_instr_addr_s cn38xxp2; -+ struct cvmx_npi_px_instr_addr_s cn50xx; -+ struct cvmx_npi_px_instr_addr_s cn58xx; -+ struct cvmx_npi_px_instr_addr_s cn58xxp1; -+}; -+ -+union cvmx_npi_px_instr_cnts { -+ uint64_t u64; -+ struct cvmx_npi_px_instr_cnts_s { -+ uint64_t reserved_38_63:26; -+ uint64_t fcnt:6; -+ uint64_t avail:32; -+ } s; -+ struct cvmx_npi_px_instr_cnts_s cn30xx; -+ struct cvmx_npi_px_instr_cnts_s cn31xx; -+ struct cvmx_npi_px_instr_cnts_s cn38xx; -+ struct cvmx_npi_px_instr_cnts_s cn38xxp2; -+ struct cvmx_npi_px_instr_cnts_s cn50xx; -+ struct cvmx_npi_px_instr_cnts_s cn58xx; -+ struct cvmx_npi_px_instr_cnts_s cn58xxp1; -+}; -+ -+union cvmx_npi_px_pair_cnts { -+ uint64_t u64; -+ struct cvmx_npi_px_pair_cnts_s { -+ uint64_t reserved_37_63:27; -+ uint64_t fcnt:5; -+ uint64_t avail:32; -+ } s; -+ struct cvmx_npi_px_pair_cnts_s cn30xx; -+ struct cvmx_npi_px_pair_cnts_s cn31xx; -+ struct cvmx_npi_px_pair_cnts_s cn38xx; -+ struct cvmx_npi_px_pair_cnts_s cn38xxp2; -+ struct cvmx_npi_px_pair_cnts_s cn50xx; -+ struct cvmx_npi_px_pair_cnts_s cn58xx; -+ struct cvmx_npi_px_pair_cnts_s cn58xxp1; -+}; -+ -+union cvmx_npi_pci_burst_size { -+ uint64_t u64; -+ struct cvmx_npi_pci_burst_size_s { -+ uint64_t reserved_14_63:50; -+ uint64_t wr_brst:7; -+ uint64_t rd_brst:7; -+ } s; -+ struct cvmx_npi_pci_burst_size_s cn30xx; -+ struct cvmx_npi_pci_burst_size_s cn31xx; -+ struct cvmx_npi_pci_burst_size_s cn38xx; -+ struct cvmx_npi_pci_burst_size_s cn38xxp2; -+ struct cvmx_npi_pci_burst_size_s cn50xx; -+ struct cvmx_npi_pci_burst_size_s cn58xx; -+ struct cvmx_npi_pci_burst_size_s cn58xxp1; -+}; -+ -+union cvmx_npi_pci_int_arb_cfg { -+ uint64_t u64; -+ struct cvmx_npi_pci_int_arb_cfg_s { -+ uint64_t reserved_13_63:51; -+ uint64_t hostmode:1; -+ uint64_t pci_ovr:4; -+ uint64_t reserved_5_7:3; -+ uint64_t en:1; -+ uint64_t park_mod:1; -+ uint64_t park_dev:3; -+ } s; -+ struct cvmx_npi_pci_int_arb_cfg_cn30xx { -+ uint64_t reserved_5_63:59; -+ uint64_t en:1; -+ uint64_t park_mod:1; -+ uint64_t park_dev:3; -+ } cn30xx; -+ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn31xx; -+ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xx; -+ struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xxp2; -+ struct cvmx_npi_pci_int_arb_cfg_s cn50xx; -+ struct cvmx_npi_pci_int_arb_cfg_s cn58xx; -+ struct cvmx_npi_pci_int_arb_cfg_s cn58xxp1; -+}; -+ -+union cvmx_npi_pci_read_cmd { -+ uint64_t u64; -+ struct cvmx_npi_pci_read_cmd_s { -+ uint64_t reserved_11_63:53; -+ uint64_t cmd_size:11; -+ } s; -+ struct cvmx_npi_pci_read_cmd_s cn30xx; -+ struct cvmx_npi_pci_read_cmd_s cn31xx; -+ struct cvmx_npi_pci_read_cmd_s cn38xx; -+ struct cvmx_npi_pci_read_cmd_s cn38xxp2; -+ struct cvmx_npi_pci_read_cmd_s cn50xx; -+ struct cvmx_npi_pci_read_cmd_s cn58xx; -+ struct cvmx_npi_pci_read_cmd_s cn58xxp1; -+}; -+ -+union cvmx_npi_port32_instr_hdr { -+ uint64_t u64; -+ struct cvmx_npi_port32_instr_hdr_s { -+ uint64_t reserved_44_63:20; -+ uint64_t pbp:1; -+ uint64_t rsv_f:5; -+ uint64_t rparmode:2; -+ uint64_t rsv_e:1; -+ uint64_t rskp_len:7; -+ uint64_t rsv_d:6; -+ uint64_t use_ihdr:1; -+ uint64_t rsv_c:5; -+ uint64_t par_mode:2; -+ uint64_t rsv_b:1; -+ uint64_t skp_len:7; -+ uint64_t rsv_a:6; -+ } s; -+ struct cvmx_npi_port32_instr_hdr_s cn30xx; -+ struct cvmx_npi_port32_instr_hdr_s cn31xx; -+ struct cvmx_npi_port32_instr_hdr_s cn38xx; -+ struct cvmx_npi_port32_instr_hdr_s cn38xxp2; -+ struct cvmx_npi_port32_instr_hdr_s cn50xx; -+ struct cvmx_npi_port32_instr_hdr_s cn58xx; -+ struct cvmx_npi_port32_instr_hdr_s cn58xxp1; -+}; -+ -+union cvmx_npi_port33_instr_hdr { -+ uint64_t u64; -+ struct cvmx_npi_port33_instr_hdr_s { -+ uint64_t reserved_44_63:20; -+ uint64_t pbp:1; -+ uint64_t rsv_f:5; -+ uint64_t rparmode:2; -+ uint64_t rsv_e:1; -+ uint64_t rskp_len:7; -+ uint64_t rsv_d:6; -+ uint64_t use_ihdr:1; -+ uint64_t rsv_c:5; -+ uint64_t par_mode:2; -+ uint64_t rsv_b:1; -+ uint64_t skp_len:7; -+ uint64_t rsv_a:6; -+ } s; -+ struct cvmx_npi_port33_instr_hdr_s cn31xx; -+ struct cvmx_npi_port33_instr_hdr_s cn38xx; -+ struct cvmx_npi_port33_instr_hdr_s cn38xxp2; -+ struct cvmx_npi_port33_instr_hdr_s cn50xx; -+ struct cvmx_npi_port33_instr_hdr_s cn58xx; -+ struct cvmx_npi_port33_instr_hdr_s cn58xxp1; -+}; -+ -+union cvmx_npi_port34_instr_hdr { -+ uint64_t u64; -+ struct cvmx_npi_port34_instr_hdr_s { -+ uint64_t reserved_44_63:20; -+ uint64_t pbp:1; -+ uint64_t rsv_f:5; -+ uint64_t rparmode:2; -+ uint64_t rsv_e:1; -+ uint64_t rskp_len:7; -+ uint64_t rsv_d:6; -+ uint64_t use_ihdr:1; -+ uint64_t rsv_c:5; -+ uint64_t par_mode:2; -+ uint64_t rsv_b:1; -+ uint64_t skp_len:7; -+ uint64_t rsv_a:6; -+ } s; -+ struct cvmx_npi_port34_instr_hdr_s cn38xx; -+ struct cvmx_npi_port34_instr_hdr_s cn38xxp2; -+ struct cvmx_npi_port34_instr_hdr_s cn58xx; -+ struct cvmx_npi_port34_instr_hdr_s cn58xxp1; -+}; -+ -+union cvmx_npi_port35_instr_hdr { -+ uint64_t u64; -+ struct cvmx_npi_port35_instr_hdr_s { -+ uint64_t reserved_44_63:20; -+ uint64_t pbp:1; -+ uint64_t rsv_f:5; -+ uint64_t rparmode:2; -+ uint64_t rsv_e:1; -+ uint64_t rskp_len:7; -+ uint64_t rsv_d:6; -+ uint64_t use_ihdr:1; -+ uint64_t rsv_c:5; -+ uint64_t par_mode:2; -+ uint64_t rsv_b:1; -+ uint64_t skp_len:7; -+ uint64_t rsv_a:6; -+ } s; -+ struct cvmx_npi_port35_instr_hdr_s cn38xx; -+ struct cvmx_npi_port35_instr_hdr_s cn38xxp2; -+ struct cvmx_npi_port35_instr_hdr_s cn58xx; -+ struct cvmx_npi_port35_instr_hdr_s cn58xxp1; -+}; -+ -+union cvmx_npi_port_bp_control { -+ uint64_t u64; -+ struct cvmx_npi_port_bp_control_s { -+ uint64_t reserved_8_63:56; -+ uint64_t bp_on:4; -+ uint64_t enb:4; -+ } s; -+ struct cvmx_npi_port_bp_control_s cn30xx; -+ struct cvmx_npi_port_bp_control_s cn31xx; -+ struct cvmx_npi_port_bp_control_s cn38xx; -+ struct cvmx_npi_port_bp_control_s cn38xxp2; -+ struct cvmx_npi_port_bp_control_s cn50xx; -+ struct cvmx_npi_port_bp_control_s cn58xx; -+ struct cvmx_npi_port_bp_control_s cn58xxp1; -+}; -+ -+union cvmx_npi_rsl_int_blocks { -+ uint64_t u64; -+ struct cvmx_npi_rsl_int_blocks_s { -+ uint64_t reserved_32_63:32; -+ uint64_t rint_31:1; -+ uint64_t iob:1; -+ uint64_t reserved_28_29:2; -+ uint64_t rint_27:1; -+ uint64_t rint_26:1; -+ uint64_t rint_25:1; -+ uint64_t rint_24:1; -+ uint64_t asx1:1; -+ uint64_t asx0:1; -+ uint64_t rint_21:1; -+ uint64_t pip:1; -+ uint64_t spx1:1; -+ uint64_t spx0:1; -+ uint64_t lmc:1; -+ uint64_t l2c:1; -+ uint64_t rint_15:1; -+ uint64_t reserved_13_14:2; -+ uint64_t pow:1; -+ uint64_t tim:1; -+ uint64_t pko:1; -+ uint64_t ipd:1; -+ uint64_t rint_8:1; -+ uint64_t zip:1; -+ uint64_t dfa:1; -+ uint64_t fpa:1; -+ uint64_t key:1; -+ uint64_t npi:1; -+ uint64_t gmx1:1; -+ uint64_t gmx0:1; -+ uint64_t mio:1; -+ } s; -+ struct cvmx_npi_rsl_int_blocks_cn30xx { -+ uint64_t reserved_32_63:32; -+ uint64_t rint_31:1; -+ uint64_t iob:1; -+ uint64_t rint_29:1; -+ uint64_t rint_28:1; -+ uint64_t rint_27:1; -+ uint64_t rint_26:1; -+ uint64_t rint_25:1; -+ uint64_t rint_24:1; -+ uint64_t asx1:1; -+ uint64_t asx0:1; -+ uint64_t rint_21:1; -+ uint64_t pip:1; -+ uint64_t spx1:1; -+ uint64_t spx0:1; -+ uint64_t lmc:1; -+ uint64_t l2c:1; -+ uint64_t rint_15:1; -+ uint64_t rint_14:1; -+ uint64_t usb:1; -+ uint64_t pow:1; -+ uint64_t tim:1; -+ uint64_t pko:1; -+ uint64_t ipd:1; -+ uint64_t rint_8:1; -+ uint64_t zip:1; -+ uint64_t dfa:1; -+ uint64_t fpa:1; -+ uint64_t key:1; -+ uint64_t npi:1; -+ uint64_t gmx1:1; -+ uint64_t gmx0:1; -+ uint64_t mio:1; -+ } cn30xx; -+ struct cvmx_npi_rsl_int_blocks_cn30xx cn31xx; -+ struct cvmx_npi_rsl_int_blocks_cn38xx { -+ uint64_t reserved_32_63:32; -+ uint64_t rint_31:1; -+ uint64_t iob:1; -+ uint64_t rint_29:1; -+ uint64_t rint_28:1; -+ uint64_t rint_27:1; -+ uint64_t rint_26:1; -+ uint64_t rint_25:1; -+ uint64_t rint_24:1; -+ uint64_t asx1:1; -+ uint64_t asx0:1; -+ uint64_t rint_21:1; -+ uint64_t pip:1; -+ uint64_t spx1:1; -+ uint64_t spx0:1; -+ uint64_t lmc:1; -+ uint64_t l2c:1; -+ uint64_t rint_15:1; -+ uint64_t rint_14:1; -+ uint64_t rint_13:1; -+ uint64_t pow:1; -+ uint64_t tim:1; -+ uint64_t pko:1; -+ uint64_t ipd:1; -+ uint64_t rint_8:1; -+ uint64_t zip:1; -+ uint64_t dfa:1; -+ uint64_t fpa:1; -+ uint64_t key:1; -+ uint64_t npi:1; -+ uint64_t gmx1:1; -+ uint64_t gmx0:1; -+ uint64_t mio:1; -+ } cn38xx; -+ struct cvmx_npi_rsl_int_blocks_cn38xx cn38xxp2; -+ struct cvmx_npi_rsl_int_blocks_cn50xx { -+ uint64_t reserved_31_63:33; -+ uint64_t iob:1; -+ uint64_t lmc1:1; -+ uint64_t agl:1; -+ uint64_t reserved_24_27:4; -+ uint64_t asx1:1; -+ uint64_t asx0:1; -+ uint64_t reserved_21_21:1; -+ uint64_t pip:1; -+ uint64_t spx1:1; -+ uint64_t spx0:1; -+ uint64_t lmc:1; -+ uint64_t l2c:1; -+ uint64_t reserved_15_15:1; -+ uint64_t rad:1; -+ uint64_t usb:1; -+ uint64_t pow:1; -+ uint64_t tim:1; -+ uint64_t pko:1; -+ uint64_t ipd:1; -+ uint64_t reserved_8_8:1; -+ uint64_t zip:1; -+ uint64_t dfa:1; -+ uint64_t fpa:1; -+ uint64_t key:1; -+ uint64_t npi:1; -+ uint64_t gmx1:1; -+ uint64_t gmx0:1; -+ uint64_t mio:1; -+ } cn50xx; -+ struct cvmx_npi_rsl_int_blocks_cn38xx cn58xx; -+ struct cvmx_npi_rsl_int_blocks_cn38xx cn58xxp1; -+}; -+ -+union cvmx_npi_size_inputx { -+ uint64_t u64; -+ struct cvmx_npi_size_inputx_s { -+ uint64_t reserved_32_63:32; -+ uint64_t size:32; -+ } s; -+ struct cvmx_npi_size_inputx_s cn30xx; -+ struct cvmx_npi_size_inputx_s cn31xx; -+ struct cvmx_npi_size_inputx_s cn38xx; -+ struct cvmx_npi_size_inputx_s cn38xxp2; -+ struct cvmx_npi_size_inputx_s cn50xx; -+ struct cvmx_npi_size_inputx_s cn58xx; -+ struct cvmx_npi_size_inputx_s cn58xxp1; -+}; -+ -+union cvmx_npi_win_read_to { -+ uint64_t u64; -+ struct cvmx_npi_win_read_to_s { -+ uint64_t reserved_32_63:32; -+ uint64_t time:32; -+ } s; -+ struct cvmx_npi_win_read_to_s cn30xx; -+ struct cvmx_npi_win_read_to_s cn31xx; -+ struct cvmx_npi_win_read_to_s cn38xx; -+ struct cvmx_npi_win_read_to_s cn38xxp2; -+ struct cvmx_npi_win_read_to_s cn50xx; -+ struct cvmx_npi_win_read_to_s cn58xx; -+ struct cvmx_npi_win_read_to_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-pci-defs.h -@@ -0,0 +1,1645 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PCI_DEFS_H__ -+#define __CVMX_PCI_DEFS_H__ -+ -+#define CVMX_PCI_BAR1_INDEXX(offset) \ -+ (0x0000000000000100ull + (((offset) & 31) * 4)) -+#define CVMX_PCI_BIST_REG \ -+ (0x00000000000001C0ull) -+#define CVMX_PCI_CFG00 \ -+ (0x0000000000000000ull) -+#define CVMX_PCI_CFG01 \ -+ (0x0000000000000004ull) -+#define CVMX_PCI_CFG02 \ -+ (0x0000000000000008ull) -+#define CVMX_PCI_CFG03 \ -+ (0x000000000000000Cull) -+#define CVMX_PCI_CFG04 \ -+ (0x0000000000000010ull) -+#define CVMX_PCI_CFG05 \ -+ (0x0000000000000014ull) -+#define CVMX_PCI_CFG06 \ -+ (0x0000000000000018ull) -+#define CVMX_PCI_CFG07 \ -+ (0x000000000000001Cull) -+#define CVMX_PCI_CFG08 \ -+ (0x0000000000000020ull) -+#define CVMX_PCI_CFG09 \ -+ (0x0000000000000024ull) -+#define CVMX_PCI_CFG10 \ -+ (0x0000000000000028ull) -+#define CVMX_PCI_CFG11 \ -+ (0x000000000000002Cull) -+#define CVMX_PCI_CFG12 \ -+ (0x0000000000000030ull) -+#define CVMX_PCI_CFG13 \ -+ (0x0000000000000034ull) -+#define CVMX_PCI_CFG15 \ -+ (0x000000000000003Cull) -+#define CVMX_PCI_CFG16 \ -+ (0x0000000000000040ull) -+#define CVMX_PCI_CFG17 \ -+ (0x0000000000000044ull) -+#define CVMX_PCI_CFG18 \ -+ (0x0000000000000048ull) -+#define CVMX_PCI_CFG19 \ -+ (0x000000000000004Cull) -+#define CVMX_PCI_CFG20 \ -+ (0x0000000000000050ull) -+#define CVMX_PCI_CFG21 \ -+ (0x0000000000000054ull) -+#define CVMX_PCI_CFG22 \ -+ (0x0000000000000058ull) -+#define CVMX_PCI_CFG56 \ -+ (0x00000000000000E0ull) -+#define CVMX_PCI_CFG57 \ -+ (0x00000000000000E4ull) -+#define CVMX_PCI_CFG58 \ -+ (0x00000000000000E8ull) -+#define CVMX_PCI_CFG59 \ -+ (0x00000000000000ECull) -+#define CVMX_PCI_CFG60 \ -+ (0x00000000000000F0ull) -+#define CVMX_PCI_CFG61 \ -+ (0x00000000000000F4ull) -+#define CVMX_PCI_CFG62 \ -+ (0x00000000000000F8ull) -+#define CVMX_PCI_CFG63 \ -+ (0x00000000000000FCull) -+#define CVMX_PCI_CNT_REG \ -+ (0x00000000000001B8ull) -+#define CVMX_PCI_CTL_STATUS_2 \ -+ (0x000000000000018Cull) -+#define CVMX_PCI_DBELL_0 \ -+ (0x0000000000000080ull) -+#define CVMX_PCI_DBELL_1 \ -+ (0x0000000000000088ull) -+#define CVMX_PCI_DBELL_2 \ -+ (0x0000000000000090ull) -+#define CVMX_PCI_DBELL_3 \ -+ (0x0000000000000098ull) -+#define CVMX_PCI_DBELL_X(offset) \ -+ (0x0000000000000080ull + (((offset) & 3) * 8)) -+#define CVMX_PCI_DMA_CNT0 \ -+ (0x00000000000000A0ull) -+#define CVMX_PCI_DMA_CNT1 \ -+ (0x00000000000000A8ull) -+#define CVMX_PCI_DMA_CNTX(offset) \ -+ (0x00000000000000A0ull + (((offset) & 1) * 8)) -+#define CVMX_PCI_DMA_INT_LEV0 \ -+ (0x00000000000000A4ull) -+#define CVMX_PCI_DMA_INT_LEV1 \ -+ (0x00000000000000ACull) -+#define CVMX_PCI_DMA_INT_LEVX(offset) \ -+ (0x00000000000000A4ull + (((offset) & 1) * 8)) -+#define CVMX_PCI_DMA_TIME0 \ -+ (0x00000000000000B0ull) -+#define CVMX_PCI_DMA_TIME1 \ -+ (0x00000000000000B4ull) -+#define CVMX_PCI_DMA_TIMEX(offset) \ -+ (0x00000000000000B0ull + (((offset) & 1) * 4)) -+#define CVMX_PCI_INSTR_COUNT0 \ -+ (0x0000000000000084ull) -+#define CVMX_PCI_INSTR_COUNT1 \ -+ (0x000000000000008Cull) -+#define CVMX_PCI_INSTR_COUNT2 \ -+ (0x0000000000000094ull) -+#define CVMX_PCI_INSTR_COUNT3 \ -+ (0x000000000000009Cull) -+#define CVMX_PCI_INSTR_COUNTX(offset) \ -+ (0x0000000000000084ull + (((offset) & 3) * 8)) -+#define CVMX_PCI_INT_ENB \ -+ (0x0000000000000038ull) -+#define CVMX_PCI_INT_ENB2 \ -+ (0x00000000000001A0ull) -+#define CVMX_PCI_INT_SUM \ -+ (0x0000000000000030ull) -+#define CVMX_PCI_INT_SUM2 \ -+ (0x0000000000000198ull) -+#define CVMX_PCI_MSI_RCV \ -+ (0x00000000000000F0ull) -+#define CVMX_PCI_PKTS_SENT0 \ -+ (0x0000000000000040ull) -+#define CVMX_PCI_PKTS_SENT1 \ -+ (0x0000000000000050ull) -+#define CVMX_PCI_PKTS_SENT2 \ -+ (0x0000000000000060ull) -+#define CVMX_PCI_PKTS_SENT3 \ -+ (0x0000000000000070ull) -+#define CVMX_PCI_PKTS_SENTX(offset) \ -+ (0x0000000000000040ull + (((offset) & 3) * 16)) -+#define CVMX_PCI_PKTS_SENT_INT_LEV0 \ -+ (0x0000000000000048ull) -+#define CVMX_PCI_PKTS_SENT_INT_LEV1 \ -+ (0x0000000000000058ull) -+#define CVMX_PCI_PKTS_SENT_INT_LEV2 \ -+ (0x0000000000000068ull) -+#define CVMX_PCI_PKTS_SENT_INT_LEV3 \ -+ (0x0000000000000078ull) -+#define CVMX_PCI_PKTS_SENT_INT_LEVX(offset) \ -+ (0x0000000000000048ull + (((offset) & 3) * 16)) -+#define CVMX_PCI_PKTS_SENT_TIME0 \ -+ (0x000000000000004Cull) -+#define CVMX_PCI_PKTS_SENT_TIME1 \ -+ (0x000000000000005Cull) -+#define CVMX_PCI_PKTS_SENT_TIME2 \ -+ (0x000000000000006Cull) -+#define CVMX_PCI_PKTS_SENT_TIME3 \ -+ (0x000000000000007Cull) -+#define CVMX_PCI_PKTS_SENT_TIMEX(offset) \ -+ (0x000000000000004Cull + (((offset) & 3) * 16)) -+#define CVMX_PCI_PKT_CREDITS0 \ -+ (0x0000000000000044ull) -+#define CVMX_PCI_PKT_CREDITS1 \ -+ (0x0000000000000054ull) -+#define CVMX_PCI_PKT_CREDITS2 \ -+ (0x0000000000000064ull) -+#define CVMX_PCI_PKT_CREDITS3 \ -+ (0x0000000000000074ull) -+#define CVMX_PCI_PKT_CREDITSX(offset) \ -+ (0x0000000000000044ull + (((offset) & 3) * 16)) -+#define CVMX_PCI_READ_CMD_6 \ -+ (0x0000000000000180ull) -+#define CVMX_PCI_READ_CMD_C \ -+ (0x0000000000000184ull) -+#define CVMX_PCI_READ_CMD_E \ -+ (0x0000000000000188ull) -+#define CVMX_PCI_READ_TIMEOUT \ -+ CVMX_ADD_IO_SEG(0x00011F00000000B0ull) -+#define CVMX_PCI_SCM_REG \ -+ (0x00000000000001A8ull) -+#define CVMX_PCI_TSR_REG \ -+ (0x00000000000001B0ull) -+#define CVMX_PCI_WIN_RD_ADDR \ -+ (0x0000000000000008ull) -+#define CVMX_PCI_WIN_RD_DATA \ -+ (0x0000000000000020ull) -+#define CVMX_PCI_WIN_WR_ADDR \ -+ (0x0000000000000000ull) -+#define CVMX_PCI_WIN_WR_DATA \ -+ (0x0000000000000010ull) -+#define CVMX_PCI_WIN_WR_MASK \ -+ (0x0000000000000018ull) -+ -+union cvmx_pci_bar1_indexx { -+ uint32_t u32; -+ struct cvmx_pci_bar1_indexx_s { -+ uint32_t reserved_18_31:14; -+ uint32_t addr_idx:14; -+ uint32_t ca:1; -+ uint32_t end_swp:2; -+ uint32_t addr_v:1; -+ } s; -+ struct cvmx_pci_bar1_indexx_s cn30xx; -+ struct cvmx_pci_bar1_indexx_s cn31xx; -+ struct cvmx_pci_bar1_indexx_s cn38xx; -+ struct cvmx_pci_bar1_indexx_s cn38xxp2; -+ struct cvmx_pci_bar1_indexx_s cn50xx; -+ struct cvmx_pci_bar1_indexx_s cn58xx; -+ struct cvmx_pci_bar1_indexx_s cn58xxp1; -+}; -+ -+union cvmx_pci_bist_reg { -+ uint64_t u64; -+ struct cvmx_pci_bist_reg_s { -+ uint64_t reserved_10_63:54; -+ uint64_t rsp_bs:1; -+ uint64_t dma0_bs:1; -+ uint64_t cmd0_bs:1; -+ uint64_t cmd_bs:1; -+ uint64_t csr2p_bs:1; -+ uint64_t csrr_bs:1; -+ uint64_t rsp2p_bs:1; -+ uint64_t csr2n_bs:1; -+ uint64_t dat2n_bs:1; -+ uint64_t dbg2n_bs:1; -+ } s; -+ struct cvmx_pci_bist_reg_s cn50xx; -+}; -+ -+union cvmx_pci_cfg00 { -+ uint32_t u32; -+ struct cvmx_pci_cfg00_s { -+ uint32_t devid:16; -+ uint32_t vendid:16; -+ } s; -+ struct cvmx_pci_cfg00_s cn30xx; -+ struct cvmx_pci_cfg00_s cn31xx; -+ struct cvmx_pci_cfg00_s cn38xx; -+ struct cvmx_pci_cfg00_s cn38xxp2; -+ struct cvmx_pci_cfg00_s cn50xx; -+ struct cvmx_pci_cfg00_s cn58xx; -+ struct cvmx_pci_cfg00_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg01 { -+ uint32_t u32; -+ struct cvmx_pci_cfg01_s { -+ uint32_t dpe:1; -+ uint32_t sse:1; -+ uint32_t rma:1; -+ uint32_t rta:1; -+ uint32_t sta:1; -+ uint32_t devt:2; -+ uint32_t mdpe:1; -+ uint32_t fbb:1; -+ uint32_t reserved_22_22:1; -+ uint32_t m66:1; -+ uint32_t cle:1; -+ uint32_t i_stat:1; -+ uint32_t reserved_11_18:8; -+ uint32_t i_dis:1; -+ uint32_t fbbe:1; -+ uint32_t see:1; -+ uint32_t ads:1; -+ uint32_t pee:1; -+ uint32_t vps:1; -+ uint32_t mwice:1; -+ uint32_t scse:1; -+ uint32_t me:1; -+ uint32_t msae:1; -+ uint32_t isae:1; -+ } s; -+ struct cvmx_pci_cfg01_s cn30xx; -+ struct cvmx_pci_cfg01_s cn31xx; -+ struct cvmx_pci_cfg01_s cn38xx; -+ struct cvmx_pci_cfg01_s cn38xxp2; -+ struct cvmx_pci_cfg01_s cn50xx; -+ struct cvmx_pci_cfg01_s cn58xx; -+ struct cvmx_pci_cfg01_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg02 { -+ uint32_t u32; -+ struct cvmx_pci_cfg02_s { -+ uint32_t cc:24; -+ uint32_t rid:8; -+ } s; -+ struct cvmx_pci_cfg02_s cn30xx; -+ struct cvmx_pci_cfg02_s cn31xx; -+ struct cvmx_pci_cfg02_s cn38xx; -+ struct cvmx_pci_cfg02_s cn38xxp2; -+ struct cvmx_pci_cfg02_s cn50xx; -+ struct cvmx_pci_cfg02_s cn58xx; -+ struct cvmx_pci_cfg02_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg03 { -+ uint32_t u32; -+ struct cvmx_pci_cfg03_s { -+ uint32_t bcap:1; -+ uint32_t brb:1; -+ uint32_t reserved_28_29:2; -+ uint32_t bcod:4; -+ uint32_t ht:8; -+ uint32_t lt:8; -+ uint32_t cls:8; -+ } s; -+ struct cvmx_pci_cfg03_s cn30xx; -+ struct cvmx_pci_cfg03_s cn31xx; -+ struct cvmx_pci_cfg03_s cn38xx; -+ struct cvmx_pci_cfg03_s cn38xxp2; -+ struct cvmx_pci_cfg03_s cn50xx; -+ struct cvmx_pci_cfg03_s cn58xx; -+ struct cvmx_pci_cfg03_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg04 { -+ uint32_t u32; -+ struct cvmx_pci_cfg04_s { -+ uint32_t lbase:20; -+ uint32_t lbasez:8; -+ uint32_t pf:1; -+ uint32_t typ:2; -+ uint32_t mspc:1; -+ } s; -+ struct cvmx_pci_cfg04_s cn30xx; -+ struct cvmx_pci_cfg04_s cn31xx; -+ struct cvmx_pci_cfg04_s cn38xx; -+ struct cvmx_pci_cfg04_s cn38xxp2; -+ struct cvmx_pci_cfg04_s cn50xx; -+ struct cvmx_pci_cfg04_s cn58xx; -+ struct cvmx_pci_cfg04_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg05 { -+ uint32_t u32; -+ struct cvmx_pci_cfg05_s { -+ uint32_t hbase:32; -+ } s; -+ struct cvmx_pci_cfg05_s cn30xx; -+ struct cvmx_pci_cfg05_s cn31xx; -+ struct cvmx_pci_cfg05_s cn38xx; -+ struct cvmx_pci_cfg05_s cn38xxp2; -+ struct cvmx_pci_cfg05_s cn50xx; -+ struct cvmx_pci_cfg05_s cn58xx; -+ struct cvmx_pci_cfg05_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg06 { -+ uint32_t u32; -+ struct cvmx_pci_cfg06_s { -+ uint32_t lbase:5; -+ uint32_t lbasez:23; -+ uint32_t pf:1; -+ uint32_t typ:2; -+ uint32_t mspc:1; -+ } s; -+ struct cvmx_pci_cfg06_s cn30xx; -+ struct cvmx_pci_cfg06_s cn31xx; -+ struct cvmx_pci_cfg06_s cn38xx; -+ struct cvmx_pci_cfg06_s cn38xxp2; -+ struct cvmx_pci_cfg06_s cn50xx; -+ struct cvmx_pci_cfg06_s cn58xx; -+ struct cvmx_pci_cfg06_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg07 { -+ uint32_t u32; -+ struct cvmx_pci_cfg07_s { -+ uint32_t hbase:32; -+ } s; -+ struct cvmx_pci_cfg07_s cn30xx; -+ struct cvmx_pci_cfg07_s cn31xx; -+ struct cvmx_pci_cfg07_s cn38xx; -+ struct cvmx_pci_cfg07_s cn38xxp2; -+ struct cvmx_pci_cfg07_s cn50xx; -+ struct cvmx_pci_cfg07_s cn58xx; -+ struct cvmx_pci_cfg07_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg08 { -+ uint32_t u32; -+ struct cvmx_pci_cfg08_s { -+ uint32_t lbasez:28; -+ uint32_t pf:1; -+ uint32_t typ:2; -+ uint32_t mspc:1; -+ } s; -+ struct cvmx_pci_cfg08_s cn30xx; -+ struct cvmx_pci_cfg08_s cn31xx; -+ struct cvmx_pci_cfg08_s cn38xx; -+ struct cvmx_pci_cfg08_s cn38xxp2; -+ struct cvmx_pci_cfg08_s cn50xx; -+ struct cvmx_pci_cfg08_s cn58xx; -+ struct cvmx_pci_cfg08_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg09 { -+ uint32_t u32; -+ struct cvmx_pci_cfg09_s { -+ uint32_t hbase:25; -+ uint32_t hbasez:7; -+ } s; -+ struct cvmx_pci_cfg09_s cn30xx; -+ struct cvmx_pci_cfg09_s cn31xx; -+ struct cvmx_pci_cfg09_s cn38xx; -+ struct cvmx_pci_cfg09_s cn38xxp2; -+ struct cvmx_pci_cfg09_s cn50xx; -+ struct cvmx_pci_cfg09_s cn58xx; -+ struct cvmx_pci_cfg09_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg10 { -+ uint32_t u32; -+ struct cvmx_pci_cfg10_s { -+ uint32_t cisp:32; -+ } s; -+ struct cvmx_pci_cfg10_s cn30xx; -+ struct cvmx_pci_cfg10_s cn31xx; -+ struct cvmx_pci_cfg10_s cn38xx; -+ struct cvmx_pci_cfg10_s cn38xxp2; -+ struct cvmx_pci_cfg10_s cn50xx; -+ struct cvmx_pci_cfg10_s cn58xx; -+ struct cvmx_pci_cfg10_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg11 { -+ uint32_t u32; -+ struct cvmx_pci_cfg11_s { -+ uint32_t ssid:16; -+ uint32_t ssvid:16; -+ } s; -+ struct cvmx_pci_cfg11_s cn30xx; -+ struct cvmx_pci_cfg11_s cn31xx; -+ struct cvmx_pci_cfg11_s cn38xx; -+ struct cvmx_pci_cfg11_s cn38xxp2; -+ struct cvmx_pci_cfg11_s cn50xx; -+ struct cvmx_pci_cfg11_s cn58xx; -+ struct cvmx_pci_cfg11_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg12 { -+ uint32_t u32; -+ struct cvmx_pci_cfg12_s { -+ uint32_t erbar:16; -+ uint32_t erbarz:5; -+ uint32_t reserved_1_10:10; -+ uint32_t erbar_en:1; -+ } s; -+ struct cvmx_pci_cfg12_s cn30xx; -+ struct cvmx_pci_cfg12_s cn31xx; -+ struct cvmx_pci_cfg12_s cn38xx; -+ struct cvmx_pci_cfg12_s cn38xxp2; -+ struct cvmx_pci_cfg12_s cn50xx; -+ struct cvmx_pci_cfg12_s cn58xx; -+ struct cvmx_pci_cfg12_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg13 { -+ uint32_t u32; -+ struct cvmx_pci_cfg13_s { -+ uint32_t reserved_8_31:24; -+ uint32_t cp:8; -+ } s; -+ struct cvmx_pci_cfg13_s cn30xx; -+ struct cvmx_pci_cfg13_s cn31xx; -+ struct cvmx_pci_cfg13_s cn38xx; -+ struct cvmx_pci_cfg13_s cn38xxp2; -+ struct cvmx_pci_cfg13_s cn50xx; -+ struct cvmx_pci_cfg13_s cn58xx; -+ struct cvmx_pci_cfg13_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg15 { -+ uint32_t u32; -+ struct cvmx_pci_cfg15_s { -+ uint32_t ml:8; -+ uint32_t mg:8; -+ uint32_t inta:8; -+ uint32_t il:8; -+ } s; -+ struct cvmx_pci_cfg15_s cn30xx; -+ struct cvmx_pci_cfg15_s cn31xx; -+ struct cvmx_pci_cfg15_s cn38xx; -+ struct cvmx_pci_cfg15_s cn38xxp2; -+ struct cvmx_pci_cfg15_s cn50xx; -+ struct cvmx_pci_cfg15_s cn58xx; -+ struct cvmx_pci_cfg15_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg16 { -+ uint32_t u32; -+ struct cvmx_pci_cfg16_s { -+ uint32_t trdnpr:1; -+ uint32_t trdard:1; -+ uint32_t rdsati:1; -+ uint32_t trdrs:1; -+ uint32_t trtae:1; -+ uint32_t twsei:1; -+ uint32_t twsen:1; -+ uint32_t twtae:1; -+ uint32_t tmae:1; -+ uint32_t tslte:3; -+ uint32_t tilt:4; -+ uint32_t pbe:12; -+ uint32_t dppmr:1; -+ uint32_t reserved_2_2:1; -+ uint32_t tswc:1; -+ uint32_t mltd:1; -+ } s; -+ struct cvmx_pci_cfg16_s cn30xx; -+ struct cvmx_pci_cfg16_s cn31xx; -+ struct cvmx_pci_cfg16_s cn38xx; -+ struct cvmx_pci_cfg16_s cn38xxp2; -+ struct cvmx_pci_cfg16_s cn50xx; -+ struct cvmx_pci_cfg16_s cn58xx; -+ struct cvmx_pci_cfg16_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg17 { -+ uint32_t u32; -+ struct cvmx_pci_cfg17_s { -+ uint32_t tscme:32; -+ } s; -+ struct cvmx_pci_cfg17_s cn30xx; -+ struct cvmx_pci_cfg17_s cn31xx; -+ struct cvmx_pci_cfg17_s cn38xx; -+ struct cvmx_pci_cfg17_s cn38xxp2; -+ struct cvmx_pci_cfg17_s cn50xx; -+ struct cvmx_pci_cfg17_s cn58xx; -+ struct cvmx_pci_cfg17_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg18 { -+ uint32_t u32; -+ struct cvmx_pci_cfg18_s { -+ uint32_t tdsrps:32; -+ } s; -+ struct cvmx_pci_cfg18_s cn30xx; -+ struct cvmx_pci_cfg18_s cn31xx; -+ struct cvmx_pci_cfg18_s cn38xx; -+ struct cvmx_pci_cfg18_s cn38xxp2; -+ struct cvmx_pci_cfg18_s cn50xx; -+ struct cvmx_pci_cfg18_s cn58xx; -+ struct cvmx_pci_cfg18_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg19 { -+ uint32_t u32; -+ struct cvmx_pci_cfg19_s { -+ uint32_t mrbcm:1; -+ uint32_t mrbci:1; -+ uint32_t mdwe:1; -+ uint32_t mdre:1; -+ uint32_t mdrimc:1; -+ uint32_t mdrrmc:3; -+ uint32_t tmes:8; -+ uint32_t teci:1; -+ uint32_t tmei:1; -+ uint32_t tmse:1; -+ uint32_t tmdpes:1; -+ uint32_t tmapes:1; -+ uint32_t reserved_9_10:2; -+ uint32_t tibcd:1; -+ uint32_t tibde:1; -+ uint32_t reserved_6_6:1; -+ uint32_t tidomc:1; -+ uint32_t tdomc:5; -+ } s; -+ struct cvmx_pci_cfg19_s cn30xx; -+ struct cvmx_pci_cfg19_s cn31xx; -+ struct cvmx_pci_cfg19_s cn38xx; -+ struct cvmx_pci_cfg19_s cn38xxp2; -+ struct cvmx_pci_cfg19_s cn50xx; -+ struct cvmx_pci_cfg19_s cn58xx; -+ struct cvmx_pci_cfg19_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg20 { -+ uint32_t u32; -+ struct cvmx_pci_cfg20_s { -+ uint32_t mdsp:32; -+ } s; -+ struct cvmx_pci_cfg20_s cn30xx; -+ struct cvmx_pci_cfg20_s cn31xx; -+ struct cvmx_pci_cfg20_s cn38xx; -+ struct cvmx_pci_cfg20_s cn38xxp2; -+ struct cvmx_pci_cfg20_s cn50xx; -+ struct cvmx_pci_cfg20_s cn58xx; -+ struct cvmx_pci_cfg20_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg21 { -+ uint32_t u32; -+ struct cvmx_pci_cfg21_s { -+ uint32_t scmre:32; -+ } s; -+ struct cvmx_pci_cfg21_s cn30xx; -+ struct cvmx_pci_cfg21_s cn31xx; -+ struct cvmx_pci_cfg21_s cn38xx; -+ struct cvmx_pci_cfg21_s cn38xxp2; -+ struct cvmx_pci_cfg21_s cn50xx; -+ struct cvmx_pci_cfg21_s cn58xx; -+ struct cvmx_pci_cfg21_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg22 { -+ uint32_t u32; -+ struct cvmx_pci_cfg22_s { -+ uint32_t mac:7; -+ uint32_t reserved_19_24:6; -+ uint32_t flush:1; -+ uint32_t mra:1; -+ uint32_t mtta:1; -+ uint32_t mrv:8; -+ uint32_t mttv:8; -+ } s; -+ struct cvmx_pci_cfg22_s cn30xx; -+ struct cvmx_pci_cfg22_s cn31xx; -+ struct cvmx_pci_cfg22_s cn38xx; -+ struct cvmx_pci_cfg22_s cn38xxp2; -+ struct cvmx_pci_cfg22_s cn50xx; -+ struct cvmx_pci_cfg22_s cn58xx; -+ struct cvmx_pci_cfg22_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg56 { -+ uint32_t u32; -+ struct cvmx_pci_cfg56_s { -+ uint32_t reserved_23_31:9; -+ uint32_t most:3; -+ uint32_t mmbc:2; -+ uint32_t roe:1; -+ uint32_t dpere:1; -+ uint32_t ncp:8; -+ uint32_t pxcid:8; -+ } s; -+ struct cvmx_pci_cfg56_s cn30xx; -+ struct cvmx_pci_cfg56_s cn31xx; -+ struct cvmx_pci_cfg56_s cn38xx; -+ struct cvmx_pci_cfg56_s cn38xxp2; -+ struct cvmx_pci_cfg56_s cn50xx; -+ struct cvmx_pci_cfg56_s cn58xx; -+ struct cvmx_pci_cfg56_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg57 { -+ uint32_t u32; -+ struct cvmx_pci_cfg57_s { -+ uint32_t reserved_30_31:2; -+ uint32_t scemr:1; -+ uint32_t mcrsd:3; -+ uint32_t mostd:3; -+ uint32_t mmrbcd:2; -+ uint32_t dc:1; -+ uint32_t usc:1; -+ uint32_t scd:1; -+ uint32_t m133:1; -+ uint32_t w64:1; -+ uint32_t bn:8; -+ uint32_t dn:5; -+ uint32_t fn:3; -+ } s; -+ struct cvmx_pci_cfg57_s cn30xx; -+ struct cvmx_pci_cfg57_s cn31xx; -+ struct cvmx_pci_cfg57_s cn38xx; -+ struct cvmx_pci_cfg57_s cn38xxp2; -+ struct cvmx_pci_cfg57_s cn50xx; -+ struct cvmx_pci_cfg57_s cn58xx; -+ struct cvmx_pci_cfg57_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg58 { -+ uint32_t u32; -+ struct cvmx_pci_cfg58_s { -+ uint32_t pmes:5; -+ uint32_t d2s:1; -+ uint32_t d1s:1; -+ uint32_t auxc:3; -+ uint32_t dsi:1; -+ uint32_t reserved_20_20:1; -+ uint32_t pmec:1; -+ uint32_t pcimiv:3; -+ uint32_t ncp:8; -+ uint32_t pmcid:8; -+ } s; -+ struct cvmx_pci_cfg58_s cn30xx; -+ struct cvmx_pci_cfg58_s cn31xx; -+ struct cvmx_pci_cfg58_s cn38xx; -+ struct cvmx_pci_cfg58_s cn38xxp2; -+ struct cvmx_pci_cfg58_s cn50xx; -+ struct cvmx_pci_cfg58_s cn58xx; -+ struct cvmx_pci_cfg58_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg59 { -+ uint32_t u32; -+ struct cvmx_pci_cfg59_s { -+ uint32_t pmdia:8; -+ uint32_t bpccen:1; -+ uint32_t bd3h:1; -+ uint32_t reserved_16_21:6; -+ uint32_t pmess:1; -+ uint32_t pmedsia:2; -+ uint32_t pmds:4; -+ uint32_t pmeens:1; -+ uint32_t reserved_2_7:6; -+ uint32_t ps:2; -+ } s; -+ struct cvmx_pci_cfg59_s cn30xx; -+ struct cvmx_pci_cfg59_s cn31xx; -+ struct cvmx_pci_cfg59_s cn38xx; -+ struct cvmx_pci_cfg59_s cn38xxp2; -+ struct cvmx_pci_cfg59_s cn50xx; -+ struct cvmx_pci_cfg59_s cn58xx; -+ struct cvmx_pci_cfg59_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg60 { -+ uint32_t u32; -+ struct cvmx_pci_cfg60_s { -+ uint32_t reserved_24_31:8; -+ uint32_t m64:1; -+ uint32_t mme:3; -+ uint32_t mmc:3; -+ uint32_t msien:1; -+ uint32_t ncp:8; -+ uint32_t msicid:8; -+ } s; -+ struct cvmx_pci_cfg60_s cn30xx; -+ struct cvmx_pci_cfg60_s cn31xx; -+ struct cvmx_pci_cfg60_s cn38xx; -+ struct cvmx_pci_cfg60_s cn38xxp2; -+ struct cvmx_pci_cfg60_s cn50xx; -+ struct cvmx_pci_cfg60_s cn58xx; -+ struct cvmx_pci_cfg60_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg61 { -+ uint32_t u32; -+ struct cvmx_pci_cfg61_s { -+ uint32_t msi31t2:30; -+ uint32_t reserved_0_1:2; -+ } s; -+ struct cvmx_pci_cfg61_s cn30xx; -+ struct cvmx_pci_cfg61_s cn31xx; -+ struct cvmx_pci_cfg61_s cn38xx; -+ struct cvmx_pci_cfg61_s cn38xxp2; -+ struct cvmx_pci_cfg61_s cn50xx; -+ struct cvmx_pci_cfg61_s cn58xx; -+ struct cvmx_pci_cfg61_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg62 { -+ uint32_t u32; -+ struct cvmx_pci_cfg62_s { -+ uint32_t msi:32; -+ } s; -+ struct cvmx_pci_cfg62_s cn30xx; -+ struct cvmx_pci_cfg62_s cn31xx; -+ struct cvmx_pci_cfg62_s cn38xx; -+ struct cvmx_pci_cfg62_s cn38xxp2; -+ struct cvmx_pci_cfg62_s cn50xx; -+ struct cvmx_pci_cfg62_s cn58xx; -+ struct cvmx_pci_cfg62_s cn58xxp1; -+}; -+ -+union cvmx_pci_cfg63 { -+ uint32_t u32; -+ struct cvmx_pci_cfg63_s { -+ uint32_t reserved_16_31:16; -+ uint32_t msimd:16; -+ } s; -+ struct cvmx_pci_cfg63_s cn30xx; -+ struct cvmx_pci_cfg63_s cn31xx; -+ struct cvmx_pci_cfg63_s cn38xx; -+ struct cvmx_pci_cfg63_s cn38xxp2; -+ struct cvmx_pci_cfg63_s cn50xx; -+ struct cvmx_pci_cfg63_s cn58xx; -+ struct cvmx_pci_cfg63_s cn58xxp1; -+}; -+ -+union cvmx_pci_cnt_reg { -+ uint64_t u64; -+ struct cvmx_pci_cnt_reg_s { -+ uint64_t reserved_38_63:26; -+ uint64_t hm_pcix:1; -+ uint64_t hm_speed:2; -+ uint64_t ap_pcix:1; -+ uint64_t ap_speed:2; -+ uint64_t pcicnt:32; -+ } s; -+ struct cvmx_pci_cnt_reg_s cn50xx; -+ struct cvmx_pci_cnt_reg_s cn58xx; -+ struct cvmx_pci_cnt_reg_s cn58xxp1; -+}; -+ -+union cvmx_pci_ctl_status_2 { -+ uint32_t u32; -+ struct cvmx_pci_ctl_status_2_s { -+ uint32_t reserved_29_31:3; -+ uint32_t bb1_hole:3; -+ uint32_t bb1_siz:1; -+ uint32_t bb_ca:1; -+ uint32_t bb_es:2; -+ uint32_t bb1:1; -+ uint32_t bb0:1; -+ uint32_t erst_n:1; -+ uint32_t bar2pres:1; -+ uint32_t scmtyp:1; -+ uint32_t scm:1; -+ uint32_t en_wfilt:1; -+ uint32_t reserved_14_14:1; -+ uint32_t ap_pcix:1; -+ uint32_t ap_64ad:1; -+ uint32_t b12_bist:1; -+ uint32_t pmo_amod:1; -+ uint32_t pmo_fpc:3; -+ uint32_t tsr_hwm:3; -+ uint32_t bar2_enb:1; -+ uint32_t bar2_esx:2; -+ uint32_t bar2_cax:1; -+ } s; -+ struct cvmx_pci_ctl_status_2_s cn30xx; -+ struct cvmx_pci_ctl_status_2_cn31xx { -+ uint32_t reserved_20_31:12; -+ uint32_t erst_n:1; -+ uint32_t bar2pres:1; -+ uint32_t scmtyp:1; -+ uint32_t scm:1; -+ uint32_t en_wfilt:1; -+ uint32_t reserved_14_14:1; -+ uint32_t ap_pcix:1; -+ uint32_t ap_64ad:1; -+ uint32_t b12_bist:1; -+ uint32_t pmo_amod:1; -+ uint32_t pmo_fpc:3; -+ uint32_t tsr_hwm:3; -+ uint32_t bar2_enb:1; -+ uint32_t bar2_esx:2; -+ uint32_t bar2_cax:1; -+ } cn31xx; -+ struct cvmx_pci_ctl_status_2_s cn38xx; -+ struct cvmx_pci_ctl_status_2_cn31xx cn38xxp2; -+ struct cvmx_pci_ctl_status_2_s cn50xx; -+ struct cvmx_pci_ctl_status_2_s cn58xx; -+ struct cvmx_pci_ctl_status_2_s cn58xxp1; -+}; -+ -+union cvmx_pci_dbellx { -+ uint32_t u32; -+ struct cvmx_pci_dbellx_s { -+ uint32_t reserved_16_31:16; -+ uint32_t inc_val:16; -+ } s; -+ struct cvmx_pci_dbellx_s cn30xx; -+ struct cvmx_pci_dbellx_s cn31xx; -+ struct cvmx_pci_dbellx_s cn38xx; -+ struct cvmx_pci_dbellx_s cn38xxp2; -+ struct cvmx_pci_dbellx_s cn50xx; -+ struct cvmx_pci_dbellx_s cn58xx; -+ struct cvmx_pci_dbellx_s cn58xxp1; -+}; -+ -+union cvmx_pci_dma_cntx { -+ uint32_t u32; -+ struct cvmx_pci_dma_cntx_s { -+ uint32_t dma_cnt:32; -+ } s; -+ struct cvmx_pci_dma_cntx_s cn30xx; -+ struct cvmx_pci_dma_cntx_s cn31xx; -+ struct cvmx_pci_dma_cntx_s cn38xx; -+ struct cvmx_pci_dma_cntx_s cn38xxp2; -+ struct cvmx_pci_dma_cntx_s cn50xx; -+ struct cvmx_pci_dma_cntx_s cn58xx; -+ struct cvmx_pci_dma_cntx_s cn58xxp1; -+}; -+ -+union cvmx_pci_dma_int_levx { -+ uint32_t u32; -+ struct cvmx_pci_dma_int_levx_s { -+ uint32_t pkt_cnt:32; -+ } s; -+ struct cvmx_pci_dma_int_levx_s cn30xx; -+ struct cvmx_pci_dma_int_levx_s cn31xx; -+ struct cvmx_pci_dma_int_levx_s cn38xx; -+ struct cvmx_pci_dma_int_levx_s cn38xxp2; -+ struct cvmx_pci_dma_int_levx_s cn50xx; -+ struct cvmx_pci_dma_int_levx_s cn58xx; -+ struct cvmx_pci_dma_int_levx_s cn58xxp1; -+}; -+ -+union cvmx_pci_dma_timex { -+ uint32_t u32; -+ struct cvmx_pci_dma_timex_s { -+ uint32_t dma_time:32; -+ } s; -+ struct cvmx_pci_dma_timex_s cn30xx; -+ struct cvmx_pci_dma_timex_s cn31xx; -+ struct cvmx_pci_dma_timex_s cn38xx; -+ struct cvmx_pci_dma_timex_s cn38xxp2; -+ struct cvmx_pci_dma_timex_s cn50xx; -+ struct cvmx_pci_dma_timex_s cn58xx; -+ struct cvmx_pci_dma_timex_s cn58xxp1; -+}; -+ -+union cvmx_pci_instr_countx { -+ uint32_t u32; -+ struct cvmx_pci_instr_countx_s { -+ uint32_t icnt:32; -+ } s; -+ struct cvmx_pci_instr_countx_s cn30xx; -+ struct cvmx_pci_instr_countx_s cn31xx; -+ struct cvmx_pci_instr_countx_s cn38xx; -+ struct cvmx_pci_instr_countx_s cn38xxp2; -+ struct cvmx_pci_instr_countx_s cn50xx; -+ struct cvmx_pci_instr_countx_s cn58xx; -+ struct cvmx_pci_instr_countx_s cn58xxp1; -+}; -+ -+union cvmx_pci_int_enb { -+ uint64_t u64; -+ struct cvmx_pci_int_enb_s { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t idtime1:1; -+ uint64_t idtime0:1; -+ uint64_t idcnt1:1; -+ uint64_t idcnt0:1; -+ uint64_t iptime3:1; -+ uint64_t iptime2:1; -+ uint64_t iptime1:1; -+ uint64_t iptime0:1; -+ uint64_t ipcnt3:1; -+ uint64_t ipcnt2:1; -+ uint64_t ipcnt1:1; -+ uint64_t ipcnt0:1; -+ uint64_t irsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t idperr:1; -+ uint64_t iaperr:1; -+ uint64_t iserr:1; -+ uint64_t itsr_abt:1; -+ uint64_t imsc_msg:1; -+ uint64_t imsi_mabt:1; -+ uint64_t imsi_tabt:1; -+ uint64_t imsi_per:1; -+ uint64_t imr_tto:1; -+ uint64_t imr_abt:1; -+ uint64_t itr_abt:1; -+ uint64_t imr_wtto:1; -+ uint64_t imr_wabt:1; -+ uint64_t itr_wabt:1; -+ } s; -+ struct cvmx_pci_int_enb_cn30xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t idtime1:1; -+ uint64_t idtime0:1; -+ uint64_t idcnt1:1; -+ uint64_t idcnt0:1; -+ uint64_t reserved_22_24:3; -+ uint64_t iptime0:1; -+ uint64_t reserved_18_20:3; -+ uint64_t ipcnt0:1; -+ uint64_t irsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t idperr:1; -+ uint64_t iaperr:1; -+ uint64_t iserr:1; -+ uint64_t itsr_abt:1; -+ uint64_t imsc_msg:1; -+ uint64_t imsi_mabt:1; -+ uint64_t imsi_tabt:1; -+ uint64_t imsi_per:1; -+ uint64_t imr_tto:1; -+ uint64_t imr_abt:1; -+ uint64_t itr_abt:1; -+ uint64_t imr_wtto:1; -+ uint64_t imr_wabt:1; -+ uint64_t itr_wabt:1; -+ } cn30xx; -+ struct cvmx_pci_int_enb_cn31xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t idtime1:1; -+ uint64_t idtime0:1; -+ uint64_t idcnt1:1; -+ uint64_t idcnt0:1; -+ uint64_t reserved_23_24:2; -+ uint64_t iptime1:1; -+ uint64_t iptime0:1; -+ uint64_t reserved_19_20:2; -+ uint64_t ipcnt1:1; -+ uint64_t ipcnt0:1; -+ uint64_t irsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t idperr:1; -+ uint64_t iaperr:1; -+ uint64_t iserr:1; -+ uint64_t itsr_abt:1; -+ uint64_t imsc_msg:1; -+ uint64_t imsi_mabt:1; -+ uint64_t imsi_tabt:1; -+ uint64_t imsi_per:1; -+ uint64_t imr_tto:1; -+ uint64_t imr_abt:1; -+ uint64_t itr_abt:1; -+ uint64_t imr_wtto:1; -+ uint64_t imr_wabt:1; -+ uint64_t itr_wabt:1; -+ } cn31xx; -+ struct cvmx_pci_int_enb_s cn38xx; -+ struct cvmx_pci_int_enb_s cn38xxp2; -+ struct cvmx_pci_int_enb_cn31xx cn50xx; -+ struct cvmx_pci_int_enb_s cn58xx; -+ struct cvmx_pci_int_enb_s cn58xxp1; -+}; -+ -+union cvmx_pci_int_enb2 { -+ uint64_t u64; -+ struct cvmx_pci_int_enb2_s { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t rdtime1:1; -+ uint64_t rdtime0:1; -+ uint64_t rdcnt1:1; -+ uint64_t rdcnt0:1; -+ uint64_t rptime3:1; -+ uint64_t rptime2:1; -+ uint64_t rptime1:1; -+ uint64_t rptime0:1; -+ uint64_t rpcnt3:1; -+ uint64_t rpcnt2:1; -+ uint64_t rpcnt1:1; -+ uint64_t rpcnt0:1; -+ uint64_t rrsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t rdperr:1; -+ uint64_t raperr:1; -+ uint64_t rserr:1; -+ uint64_t rtsr_abt:1; -+ uint64_t rmsc_msg:1; -+ uint64_t rmsi_mabt:1; -+ uint64_t rmsi_tabt:1; -+ uint64_t rmsi_per:1; -+ uint64_t rmr_tto:1; -+ uint64_t rmr_abt:1; -+ uint64_t rtr_abt:1; -+ uint64_t rmr_wtto:1; -+ uint64_t rmr_wabt:1; -+ uint64_t rtr_wabt:1; -+ } s; -+ struct cvmx_pci_int_enb2_cn30xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t rdtime1:1; -+ uint64_t rdtime0:1; -+ uint64_t rdcnt1:1; -+ uint64_t rdcnt0:1; -+ uint64_t reserved_22_24:3; -+ uint64_t rptime0:1; -+ uint64_t reserved_18_20:3; -+ uint64_t rpcnt0:1; -+ uint64_t rrsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t rdperr:1; -+ uint64_t raperr:1; -+ uint64_t rserr:1; -+ uint64_t rtsr_abt:1; -+ uint64_t rmsc_msg:1; -+ uint64_t rmsi_mabt:1; -+ uint64_t rmsi_tabt:1; -+ uint64_t rmsi_per:1; -+ uint64_t rmr_tto:1; -+ uint64_t rmr_abt:1; -+ uint64_t rtr_abt:1; -+ uint64_t rmr_wtto:1; -+ uint64_t rmr_wabt:1; -+ uint64_t rtr_wabt:1; -+ } cn30xx; -+ struct cvmx_pci_int_enb2_cn31xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t rdtime1:1; -+ uint64_t rdtime0:1; -+ uint64_t rdcnt1:1; -+ uint64_t rdcnt0:1; -+ uint64_t reserved_23_24:2; -+ uint64_t rptime1:1; -+ uint64_t rptime0:1; -+ uint64_t reserved_19_20:2; -+ uint64_t rpcnt1:1; -+ uint64_t rpcnt0:1; -+ uint64_t rrsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t rdperr:1; -+ uint64_t raperr:1; -+ uint64_t rserr:1; -+ uint64_t rtsr_abt:1; -+ uint64_t rmsc_msg:1; -+ uint64_t rmsi_mabt:1; -+ uint64_t rmsi_tabt:1; -+ uint64_t rmsi_per:1; -+ uint64_t rmr_tto:1; -+ uint64_t rmr_abt:1; -+ uint64_t rtr_abt:1; -+ uint64_t rmr_wtto:1; -+ uint64_t rmr_wabt:1; -+ uint64_t rtr_wabt:1; -+ } cn31xx; -+ struct cvmx_pci_int_enb2_s cn38xx; -+ struct cvmx_pci_int_enb2_s cn38xxp2; -+ struct cvmx_pci_int_enb2_cn31xx cn50xx; -+ struct cvmx_pci_int_enb2_s cn58xx; -+ struct cvmx_pci_int_enb2_s cn58xxp1; -+}; -+ -+union cvmx_pci_int_sum { -+ uint64_t u64; -+ struct cvmx_pci_int_sum_s { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t ptime3:1; -+ uint64_t ptime2:1; -+ uint64_t ptime1:1; -+ uint64_t ptime0:1; -+ uint64_t pcnt3:1; -+ uint64_t pcnt2:1; -+ uint64_t pcnt1:1; -+ uint64_t pcnt0:1; -+ uint64_t rsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t dperr:1; -+ uint64_t aperr:1; -+ uint64_t serr:1; -+ uint64_t tsr_abt:1; -+ uint64_t msc_msg:1; -+ uint64_t msi_mabt:1; -+ uint64_t msi_tabt:1; -+ uint64_t msi_per:1; -+ uint64_t mr_tto:1; -+ uint64_t mr_abt:1; -+ uint64_t tr_abt:1; -+ uint64_t mr_wtto:1; -+ uint64_t mr_wabt:1; -+ uint64_t tr_wabt:1; -+ } s; -+ struct cvmx_pci_int_sum_cn30xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t reserved_22_24:3; -+ uint64_t ptime0:1; -+ uint64_t reserved_18_20:3; -+ uint64_t pcnt0:1; -+ uint64_t rsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t dperr:1; -+ uint64_t aperr:1; -+ uint64_t serr:1; -+ uint64_t tsr_abt:1; -+ uint64_t msc_msg:1; -+ uint64_t msi_mabt:1; -+ uint64_t msi_tabt:1; -+ uint64_t msi_per:1; -+ uint64_t mr_tto:1; -+ uint64_t mr_abt:1; -+ uint64_t tr_abt:1; -+ uint64_t mr_wtto:1; -+ uint64_t mr_wabt:1; -+ uint64_t tr_wabt:1; -+ } cn30xx; -+ struct cvmx_pci_int_sum_cn31xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t reserved_23_24:2; -+ uint64_t ptime1:1; -+ uint64_t ptime0:1; -+ uint64_t reserved_19_20:2; -+ uint64_t pcnt1:1; -+ uint64_t pcnt0:1; -+ uint64_t rsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t dperr:1; -+ uint64_t aperr:1; -+ uint64_t serr:1; -+ uint64_t tsr_abt:1; -+ uint64_t msc_msg:1; -+ uint64_t msi_mabt:1; -+ uint64_t msi_tabt:1; -+ uint64_t msi_per:1; -+ uint64_t mr_tto:1; -+ uint64_t mr_abt:1; -+ uint64_t tr_abt:1; -+ uint64_t mr_wtto:1; -+ uint64_t mr_wabt:1; -+ uint64_t tr_wabt:1; -+ } cn31xx; -+ struct cvmx_pci_int_sum_s cn38xx; -+ struct cvmx_pci_int_sum_s cn38xxp2; -+ struct cvmx_pci_int_sum_cn31xx cn50xx; -+ struct cvmx_pci_int_sum_s cn58xx; -+ struct cvmx_pci_int_sum_s cn58xxp1; -+}; -+ -+union cvmx_pci_int_sum2 { -+ uint64_t u64; -+ struct cvmx_pci_int_sum2_s { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t ptime3:1; -+ uint64_t ptime2:1; -+ uint64_t ptime1:1; -+ uint64_t ptime0:1; -+ uint64_t pcnt3:1; -+ uint64_t pcnt2:1; -+ uint64_t pcnt1:1; -+ uint64_t pcnt0:1; -+ uint64_t rsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t dperr:1; -+ uint64_t aperr:1; -+ uint64_t serr:1; -+ uint64_t tsr_abt:1; -+ uint64_t msc_msg:1; -+ uint64_t msi_mabt:1; -+ uint64_t msi_tabt:1; -+ uint64_t msi_per:1; -+ uint64_t mr_tto:1; -+ uint64_t mr_abt:1; -+ uint64_t tr_abt:1; -+ uint64_t mr_wtto:1; -+ uint64_t mr_wabt:1; -+ uint64_t tr_wabt:1; -+ } s; -+ struct cvmx_pci_int_sum2_cn30xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t reserved_22_24:3; -+ uint64_t ptime0:1; -+ uint64_t reserved_18_20:3; -+ uint64_t pcnt0:1; -+ uint64_t rsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t dperr:1; -+ uint64_t aperr:1; -+ uint64_t serr:1; -+ uint64_t tsr_abt:1; -+ uint64_t msc_msg:1; -+ uint64_t msi_mabt:1; -+ uint64_t msi_tabt:1; -+ uint64_t msi_per:1; -+ uint64_t mr_tto:1; -+ uint64_t mr_abt:1; -+ uint64_t tr_abt:1; -+ uint64_t mr_wtto:1; -+ uint64_t mr_wabt:1; -+ uint64_t tr_wabt:1; -+ } cn30xx; -+ struct cvmx_pci_int_sum2_cn31xx { -+ uint64_t reserved_34_63:30; -+ uint64_t ill_rd:1; -+ uint64_t ill_wr:1; -+ uint64_t win_wr:1; -+ uint64_t dma1_fi:1; -+ uint64_t dma0_fi:1; -+ uint64_t dtime1:1; -+ uint64_t dtime0:1; -+ uint64_t dcnt1:1; -+ uint64_t dcnt0:1; -+ uint64_t reserved_23_24:2; -+ uint64_t ptime1:1; -+ uint64_t ptime0:1; -+ uint64_t reserved_19_20:2; -+ uint64_t pcnt1:1; -+ uint64_t pcnt0:1; -+ uint64_t rsl_int:1; -+ uint64_t ill_rrd:1; -+ uint64_t ill_rwr:1; -+ uint64_t dperr:1; -+ uint64_t aperr:1; -+ uint64_t serr:1; -+ uint64_t tsr_abt:1; -+ uint64_t msc_msg:1; -+ uint64_t msi_mabt:1; -+ uint64_t msi_tabt:1; -+ uint64_t msi_per:1; -+ uint64_t mr_tto:1; -+ uint64_t mr_abt:1; -+ uint64_t tr_abt:1; -+ uint64_t mr_wtto:1; -+ uint64_t mr_wabt:1; -+ uint64_t tr_wabt:1; -+ } cn31xx; -+ struct cvmx_pci_int_sum2_s cn38xx; -+ struct cvmx_pci_int_sum2_s cn38xxp2; -+ struct cvmx_pci_int_sum2_cn31xx cn50xx; -+ struct cvmx_pci_int_sum2_s cn58xx; -+ struct cvmx_pci_int_sum2_s cn58xxp1; -+}; -+ -+union cvmx_pci_msi_rcv { -+ uint32_t u32; -+ struct cvmx_pci_msi_rcv_s { -+ uint32_t reserved_6_31:26; -+ uint32_t intr:6; -+ } s; -+ struct cvmx_pci_msi_rcv_s cn30xx; -+ struct cvmx_pci_msi_rcv_s cn31xx; -+ struct cvmx_pci_msi_rcv_s cn38xx; -+ struct cvmx_pci_msi_rcv_s cn38xxp2; -+ struct cvmx_pci_msi_rcv_s cn50xx; -+ struct cvmx_pci_msi_rcv_s cn58xx; -+ struct cvmx_pci_msi_rcv_s cn58xxp1; -+}; -+ -+union cvmx_pci_pkt_creditsx { -+ uint32_t u32; -+ struct cvmx_pci_pkt_creditsx_s { -+ uint32_t pkt_cnt:16; -+ uint32_t ptr_cnt:16; -+ } s; -+ struct cvmx_pci_pkt_creditsx_s cn30xx; -+ struct cvmx_pci_pkt_creditsx_s cn31xx; -+ struct cvmx_pci_pkt_creditsx_s cn38xx; -+ struct cvmx_pci_pkt_creditsx_s cn38xxp2; -+ struct cvmx_pci_pkt_creditsx_s cn50xx; -+ struct cvmx_pci_pkt_creditsx_s cn58xx; -+ struct cvmx_pci_pkt_creditsx_s cn58xxp1; -+}; -+ -+union cvmx_pci_pkts_sentx { -+ uint32_t u32; -+ struct cvmx_pci_pkts_sentx_s { -+ uint32_t pkt_cnt:32; -+ } s; -+ struct cvmx_pci_pkts_sentx_s cn30xx; -+ struct cvmx_pci_pkts_sentx_s cn31xx; -+ struct cvmx_pci_pkts_sentx_s cn38xx; -+ struct cvmx_pci_pkts_sentx_s cn38xxp2; -+ struct cvmx_pci_pkts_sentx_s cn50xx; -+ struct cvmx_pci_pkts_sentx_s cn58xx; -+ struct cvmx_pci_pkts_sentx_s cn58xxp1; -+}; -+ -+union cvmx_pci_pkts_sent_int_levx { -+ uint32_t u32; -+ struct cvmx_pci_pkts_sent_int_levx_s { -+ uint32_t pkt_cnt:32; -+ } s; -+ struct cvmx_pci_pkts_sent_int_levx_s cn30xx; -+ struct cvmx_pci_pkts_sent_int_levx_s cn31xx; -+ struct cvmx_pci_pkts_sent_int_levx_s cn38xx; -+ struct cvmx_pci_pkts_sent_int_levx_s cn38xxp2; -+ struct cvmx_pci_pkts_sent_int_levx_s cn50xx; -+ struct cvmx_pci_pkts_sent_int_levx_s cn58xx; -+ struct cvmx_pci_pkts_sent_int_levx_s cn58xxp1; -+}; -+ -+union cvmx_pci_pkts_sent_timex { -+ uint32_t u32; -+ struct cvmx_pci_pkts_sent_timex_s { -+ uint32_t pkt_time:32; -+ } s; -+ struct cvmx_pci_pkts_sent_timex_s cn30xx; -+ struct cvmx_pci_pkts_sent_timex_s cn31xx; -+ struct cvmx_pci_pkts_sent_timex_s cn38xx; -+ struct cvmx_pci_pkts_sent_timex_s cn38xxp2; -+ struct cvmx_pci_pkts_sent_timex_s cn50xx; -+ struct cvmx_pci_pkts_sent_timex_s cn58xx; -+ struct cvmx_pci_pkts_sent_timex_s cn58xxp1; -+}; -+ -+union cvmx_pci_read_cmd_6 { -+ uint32_t u32; -+ struct cvmx_pci_read_cmd_6_s { -+ uint32_t reserved_9_31:23; -+ uint32_t min_data:6; -+ uint32_t prefetch:3; -+ } s; -+ struct cvmx_pci_read_cmd_6_s cn30xx; -+ struct cvmx_pci_read_cmd_6_s cn31xx; -+ struct cvmx_pci_read_cmd_6_s cn38xx; -+ struct cvmx_pci_read_cmd_6_s cn38xxp2; -+ struct cvmx_pci_read_cmd_6_s cn50xx; -+ struct cvmx_pci_read_cmd_6_s cn58xx; -+ struct cvmx_pci_read_cmd_6_s cn58xxp1; -+}; -+ -+union cvmx_pci_read_cmd_c { -+ uint32_t u32; -+ struct cvmx_pci_read_cmd_c_s { -+ uint32_t reserved_9_31:23; -+ uint32_t min_data:6; -+ uint32_t prefetch:3; -+ } s; -+ struct cvmx_pci_read_cmd_c_s cn30xx; -+ struct cvmx_pci_read_cmd_c_s cn31xx; -+ struct cvmx_pci_read_cmd_c_s cn38xx; -+ struct cvmx_pci_read_cmd_c_s cn38xxp2; -+ struct cvmx_pci_read_cmd_c_s cn50xx; -+ struct cvmx_pci_read_cmd_c_s cn58xx; -+ struct cvmx_pci_read_cmd_c_s cn58xxp1; -+}; -+ -+union cvmx_pci_read_cmd_e { -+ uint32_t u32; -+ struct cvmx_pci_read_cmd_e_s { -+ uint32_t reserved_9_31:23; -+ uint32_t min_data:6; -+ uint32_t prefetch:3; -+ } s; -+ struct cvmx_pci_read_cmd_e_s cn30xx; -+ struct cvmx_pci_read_cmd_e_s cn31xx; -+ struct cvmx_pci_read_cmd_e_s cn38xx; -+ struct cvmx_pci_read_cmd_e_s cn38xxp2; -+ struct cvmx_pci_read_cmd_e_s cn50xx; -+ struct cvmx_pci_read_cmd_e_s cn58xx; -+ struct cvmx_pci_read_cmd_e_s cn58xxp1; -+}; -+ -+union cvmx_pci_read_timeout { -+ uint64_t u64; -+ struct cvmx_pci_read_timeout_s { -+ uint64_t reserved_32_63:32; -+ uint64_t enb:1; -+ uint64_t cnt:31; -+ } s; -+ struct cvmx_pci_read_timeout_s cn30xx; -+ struct cvmx_pci_read_timeout_s cn31xx; -+ struct cvmx_pci_read_timeout_s cn38xx; -+ struct cvmx_pci_read_timeout_s cn38xxp2; -+ struct cvmx_pci_read_timeout_s cn50xx; -+ struct cvmx_pci_read_timeout_s cn58xx; -+ struct cvmx_pci_read_timeout_s cn58xxp1; -+}; -+ -+union cvmx_pci_scm_reg { -+ uint64_t u64; -+ struct cvmx_pci_scm_reg_s { -+ uint64_t reserved_32_63:32; -+ uint64_t scm:32; -+ } s; -+ struct cvmx_pci_scm_reg_s cn30xx; -+ struct cvmx_pci_scm_reg_s cn31xx; -+ struct cvmx_pci_scm_reg_s cn38xx; -+ struct cvmx_pci_scm_reg_s cn38xxp2; -+ struct cvmx_pci_scm_reg_s cn50xx; -+ struct cvmx_pci_scm_reg_s cn58xx; -+ struct cvmx_pci_scm_reg_s cn58xxp1; -+}; -+ -+union cvmx_pci_tsr_reg { -+ uint64_t u64; -+ struct cvmx_pci_tsr_reg_s { -+ uint64_t reserved_36_63:28; -+ uint64_t tsr:36; -+ } s; -+ struct cvmx_pci_tsr_reg_s cn30xx; -+ struct cvmx_pci_tsr_reg_s cn31xx; -+ struct cvmx_pci_tsr_reg_s cn38xx; -+ struct cvmx_pci_tsr_reg_s cn38xxp2; -+ struct cvmx_pci_tsr_reg_s cn50xx; -+ struct cvmx_pci_tsr_reg_s cn58xx; -+ struct cvmx_pci_tsr_reg_s cn58xxp1; -+}; -+ -+union cvmx_pci_win_rd_addr { -+ uint64_t u64; -+ struct cvmx_pci_win_rd_addr_s { -+ uint64_t reserved_49_63:15; -+ uint64_t iobit:1; -+ uint64_t reserved_0_47:48; -+ } s; -+ struct cvmx_pci_win_rd_addr_cn30xx { -+ uint64_t reserved_49_63:15; -+ uint64_t iobit:1; -+ uint64_t rd_addr:46; -+ uint64_t reserved_0_1:2; -+ } cn30xx; -+ struct cvmx_pci_win_rd_addr_cn30xx cn31xx; -+ struct cvmx_pci_win_rd_addr_cn38xx { -+ uint64_t reserved_49_63:15; -+ uint64_t iobit:1; -+ uint64_t rd_addr:45; -+ uint64_t reserved_0_2:3; -+ } cn38xx; -+ struct cvmx_pci_win_rd_addr_cn38xx cn38xxp2; -+ struct cvmx_pci_win_rd_addr_cn30xx cn50xx; -+ struct cvmx_pci_win_rd_addr_cn38xx cn58xx; -+ struct cvmx_pci_win_rd_addr_cn38xx cn58xxp1; -+}; -+ -+union cvmx_pci_win_rd_data { -+ uint64_t u64; -+ struct cvmx_pci_win_rd_data_s { -+ uint64_t rd_data:64; -+ } s; -+ struct cvmx_pci_win_rd_data_s cn30xx; -+ struct cvmx_pci_win_rd_data_s cn31xx; -+ struct cvmx_pci_win_rd_data_s cn38xx; -+ struct cvmx_pci_win_rd_data_s cn38xxp2; -+ struct cvmx_pci_win_rd_data_s cn50xx; -+ struct cvmx_pci_win_rd_data_s cn58xx; -+ struct cvmx_pci_win_rd_data_s cn58xxp1; -+}; -+ -+union cvmx_pci_win_wr_addr { -+ uint64_t u64; -+ struct cvmx_pci_win_wr_addr_s { -+ uint64_t reserved_49_63:15; -+ uint64_t iobit:1; -+ uint64_t wr_addr:45; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_pci_win_wr_addr_s cn30xx; -+ struct cvmx_pci_win_wr_addr_s cn31xx; -+ struct cvmx_pci_win_wr_addr_s cn38xx; -+ struct cvmx_pci_win_wr_addr_s cn38xxp2; -+ struct cvmx_pci_win_wr_addr_s cn50xx; -+ struct cvmx_pci_win_wr_addr_s cn58xx; -+ struct cvmx_pci_win_wr_addr_s cn58xxp1; -+}; -+ -+union cvmx_pci_win_wr_data { -+ uint64_t u64; -+ struct cvmx_pci_win_wr_data_s { -+ uint64_t wr_data:64; -+ } s; -+ struct cvmx_pci_win_wr_data_s cn30xx; -+ struct cvmx_pci_win_wr_data_s cn31xx; -+ struct cvmx_pci_win_wr_data_s cn38xx; -+ struct cvmx_pci_win_wr_data_s cn38xxp2; -+ struct cvmx_pci_win_wr_data_s cn50xx; -+ struct cvmx_pci_win_wr_data_s cn58xx; -+ struct cvmx_pci_win_wr_data_s cn58xxp1; -+}; -+ -+union cvmx_pci_win_wr_mask { -+ uint64_t u64; -+ struct cvmx_pci_win_wr_mask_s { -+ uint64_t reserved_8_63:56; -+ uint64_t wr_mask:8; -+ } s; -+ struct cvmx_pci_win_wr_mask_s cn30xx; -+ struct cvmx_pci_win_wr_mask_s cn31xx; -+ struct cvmx_pci_win_wr_mask_s cn38xx; -+ struct cvmx_pci_win_wr_mask_s cn38xxp2; -+ struct cvmx_pci_win_wr_mask_s cn50xx; -+ struct cvmx_pci_win_wr_mask_s cn58xx; -+ struct cvmx_pci_win_wr_mask_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h -@@ -0,0 +1,1365 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PCIEEP_DEFS_H__ -+#define __CVMX_PCIEEP_DEFS_H__ -+ -+#define CVMX_PCIEEP_CFG000 \ -+ (0x0000000000000000ull) -+#define CVMX_PCIEEP_CFG001 \ -+ (0x0000000000000004ull) -+#define CVMX_PCIEEP_CFG002 \ -+ (0x0000000000000008ull) -+#define CVMX_PCIEEP_CFG003 \ -+ (0x000000000000000Cull) -+#define CVMX_PCIEEP_CFG004 \ -+ (0x0000000000000010ull) -+#define CVMX_PCIEEP_CFG004_MASK \ -+ (0x0000000080000010ull) -+#define CVMX_PCIEEP_CFG005 \ -+ (0x0000000000000014ull) -+#define CVMX_PCIEEP_CFG005_MASK \ -+ (0x0000000080000014ull) -+#define CVMX_PCIEEP_CFG006 \ -+ (0x0000000000000018ull) -+#define CVMX_PCIEEP_CFG006_MASK \ -+ (0x0000000080000018ull) -+#define CVMX_PCIEEP_CFG007 \ -+ (0x000000000000001Cull) -+#define CVMX_PCIEEP_CFG007_MASK \ -+ (0x000000008000001Cull) -+#define CVMX_PCIEEP_CFG008 \ -+ (0x0000000000000020ull) -+#define CVMX_PCIEEP_CFG008_MASK \ -+ (0x0000000080000020ull) -+#define CVMX_PCIEEP_CFG009 \ -+ (0x0000000000000024ull) -+#define CVMX_PCIEEP_CFG009_MASK \ -+ (0x0000000080000024ull) -+#define CVMX_PCIEEP_CFG010 \ -+ (0x0000000000000028ull) -+#define CVMX_PCIEEP_CFG011 \ -+ (0x000000000000002Cull) -+#define CVMX_PCIEEP_CFG012 \ -+ (0x0000000000000030ull) -+#define CVMX_PCIEEP_CFG012_MASK \ -+ (0x0000000080000030ull) -+#define CVMX_PCIEEP_CFG013 \ -+ (0x0000000000000034ull) -+#define CVMX_PCIEEP_CFG015 \ -+ (0x000000000000003Cull) -+#define CVMX_PCIEEP_CFG016 \ -+ (0x0000000000000040ull) -+#define CVMX_PCIEEP_CFG017 \ -+ (0x0000000000000044ull) -+#define CVMX_PCIEEP_CFG020 \ -+ (0x0000000000000050ull) -+#define CVMX_PCIEEP_CFG021 \ -+ (0x0000000000000054ull) -+#define CVMX_PCIEEP_CFG022 \ -+ (0x0000000000000058ull) -+#define CVMX_PCIEEP_CFG023 \ -+ (0x000000000000005Cull) -+#define CVMX_PCIEEP_CFG028 \ -+ (0x0000000000000070ull) -+#define CVMX_PCIEEP_CFG029 \ -+ (0x0000000000000074ull) -+#define CVMX_PCIEEP_CFG030 \ -+ (0x0000000000000078ull) -+#define CVMX_PCIEEP_CFG031 \ -+ (0x000000000000007Cull) -+#define CVMX_PCIEEP_CFG032 \ -+ (0x0000000000000080ull) -+#define CVMX_PCIEEP_CFG033 \ -+ (0x0000000000000084ull) -+#define CVMX_PCIEEP_CFG034 \ -+ (0x0000000000000088ull) -+#define CVMX_PCIEEP_CFG037 \ -+ (0x0000000000000094ull) -+#define CVMX_PCIEEP_CFG038 \ -+ (0x0000000000000098ull) -+#define CVMX_PCIEEP_CFG039 \ -+ (0x000000000000009Cull) -+#define CVMX_PCIEEP_CFG040 \ -+ (0x00000000000000A0ull) -+#define CVMX_PCIEEP_CFG041 \ -+ (0x00000000000000A4ull) -+#define CVMX_PCIEEP_CFG042 \ -+ (0x00000000000000A8ull) -+#define CVMX_PCIEEP_CFG064 \ -+ (0x0000000000000100ull) -+#define CVMX_PCIEEP_CFG065 \ -+ (0x0000000000000104ull) -+#define CVMX_PCIEEP_CFG066 \ -+ (0x0000000000000108ull) -+#define CVMX_PCIEEP_CFG067 \ -+ (0x000000000000010Cull) -+#define CVMX_PCIEEP_CFG068 \ -+ (0x0000000000000110ull) -+#define CVMX_PCIEEP_CFG069 \ -+ (0x0000000000000114ull) -+#define CVMX_PCIEEP_CFG070 \ -+ (0x0000000000000118ull) -+#define CVMX_PCIEEP_CFG071 \ -+ (0x000000000000011Cull) -+#define CVMX_PCIEEP_CFG072 \ -+ (0x0000000000000120ull) -+#define CVMX_PCIEEP_CFG073 \ -+ (0x0000000000000124ull) -+#define CVMX_PCIEEP_CFG074 \ -+ (0x0000000000000128ull) -+#define CVMX_PCIEEP_CFG448 \ -+ (0x0000000000000700ull) -+#define CVMX_PCIEEP_CFG449 \ -+ (0x0000000000000704ull) -+#define CVMX_PCIEEP_CFG450 \ -+ (0x0000000000000708ull) -+#define CVMX_PCIEEP_CFG451 \ -+ (0x000000000000070Cull) -+#define CVMX_PCIEEP_CFG452 \ -+ (0x0000000000000710ull) -+#define CVMX_PCIEEP_CFG453 \ -+ (0x0000000000000714ull) -+#define CVMX_PCIEEP_CFG454 \ -+ (0x0000000000000718ull) -+#define CVMX_PCIEEP_CFG455 \ -+ (0x000000000000071Cull) -+#define CVMX_PCIEEP_CFG456 \ -+ (0x0000000000000720ull) -+#define CVMX_PCIEEP_CFG458 \ -+ (0x0000000000000728ull) -+#define CVMX_PCIEEP_CFG459 \ -+ (0x000000000000072Cull) -+#define CVMX_PCIEEP_CFG460 \ -+ (0x0000000000000730ull) -+#define CVMX_PCIEEP_CFG461 \ -+ (0x0000000000000734ull) -+#define CVMX_PCIEEP_CFG462 \ -+ (0x0000000000000738ull) -+#define CVMX_PCIEEP_CFG463 \ -+ (0x000000000000073Cull) -+#define CVMX_PCIEEP_CFG464 \ -+ (0x0000000000000740ull) -+#define CVMX_PCIEEP_CFG465 \ -+ (0x0000000000000744ull) -+#define CVMX_PCIEEP_CFG466 \ -+ (0x0000000000000748ull) -+#define CVMX_PCIEEP_CFG467 \ -+ (0x000000000000074Cull) -+#define CVMX_PCIEEP_CFG468 \ -+ (0x0000000000000750ull) -+#define CVMX_PCIEEP_CFG490 \ -+ (0x00000000000007A8ull) -+#define CVMX_PCIEEP_CFG491 \ -+ (0x00000000000007ACull) -+#define CVMX_PCIEEP_CFG492 \ -+ (0x00000000000007B0ull) -+#define CVMX_PCIEEP_CFG516 \ -+ (0x0000000000000810ull) -+#define CVMX_PCIEEP_CFG517 \ -+ (0x0000000000000814ull) -+ -+union cvmx_pcieep_cfg000 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg000_s { -+ uint32_t devid:16; -+ uint32_t vendid:16; -+ } s; -+ struct cvmx_pcieep_cfg000_s cn52xx; -+ struct cvmx_pcieep_cfg000_s cn52xxp1; -+ struct cvmx_pcieep_cfg000_s cn56xx; -+ struct cvmx_pcieep_cfg000_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg001 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg001_s { -+ uint32_t dpe:1; -+ uint32_t sse:1; -+ uint32_t rma:1; -+ uint32_t rta:1; -+ uint32_t sta:1; -+ uint32_t devt:2; -+ uint32_t mdpe:1; -+ uint32_t fbb:1; -+ uint32_t reserved_22_22:1; -+ uint32_t m66:1; -+ uint32_t cl:1; -+ uint32_t i_stat:1; -+ uint32_t reserved_11_18:8; -+ uint32_t i_dis:1; -+ uint32_t fbbe:1; -+ uint32_t see:1; -+ uint32_t ids_wcc:1; -+ uint32_t per:1; -+ uint32_t vps:1; -+ uint32_t mwice:1; -+ uint32_t scse:1; -+ uint32_t me:1; -+ uint32_t msae:1; -+ uint32_t isae:1; -+ } s; -+ struct cvmx_pcieep_cfg001_s cn52xx; -+ struct cvmx_pcieep_cfg001_s cn52xxp1; -+ struct cvmx_pcieep_cfg001_s cn56xx; -+ struct cvmx_pcieep_cfg001_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg002 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg002_s { -+ uint32_t bcc:8; -+ uint32_t sc:8; -+ uint32_t pi:8; -+ uint32_t rid:8; -+ } s; -+ struct cvmx_pcieep_cfg002_s cn52xx; -+ struct cvmx_pcieep_cfg002_s cn52xxp1; -+ struct cvmx_pcieep_cfg002_s cn56xx; -+ struct cvmx_pcieep_cfg002_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg003 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg003_s { -+ uint32_t bist:8; -+ uint32_t mfd:1; -+ uint32_t chf:7; -+ uint32_t lt:8; -+ uint32_t cls:8; -+ } s; -+ struct cvmx_pcieep_cfg003_s cn52xx; -+ struct cvmx_pcieep_cfg003_s cn52xxp1; -+ struct cvmx_pcieep_cfg003_s cn56xx; -+ struct cvmx_pcieep_cfg003_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg004 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg004_s { -+ uint32_t lbab:18; -+ uint32_t reserved_4_13:10; -+ uint32_t pf:1; -+ uint32_t typ:2; -+ uint32_t mspc:1; -+ } s; -+ struct cvmx_pcieep_cfg004_s cn52xx; -+ struct cvmx_pcieep_cfg004_s cn52xxp1; -+ struct cvmx_pcieep_cfg004_s cn56xx; -+ struct cvmx_pcieep_cfg004_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg004_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg004_mask_s { -+ uint32_t lmask:31; -+ uint32_t enb:1; -+ } s; -+ struct cvmx_pcieep_cfg004_mask_s cn52xx; -+ struct cvmx_pcieep_cfg004_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg004_mask_s cn56xx; -+ struct cvmx_pcieep_cfg004_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg005 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg005_s { -+ uint32_t ubab:32; -+ } s; -+ struct cvmx_pcieep_cfg005_s cn52xx; -+ struct cvmx_pcieep_cfg005_s cn52xxp1; -+ struct cvmx_pcieep_cfg005_s cn56xx; -+ struct cvmx_pcieep_cfg005_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg005_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg005_mask_s { -+ uint32_t umask:32; -+ } s; -+ struct cvmx_pcieep_cfg005_mask_s cn52xx; -+ struct cvmx_pcieep_cfg005_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg005_mask_s cn56xx; -+ struct cvmx_pcieep_cfg005_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg006 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg006_s { -+ uint32_t lbab:6; -+ uint32_t reserved_4_25:22; -+ uint32_t pf:1; -+ uint32_t typ:2; -+ uint32_t mspc:1; -+ } s; -+ struct cvmx_pcieep_cfg006_s cn52xx; -+ struct cvmx_pcieep_cfg006_s cn52xxp1; -+ struct cvmx_pcieep_cfg006_s cn56xx; -+ struct cvmx_pcieep_cfg006_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg006_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg006_mask_s { -+ uint32_t lmask:31; -+ uint32_t enb:1; -+ } s; -+ struct cvmx_pcieep_cfg006_mask_s cn52xx; -+ struct cvmx_pcieep_cfg006_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg006_mask_s cn56xx; -+ struct cvmx_pcieep_cfg006_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg007 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg007_s { -+ uint32_t ubab:32; -+ } s; -+ struct cvmx_pcieep_cfg007_s cn52xx; -+ struct cvmx_pcieep_cfg007_s cn52xxp1; -+ struct cvmx_pcieep_cfg007_s cn56xx; -+ struct cvmx_pcieep_cfg007_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg007_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg007_mask_s { -+ uint32_t umask:32; -+ } s; -+ struct cvmx_pcieep_cfg007_mask_s cn52xx; -+ struct cvmx_pcieep_cfg007_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg007_mask_s cn56xx; -+ struct cvmx_pcieep_cfg007_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg008 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg008_s { -+ uint32_t reserved_4_31:28; -+ uint32_t pf:1; -+ uint32_t typ:2; -+ uint32_t mspc:1; -+ } s; -+ struct cvmx_pcieep_cfg008_s cn52xx; -+ struct cvmx_pcieep_cfg008_s cn52xxp1; -+ struct cvmx_pcieep_cfg008_s cn56xx; -+ struct cvmx_pcieep_cfg008_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg008_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg008_mask_s { -+ uint32_t lmask:31; -+ uint32_t enb:1; -+ } s; -+ struct cvmx_pcieep_cfg008_mask_s cn52xx; -+ struct cvmx_pcieep_cfg008_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg008_mask_s cn56xx; -+ struct cvmx_pcieep_cfg008_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg009 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg009_s { -+ uint32_t ubab:25; -+ uint32_t reserved_0_6:7; -+ } s; -+ struct cvmx_pcieep_cfg009_s cn52xx; -+ struct cvmx_pcieep_cfg009_s cn52xxp1; -+ struct cvmx_pcieep_cfg009_s cn56xx; -+ struct cvmx_pcieep_cfg009_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg009_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg009_mask_s { -+ uint32_t umask:32; -+ } s; -+ struct cvmx_pcieep_cfg009_mask_s cn52xx; -+ struct cvmx_pcieep_cfg009_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg009_mask_s cn56xx; -+ struct cvmx_pcieep_cfg009_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg010 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg010_s { -+ uint32_t cisp:32; -+ } s; -+ struct cvmx_pcieep_cfg010_s cn52xx; -+ struct cvmx_pcieep_cfg010_s cn52xxp1; -+ struct cvmx_pcieep_cfg010_s cn56xx; -+ struct cvmx_pcieep_cfg010_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg011 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg011_s { -+ uint32_t ssid:16; -+ uint32_t ssvid:16; -+ } s; -+ struct cvmx_pcieep_cfg011_s cn52xx; -+ struct cvmx_pcieep_cfg011_s cn52xxp1; -+ struct cvmx_pcieep_cfg011_s cn56xx; -+ struct cvmx_pcieep_cfg011_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg012 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg012_s { -+ uint32_t eraddr:16; -+ uint32_t reserved_1_15:15; -+ uint32_t er_en:1; -+ } s; -+ struct cvmx_pcieep_cfg012_s cn52xx; -+ struct cvmx_pcieep_cfg012_s cn52xxp1; -+ struct cvmx_pcieep_cfg012_s cn56xx; -+ struct cvmx_pcieep_cfg012_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg012_mask { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg012_mask_s { -+ uint32_t mask:31; -+ uint32_t enb:1; -+ } s; -+ struct cvmx_pcieep_cfg012_mask_s cn52xx; -+ struct cvmx_pcieep_cfg012_mask_s cn52xxp1; -+ struct cvmx_pcieep_cfg012_mask_s cn56xx; -+ struct cvmx_pcieep_cfg012_mask_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg013 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg013_s { -+ uint32_t reserved_8_31:24; -+ uint32_t cp:8; -+ } s; -+ struct cvmx_pcieep_cfg013_s cn52xx; -+ struct cvmx_pcieep_cfg013_s cn52xxp1; -+ struct cvmx_pcieep_cfg013_s cn56xx; -+ struct cvmx_pcieep_cfg013_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg015 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg015_s { -+ uint32_t ml:8; -+ uint32_t mg:8; -+ uint32_t inta:8; -+ uint32_t il:8; -+ } s; -+ struct cvmx_pcieep_cfg015_s cn52xx; -+ struct cvmx_pcieep_cfg015_s cn52xxp1; -+ struct cvmx_pcieep_cfg015_s cn56xx; -+ struct cvmx_pcieep_cfg015_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg016 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg016_s { -+ uint32_t pmes:5; -+ uint32_t d2s:1; -+ uint32_t d1s:1; -+ uint32_t auxc:3; -+ uint32_t dsi:1; -+ uint32_t reserved_20_20:1; -+ uint32_t pme_clock:1; -+ uint32_t pmsv:3; -+ uint32_t ncp:8; -+ uint32_t pmcid:8; -+ } s; -+ struct cvmx_pcieep_cfg016_s cn52xx; -+ struct cvmx_pcieep_cfg016_s cn52xxp1; -+ struct cvmx_pcieep_cfg016_s cn56xx; -+ struct cvmx_pcieep_cfg016_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg017 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg017_s { -+ uint32_t pmdia:8; -+ uint32_t bpccee:1; -+ uint32_t bd3h:1; -+ uint32_t reserved_16_21:6; -+ uint32_t pmess:1; -+ uint32_t pmedsia:2; -+ uint32_t pmds:4; -+ uint32_t pmeens:1; -+ uint32_t reserved_4_7:4; -+ uint32_t nsr:1; -+ uint32_t reserved_2_2:1; -+ uint32_t ps:2; -+ } s; -+ struct cvmx_pcieep_cfg017_s cn52xx; -+ struct cvmx_pcieep_cfg017_s cn52xxp1; -+ struct cvmx_pcieep_cfg017_s cn56xx; -+ struct cvmx_pcieep_cfg017_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg020 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg020_s { -+ uint32_t reserved_24_31:8; -+ uint32_t m64:1; -+ uint32_t mme:3; -+ uint32_t mmc:3; -+ uint32_t msien:1; -+ uint32_t ncp:8; -+ uint32_t msicid:8; -+ } s; -+ struct cvmx_pcieep_cfg020_s cn52xx; -+ struct cvmx_pcieep_cfg020_s cn52xxp1; -+ struct cvmx_pcieep_cfg020_s cn56xx; -+ struct cvmx_pcieep_cfg020_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg021 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg021_s { -+ uint32_t lmsi:30; -+ uint32_t reserved_0_1:2; -+ } s; -+ struct cvmx_pcieep_cfg021_s cn52xx; -+ struct cvmx_pcieep_cfg021_s cn52xxp1; -+ struct cvmx_pcieep_cfg021_s cn56xx; -+ struct cvmx_pcieep_cfg021_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg022 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg022_s { -+ uint32_t umsi:32; -+ } s; -+ struct cvmx_pcieep_cfg022_s cn52xx; -+ struct cvmx_pcieep_cfg022_s cn52xxp1; -+ struct cvmx_pcieep_cfg022_s cn56xx; -+ struct cvmx_pcieep_cfg022_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg023 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg023_s { -+ uint32_t reserved_16_31:16; -+ uint32_t msimd:16; -+ } s; -+ struct cvmx_pcieep_cfg023_s cn52xx; -+ struct cvmx_pcieep_cfg023_s cn52xxp1; -+ struct cvmx_pcieep_cfg023_s cn56xx; -+ struct cvmx_pcieep_cfg023_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg028 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg028_s { -+ uint32_t reserved_30_31:2; -+ uint32_t imn:5; -+ uint32_t si:1; -+ uint32_t dpt:4; -+ uint32_t pciecv:4; -+ uint32_t ncp:8; -+ uint32_t pcieid:8; -+ } s; -+ struct cvmx_pcieep_cfg028_s cn52xx; -+ struct cvmx_pcieep_cfg028_s cn52xxp1; -+ struct cvmx_pcieep_cfg028_s cn56xx; -+ struct cvmx_pcieep_cfg028_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg029 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg029_s { -+ uint32_t reserved_28_31:4; -+ uint32_t cspls:2; -+ uint32_t csplv:8; -+ uint32_t reserved_16_17:2; -+ uint32_t rber:1; -+ uint32_t reserved_12_14:3; -+ uint32_t el1al:3; -+ uint32_t el0al:3; -+ uint32_t etfs:1; -+ uint32_t pfs:2; -+ uint32_t mpss:3; -+ } s; -+ struct cvmx_pcieep_cfg029_s cn52xx; -+ struct cvmx_pcieep_cfg029_s cn52xxp1; -+ struct cvmx_pcieep_cfg029_s cn56xx; -+ struct cvmx_pcieep_cfg029_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg030 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg030_s { -+ uint32_t reserved_22_31:10; -+ uint32_t tp:1; -+ uint32_t ap_d:1; -+ uint32_t ur_d:1; -+ uint32_t fe_d:1; -+ uint32_t nfe_d:1; -+ uint32_t ce_d:1; -+ uint32_t reserved_15_15:1; -+ uint32_t mrrs:3; -+ uint32_t ns_en:1; -+ uint32_t ap_en:1; -+ uint32_t pf_en:1; -+ uint32_t etf_en:1; -+ uint32_t mps:3; -+ uint32_t ro_en:1; -+ uint32_t ur_en:1; -+ uint32_t fe_en:1; -+ uint32_t nfe_en:1; -+ uint32_t ce_en:1; -+ } s; -+ struct cvmx_pcieep_cfg030_s cn52xx; -+ struct cvmx_pcieep_cfg030_s cn52xxp1; -+ struct cvmx_pcieep_cfg030_s cn56xx; -+ struct cvmx_pcieep_cfg030_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg031 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg031_s { -+ uint32_t pnum:8; -+ uint32_t reserved_22_23:2; -+ uint32_t lbnc:1; -+ uint32_t dllarc:1; -+ uint32_t sderc:1; -+ uint32_t cpm:1; -+ uint32_t l1el:3; -+ uint32_t l0el:3; -+ uint32_t aslpms:2; -+ uint32_t mlw:6; -+ uint32_t mls:4; -+ } s; -+ struct cvmx_pcieep_cfg031_s cn52xx; -+ struct cvmx_pcieep_cfg031_s cn52xxp1; -+ struct cvmx_pcieep_cfg031_s cn56xx; -+ struct cvmx_pcieep_cfg031_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg032 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg032_s { -+ uint32_t reserved_30_31:2; -+ uint32_t dlla:1; -+ uint32_t scc:1; -+ uint32_t lt:1; -+ uint32_t reserved_26_26:1; -+ uint32_t nlw:6; -+ uint32_t ls:4; -+ uint32_t reserved_10_15:6; -+ uint32_t hawd:1; -+ uint32_t ecpm:1; -+ uint32_t es:1; -+ uint32_t ccc:1; -+ uint32_t rl:1; -+ uint32_t ld:1; -+ uint32_t rcb:1; -+ uint32_t reserved_2_2:1; -+ uint32_t aslpc:2; -+ } s; -+ struct cvmx_pcieep_cfg032_s cn52xx; -+ struct cvmx_pcieep_cfg032_s cn52xxp1; -+ struct cvmx_pcieep_cfg032_s cn56xx; -+ struct cvmx_pcieep_cfg032_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg033 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg033_s { -+ uint32_t ps_num:13; -+ uint32_t nccs:1; -+ uint32_t emip:1; -+ uint32_t sp_ls:2; -+ uint32_t sp_lv:8; -+ uint32_t hp_c:1; -+ uint32_t hp_s:1; -+ uint32_t pip:1; -+ uint32_t aip:1; -+ uint32_t mrlsp:1; -+ uint32_t pcp:1; -+ uint32_t abp:1; -+ } s; -+ struct cvmx_pcieep_cfg033_s cn52xx; -+ struct cvmx_pcieep_cfg033_s cn52xxp1; -+ struct cvmx_pcieep_cfg033_s cn56xx; -+ struct cvmx_pcieep_cfg033_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg034 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg034_s { -+ uint32_t reserved_25_31:7; -+ uint32_t dlls_c:1; -+ uint32_t emis:1; -+ uint32_t pds:1; -+ uint32_t mrlss:1; -+ uint32_t ccint_d:1; -+ uint32_t pd_c:1; -+ uint32_t mrls_c:1; -+ uint32_t pf_d:1; -+ uint32_t abp_d:1; -+ uint32_t reserved_13_15:3; -+ uint32_t dlls_en:1; -+ uint32_t emic:1; -+ uint32_t pcc:1; -+ uint32_t pic:2; -+ uint32_t aic:2; -+ uint32_t hpint_en:1; -+ uint32_t ccint_en:1; -+ uint32_t pd_en:1; -+ uint32_t mrls_en:1; -+ uint32_t pf_en:1; -+ uint32_t abp_en:1; -+ } s; -+ struct cvmx_pcieep_cfg034_s cn52xx; -+ struct cvmx_pcieep_cfg034_s cn52xxp1; -+ struct cvmx_pcieep_cfg034_s cn56xx; -+ struct cvmx_pcieep_cfg034_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg037 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg037_s { -+ uint32_t reserved_5_31:27; -+ uint32_t ctds:1; -+ uint32_t ctrs:4; -+ } s; -+ struct cvmx_pcieep_cfg037_s cn52xx; -+ struct cvmx_pcieep_cfg037_s cn52xxp1; -+ struct cvmx_pcieep_cfg037_s cn56xx; -+ struct cvmx_pcieep_cfg037_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg038 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg038_s { -+ uint32_t reserved_5_31:27; -+ uint32_t ctd:1; -+ uint32_t ctv:4; -+ } s; -+ struct cvmx_pcieep_cfg038_s cn52xx; -+ struct cvmx_pcieep_cfg038_s cn52xxp1; -+ struct cvmx_pcieep_cfg038_s cn56xx; -+ struct cvmx_pcieep_cfg038_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg039 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg039_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pcieep_cfg039_s cn52xx; -+ struct cvmx_pcieep_cfg039_s cn52xxp1; -+ struct cvmx_pcieep_cfg039_s cn56xx; -+ struct cvmx_pcieep_cfg039_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg040 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg040_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pcieep_cfg040_s cn52xx; -+ struct cvmx_pcieep_cfg040_s cn52xxp1; -+ struct cvmx_pcieep_cfg040_s cn56xx; -+ struct cvmx_pcieep_cfg040_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg041 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg041_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pcieep_cfg041_s cn52xx; -+ struct cvmx_pcieep_cfg041_s cn52xxp1; -+ struct cvmx_pcieep_cfg041_s cn56xx; -+ struct cvmx_pcieep_cfg041_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg042 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg042_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pcieep_cfg042_s cn52xx; -+ struct cvmx_pcieep_cfg042_s cn52xxp1; -+ struct cvmx_pcieep_cfg042_s cn56xx; -+ struct cvmx_pcieep_cfg042_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg064 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg064_s { -+ uint32_t nco:12; -+ uint32_t cv:4; -+ uint32_t pcieec:16; -+ } s; -+ struct cvmx_pcieep_cfg064_s cn52xx; -+ struct cvmx_pcieep_cfg064_s cn52xxp1; -+ struct cvmx_pcieep_cfg064_s cn56xx; -+ struct cvmx_pcieep_cfg064_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg065 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg065_s { -+ uint32_t reserved_21_31:11; -+ uint32_t ures:1; -+ uint32_t ecrces:1; -+ uint32_t mtlps:1; -+ uint32_t ros:1; -+ uint32_t ucs:1; -+ uint32_t cas:1; -+ uint32_t cts:1; -+ uint32_t fcpes:1; -+ uint32_t ptlps:1; -+ uint32_t reserved_6_11:6; -+ uint32_t sdes:1; -+ uint32_t dlpes:1; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pcieep_cfg065_s cn52xx; -+ struct cvmx_pcieep_cfg065_s cn52xxp1; -+ struct cvmx_pcieep_cfg065_s cn56xx; -+ struct cvmx_pcieep_cfg065_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg066 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg066_s { -+ uint32_t reserved_21_31:11; -+ uint32_t urem:1; -+ uint32_t ecrcem:1; -+ uint32_t mtlpm:1; -+ uint32_t rom:1; -+ uint32_t ucm:1; -+ uint32_t cam:1; -+ uint32_t ctm:1; -+ uint32_t fcpem:1; -+ uint32_t ptlpm:1; -+ uint32_t reserved_6_11:6; -+ uint32_t sdem:1; -+ uint32_t dlpem:1; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pcieep_cfg066_s cn52xx; -+ struct cvmx_pcieep_cfg066_s cn52xxp1; -+ struct cvmx_pcieep_cfg066_s cn56xx; -+ struct cvmx_pcieep_cfg066_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg067 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg067_s { -+ uint32_t reserved_21_31:11; -+ uint32_t ures:1; -+ uint32_t ecrces:1; -+ uint32_t mtlps:1; -+ uint32_t ros:1; -+ uint32_t ucs:1; -+ uint32_t cas:1; -+ uint32_t cts:1; -+ uint32_t fcpes:1; -+ uint32_t ptlps:1; -+ uint32_t reserved_6_11:6; -+ uint32_t sdes:1; -+ uint32_t dlpes:1; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pcieep_cfg067_s cn52xx; -+ struct cvmx_pcieep_cfg067_s cn52xxp1; -+ struct cvmx_pcieep_cfg067_s cn56xx; -+ struct cvmx_pcieep_cfg067_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg068 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg068_s { -+ uint32_t reserved_14_31:18; -+ uint32_t anfes:1; -+ uint32_t rtts:1; -+ uint32_t reserved_9_11:3; -+ uint32_t rnrs:1; -+ uint32_t bdllps:1; -+ uint32_t btlps:1; -+ uint32_t reserved_1_5:5; -+ uint32_t res:1; -+ } s; -+ struct cvmx_pcieep_cfg068_s cn52xx; -+ struct cvmx_pcieep_cfg068_s cn52xxp1; -+ struct cvmx_pcieep_cfg068_s cn56xx; -+ struct cvmx_pcieep_cfg068_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg069 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg069_s { -+ uint32_t reserved_14_31:18; -+ uint32_t anfem:1; -+ uint32_t rttm:1; -+ uint32_t reserved_9_11:3; -+ uint32_t rnrm:1; -+ uint32_t bdllpm:1; -+ uint32_t btlpm:1; -+ uint32_t reserved_1_5:5; -+ uint32_t rem:1; -+ } s; -+ struct cvmx_pcieep_cfg069_s cn52xx; -+ struct cvmx_pcieep_cfg069_s cn52xxp1; -+ struct cvmx_pcieep_cfg069_s cn56xx; -+ struct cvmx_pcieep_cfg069_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg070 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg070_s { -+ uint32_t reserved_9_31:23; -+ uint32_t ce:1; -+ uint32_t cc:1; -+ uint32_t ge:1; -+ uint32_t gc:1; -+ uint32_t fep:5; -+ } s; -+ struct cvmx_pcieep_cfg070_s cn52xx; -+ struct cvmx_pcieep_cfg070_s cn52xxp1; -+ struct cvmx_pcieep_cfg070_s cn56xx; -+ struct cvmx_pcieep_cfg070_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg071 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg071_s { -+ uint32_t dword1:32; -+ } s; -+ struct cvmx_pcieep_cfg071_s cn52xx; -+ struct cvmx_pcieep_cfg071_s cn52xxp1; -+ struct cvmx_pcieep_cfg071_s cn56xx; -+ struct cvmx_pcieep_cfg071_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg072 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg072_s { -+ uint32_t dword2:32; -+ } s; -+ struct cvmx_pcieep_cfg072_s cn52xx; -+ struct cvmx_pcieep_cfg072_s cn52xxp1; -+ struct cvmx_pcieep_cfg072_s cn56xx; -+ struct cvmx_pcieep_cfg072_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg073 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg073_s { -+ uint32_t dword3:32; -+ } s; -+ struct cvmx_pcieep_cfg073_s cn52xx; -+ struct cvmx_pcieep_cfg073_s cn52xxp1; -+ struct cvmx_pcieep_cfg073_s cn56xx; -+ struct cvmx_pcieep_cfg073_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg074 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg074_s { -+ uint32_t dword4:32; -+ } s; -+ struct cvmx_pcieep_cfg074_s cn52xx; -+ struct cvmx_pcieep_cfg074_s cn52xxp1; -+ struct cvmx_pcieep_cfg074_s cn56xx; -+ struct cvmx_pcieep_cfg074_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg448 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg448_s { -+ uint32_t rtl:16; -+ uint32_t rtltl:16; -+ } s; -+ struct cvmx_pcieep_cfg448_s cn52xx; -+ struct cvmx_pcieep_cfg448_s cn52xxp1; -+ struct cvmx_pcieep_cfg448_s cn56xx; -+ struct cvmx_pcieep_cfg448_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg449 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg449_s { -+ uint32_t omr:32; -+ } s; -+ struct cvmx_pcieep_cfg449_s cn52xx; -+ struct cvmx_pcieep_cfg449_s cn52xxp1; -+ struct cvmx_pcieep_cfg449_s cn56xx; -+ struct cvmx_pcieep_cfg449_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg450 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg450_s { -+ uint32_t lpec:8; -+ uint32_t reserved_22_23:2; -+ uint32_t link_state:6; -+ uint32_t force_link:1; -+ uint32_t reserved_8_14:7; -+ uint32_t link_num:8; -+ } s; -+ struct cvmx_pcieep_cfg450_s cn52xx; -+ struct cvmx_pcieep_cfg450_s cn52xxp1; -+ struct cvmx_pcieep_cfg450_s cn56xx; -+ struct cvmx_pcieep_cfg450_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg451 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg451_s { -+ uint32_t reserved_30_31:2; -+ uint32_t l1el:3; -+ uint32_t l0el:3; -+ uint32_t n_fts_cc:8; -+ uint32_t n_fts:8; -+ uint32_t ack_freq:8; -+ } s; -+ struct cvmx_pcieep_cfg451_s cn52xx; -+ struct cvmx_pcieep_cfg451_s cn52xxp1; -+ struct cvmx_pcieep_cfg451_s cn56xx; -+ struct cvmx_pcieep_cfg451_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg452 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg452_s { -+ uint32_t reserved_26_31:6; -+ uint32_t eccrc:1; -+ uint32_t reserved_22_24:3; -+ uint32_t lme:6; -+ uint32_t reserved_8_15:8; -+ uint32_t flm:1; -+ uint32_t reserved_6_6:1; -+ uint32_t dllle:1; -+ uint32_t reserved_4_4:1; -+ uint32_t ra:1; -+ uint32_t le:1; -+ uint32_t sd:1; -+ uint32_t omr:1; -+ } s; -+ struct cvmx_pcieep_cfg452_s cn52xx; -+ struct cvmx_pcieep_cfg452_s cn52xxp1; -+ struct cvmx_pcieep_cfg452_s cn56xx; -+ struct cvmx_pcieep_cfg452_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg453 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg453_s { -+ uint32_t dlld:1; -+ uint32_t reserved_26_30:5; -+ uint32_t ack_nak:1; -+ uint32_t fcd:1; -+ uint32_t ilst:24; -+ } s; -+ struct cvmx_pcieep_cfg453_s cn52xx; -+ struct cvmx_pcieep_cfg453_s cn52xxp1; -+ struct cvmx_pcieep_cfg453_s cn56xx; -+ struct cvmx_pcieep_cfg453_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg454 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg454_s { -+ uint32_t reserved_29_31:3; -+ uint32_t tmfcwt:5; -+ uint32_t tmanlt:5; -+ uint32_t tmrt:5; -+ uint32_t reserved_11_13:3; -+ uint32_t nskps:3; -+ uint32_t reserved_4_7:4; -+ uint32_t ntss:4; -+ } s; -+ struct cvmx_pcieep_cfg454_s cn52xx; -+ struct cvmx_pcieep_cfg454_s cn52xxp1; -+ struct cvmx_pcieep_cfg454_s cn56xx; -+ struct cvmx_pcieep_cfg454_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg455 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg455_s { -+ uint32_t m_cfg0_filt:1; -+ uint32_t m_io_filt:1; -+ uint32_t msg_ctrl:1; -+ uint32_t m_cpl_ecrc_filt:1; -+ uint32_t m_ecrc_filt:1; -+ uint32_t m_cpl_len_err:1; -+ uint32_t m_cpl_attr_err:1; -+ uint32_t m_cpl_tc_err:1; -+ uint32_t m_cpl_fun_err:1; -+ uint32_t m_cpl_rid_err:1; -+ uint32_t m_cpl_tag_err:1; -+ uint32_t m_lk_filt:1; -+ uint32_t m_cfg1_filt:1; -+ uint32_t m_bar_match:1; -+ uint32_t m_pois_filt:1; -+ uint32_t m_fun:1; -+ uint32_t dfcwt:1; -+ uint32_t reserved_11_14:4; -+ uint32_t skpiv:11; -+ } s; -+ struct cvmx_pcieep_cfg455_s cn52xx; -+ struct cvmx_pcieep_cfg455_s cn52xxp1; -+ struct cvmx_pcieep_cfg455_s cn56xx; -+ struct cvmx_pcieep_cfg455_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg456 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg456_s { -+ uint32_t reserved_2_31:30; -+ uint32_t m_vend1_drp:1; -+ uint32_t m_vend0_drp:1; -+ } s; -+ struct cvmx_pcieep_cfg456_s cn52xx; -+ struct cvmx_pcieep_cfg456_s cn52xxp1; -+ struct cvmx_pcieep_cfg456_s cn56xx; -+ struct cvmx_pcieep_cfg456_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg458 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg458_s { -+ uint32_t dbg_info_l32:32; -+ } s; -+ struct cvmx_pcieep_cfg458_s cn52xx; -+ struct cvmx_pcieep_cfg458_s cn52xxp1; -+ struct cvmx_pcieep_cfg458_s cn56xx; -+ struct cvmx_pcieep_cfg458_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg459 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg459_s { -+ uint32_t dbg_info_u32:32; -+ } s; -+ struct cvmx_pcieep_cfg459_s cn52xx; -+ struct cvmx_pcieep_cfg459_s cn52xxp1; -+ struct cvmx_pcieep_cfg459_s cn56xx; -+ struct cvmx_pcieep_cfg459_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg460 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg460_s { -+ uint32_t reserved_20_31:12; -+ uint32_t tphfcc:8; -+ uint32_t tpdfcc:12; -+ } s; -+ struct cvmx_pcieep_cfg460_s cn52xx; -+ struct cvmx_pcieep_cfg460_s cn52xxp1; -+ struct cvmx_pcieep_cfg460_s cn56xx; -+ struct cvmx_pcieep_cfg460_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg461 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg461_s { -+ uint32_t reserved_20_31:12; -+ uint32_t tchfcc:8; -+ uint32_t tcdfcc:12; -+ } s; -+ struct cvmx_pcieep_cfg461_s cn52xx; -+ struct cvmx_pcieep_cfg461_s cn52xxp1; -+ struct cvmx_pcieep_cfg461_s cn56xx; -+ struct cvmx_pcieep_cfg461_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg462 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg462_s { -+ uint32_t reserved_20_31:12; -+ uint32_t tchfcc:8; -+ uint32_t tcdfcc:12; -+ } s; -+ struct cvmx_pcieep_cfg462_s cn52xx; -+ struct cvmx_pcieep_cfg462_s cn52xxp1; -+ struct cvmx_pcieep_cfg462_s cn56xx; -+ struct cvmx_pcieep_cfg462_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg463 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg463_s { -+ uint32_t reserved_3_31:29; -+ uint32_t rqne:1; -+ uint32_t trbne:1; -+ uint32_t rtlpfccnr:1; -+ } s; -+ struct cvmx_pcieep_cfg463_s cn52xx; -+ struct cvmx_pcieep_cfg463_s cn52xxp1; -+ struct cvmx_pcieep_cfg463_s cn56xx; -+ struct cvmx_pcieep_cfg463_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg464 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg464_s { -+ uint32_t wrr_vc3:8; -+ uint32_t wrr_vc2:8; -+ uint32_t wrr_vc1:8; -+ uint32_t wrr_vc0:8; -+ } s; -+ struct cvmx_pcieep_cfg464_s cn52xx; -+ struct cvmx_pcieep_cfg464_s cn52xxp1; -+ struct cvmx_pcieep_cfg464_s cn56xx; -+ struct cvmx_pcieep_cfg464_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg465 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg465_s { -+ uint32_t wrr_vc7:8; -+ uint32_t wrr_vc6:8; -+ uint32_t wrr_vc5:8; -+ uint32_t wrr_vc4:8; -+ } s; -+ struct cvmx_pcieep_cfg465_s cn52xx; -+ struct cvmx_pcieep_cfg465_s cn52xxp1; -+ struct cvmx_pcieep_cfg465_s cn56xx; -+ struct cvmx_pcieep_cfg465_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg466 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg466_s { -+ uint32_t rx_queue_order:1; -+ uint32_t type_ordering:1; -+ uint32_t reserved_24_29:6; -+ uint32_t queue_mode:3; -+ uint32_t reserved_20_20:1; -+ uint32_t header_credits:8; -+ uint32_t data_credits:12; -+ } s; -+ struct cvmx_pcieep_cfg466_s cn52xx; -+ struct cvmx_pcieep_cfg466_s cn52xxp1; -+ struct cvmx_pcieep_cfg466_s cn56xx; -+ struct cvmx_pcieep_cfg466_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg467 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg467_s { -+ uint32_t reserved_24_31:8; -+ uint32_t queue_mode:3; -+ uint32_t reserved_20_20:1; -+ uint32_t header_credits:8; -+ uint32_t data_credits:12; -+ } s; -+ struct cvmx_pcieep_cfg467_s cn52xx; -+ struct cvmx_pcieep_cfg467_s cn52xxp1; -+ struct cvmx_pcieep_cfg467_s cn56xx; -+ struct cvmx_pcieep_cfg467_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg468 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg468_s { -+ uint32_t reserved_24_31:8; -+ uint32_t queue_mode:3; -+ uint32_t reserved_20_20:1; -+ uint32_t header_credits:8; -+ uint32_t data_credits:12; -+ } s; -+ struct cvmx_pcieep_cfg468_s cn52xx; -+ struct cvmx_pcieep_cfg468_s cn52xxp1; -+ struct cvmx_pcieep_cfg468_s cn56xx; -+ struct cvmx_pcieep_cfg468_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg490 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg490_s { -+ uint32_t reserved_26_31:6; -+ uint32_t header_depth:10; -+ uint32_t reserved_14_15:2; -+ uint32_t data_depth:14; -+ } s; -+ struct cvmx_pcieep_cfg490_s cn52xx; -+ struct cvmx_pcieep_cfg490_s cn52xxp1; -+ struct cvmx_pcieep_cfg490_s cn56xx; -+ struct cvmx_pcieep_cfg490_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg491 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg491_s { -+ uint32_t reserved_26_31:6; -+ uint32_t header_depth:10; -+ uint32_t reserved_14_15:2; -+ uint32_t data_depth:14; -+ } s; -+ struct cvmx_pcieep_cfg491_s cn52xx; -+ struct cvmx_pcieep_cfg491_s cn52xxp1; -+ struct cvmx_pcieep_cfg491_s cn56xx; -+ struct cvmx_pcieep_cfg491_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg492 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg492_s { -+ uint32_t reserved_26_31:6; -+ uint32_t header_depth:10; -+ uint32_t reserved_14_15:2; -+ uint32_t data_depth:14; -+ } s; -+ struct cvmx_pcieep_cfg492_s cn52xx; -+ struct cvmx_pcieep_cfg492_s cn52xxp1; -+ struct cvmx_pcieep_cfg492_s cn56xx; -+ struct cvmx_pcieep_cfg492_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg516 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg516_s { -+ uint32_t phy_stat:32; -+ } s; -+ struct cvmx_pcieep_cfg516_s cn52xx; -+ struct cvmx_pcieep_cfg516_s cn52xxp1; -+ struct cvmx_pcieep_cfg516_s cn56xx; -+ struct cvmx_pcieep_cfg516_s cn56xxp1; -+}; -+ -+union cvmx_pcieep_cfg517 { -+ uint32_t u32; -+ struct cvmx_pcieep_cfg517_s { -+ uint32_t phy_ctrl:32; -+ } s; -+ struct cvmx_pcieep_cfg517_s cn52xx; -+ struct cvmx_pcieep_cfg517_s cn52xxp1; -+ struct cvmx_pcieep_cfg517_s cn56xx; -+ struct cvmx_pcieep_cfg517_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h -@@ -0,0 +1,1397 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PCIERCX_DEFS_H__ -+#define __CVMX_PCIERCX_DEFS_H__ -+ -+#define CVMX_PCIERCX_CFG000(offset) \ -+ (0x0000000000000000ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG001(offset) \ -+ (0x0000000000000004ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG002(offset) \ -+ (0x0000000000000008ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG003(offset) \ -+ (0x000000000000000Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG004(offset) \ -+ (0x0000000000000010ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG005(offset) \ -+ (0x0000000000000014ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG006(offset) \ -+ (0x0000000000000018ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG007(offset) \ -+ (0x000000000000001Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG008(offset) \ -+ (0x0000000000000020ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG009(offset) \ -+ (0x0000000000000024ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG010(offset) \ -+ (0x0000000000000028ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG011(offset) \ -+ (0x000000000000002Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG012(offset) \ -+ (0x0000000000000030ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG013(offset) \ -+ (0x0000000000000034ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG014(offset) \ -+ (0x0000000000000038ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG015(offset) \ -+ (0x000000000000003Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG016(offset) \ -+ (0x0000000000000040ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG017(offset) \ -+ (0x0000000000000044ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG020(offset) \ -+ (0x0000000000000050ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG021(offset) \ -+ (0x0000000000000054ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG022(offset) \ -+ (0x0000000000000058ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG023(offset) \ -+ (0x000000000000005Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG028(offset) \ -+ (0x0000000000000070ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG029(offset) \ -+ (0x0000000000000074ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG030(offset) \ -+ (0x0000000000000078ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG031(offset) \ -+ (0x000000000000007Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG032(offset) \ -+ (0x0000000000000080ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG033(offset) \ -+ (0x0000000000000084ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG034(offset) \ -+ (0x0000000000000088ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG035(offset) \ -+ (0x000000000000008Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG036(offset) \ -+ (0x0000000000000090ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG037(offset) \ -+ (0x0000000000000094ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG038(offset) \ -+ (0x0000000000000098ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG039(offset) \ -+ (0x000000000000009Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG040(offset) \ -+ (0x00000000000000A0ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG041(offset) \ -+ (0x00000000000000A4ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG042(offset) \ -+ (0x00000000000000A8ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG064(offset) \ -+ (0x0000000000000100ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG065(offset) \ -+ (0x0000000000000104ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG066(offset) \ -+ (0x0000000000000108ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG067(offset) \ -+ (0x000000000000010Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG068(offset) \ -+ (0x0000000000000110ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG069(offset) \ -+ (0x0000000000000114ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG070(offset) \ -+ (0x0000000000000118ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG071(offset) \ -+ (0x000000000000011Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG072(offset) \ -+ (0x0000000000000120ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG073(offset) \ -+ (0x0000000000000124ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG074(offset) \ -+ (0x0000000000000128ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG075(offset) \ -+ (0x000000000000012Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG076(offset) \ -+ (0x0000000000000130ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG077(offset) \ -+ (0x0000000000000134ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG448(offset) \ -+ (0x0000000000000700ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG449(offset) \ -+ (0x0000000000000704ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG450(offset) \ -+ (0x0000000000000708ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG451(offset) \ -+ (0x000000000000070Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG452(offset) \ -+ (0x0000000000000710ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG453(offset) \ -+ (0x0000000000000714ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG454(offset) \ -+ (0x0000000000000718ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG455(offset) \ -+ (0x000000000000071Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG456(offset) \ -+ (0x0000000000000720ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG458(offset) \ -+ (0x0000000000000728ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG459(offset) \ -+ (0x000000000000072Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG460(offset) \ -+ (0x0000000000000730ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG461(offset) \ -+ (0x0000000000000734ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG462(offset) \ -+ (0x0000000000000738ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG463(offset) \ -+ (0x000000000000073Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG464(offset) \ -+ (0x0000000000000740ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG465(offset) \ -+ (0x0000000000000744ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG466(offset) \ -+ (0x0000000000000748ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG467(offset) \ -+ (0x000000000000074Cull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG468(offset) \ -+ (0x0000000000000750ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG490(offset) \ -+ (0x00000000000007A8ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG491(offset) \ -+ (0x00000000000007ACull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG492(offset) \ -+ (0x00000000000007B0ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG516(offset) \ -+ (0x0000000000000810ull + (((offset) & 1) * 0)) -+#define CVMX_PCIERCX_CFG517(offset) \ -+ (0x0000000000000814ull + (((offset) & 1) * 0)) -+ -+union cvmx_pciercx_cfg000 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg000_s { -+ uint32_t devid:16; -+ uint32_t vendid:16; -+ } s; -+ struct cvmx_pciercx_cfg000_s cn52xx; -+ struct cvmx_pciercx_cfg000_s cn52xxp1; -+ struct cvmx_pciercx_cfg000_s cn56xx; -+ struct cvmx_pciercx_cfg000_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg001 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg001_s { -+ uint32_t dpe:1; -+ uint32_t sse:1; -+ uint32_t rma:1; -+ uint32_t rta:1; -+ uint32_t sta:1; -+ uint32_t devt:2; -+ uint32_t mdpe:1; -+ uint32_t fbb:1; -+ uint32_t reserved_22_22:1; -+ uint32_t m66:1; -+ uint32_t cl:1; -+ uint32_t i_stat:1; -+ uint32_t reserved_11_18:8; -+ uint32_t i_dis:1; -+ uint32_t fbbe:1; -+ uint32_t see:1; -+ uint32_t ids_wcc:1; -+ uint32_t per:1; -+ uint32_t vps:1; -+ uint32_t mwice:1; -+ uint32_t scse:1; -+ uint32_t me:1; -+ uint32_t msae:1; -+ uint32_t isae:1; -+ } s; -+ struct cvmx_pciercx_cfg001_s cn52xx; -+ struct cvmx_pciercx_cfg001_s cn52xxp1; -+ struct cvmx_pciercx_cfg001_s cn56xx; -+ struct cvmx_pciercx_cfg001_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg002 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg002_s { -+ uint32_t bcc:8; -+ uint32_t sc:8; -+ uint32_t pi:8; -+ uint32_t rid:8; -+ } s; -+ struct cvmx_pciercx_cfg002_s cn52xx; -+ struct cvmx_pciercx_cfg002_s cn52xxp1; -+ struct cvmx_pciercx_cfg002_s cn56xx; -+ struct cvmx_pciercx_cfg002_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg003 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg003_s { -+ uint32_t bist:8; -+ uint32_t mfd:1; -+ uint32_t chf:7; -+ uint32_t lt:8; -+ uint32_t cls:8; -+ } s; -+ struct cvmx_pciercx_cfg003_s cn52xx; -+ struct cvmx_pciercx_cfg003_s cn52xxp1; -+ struct cvmx_pciercx_cfg003_s cn56xx; -+ struct cvmx_pciercx_cfg003_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg004 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg004_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg004_s cn52xx; -+ struct cvmx_pciercx_cfg004_s cn52xxp1; -+ struct cvmx_pciercx_cfg004_s cn56xx; -+ struct cvmx_pciercx_cfg004_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg005 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg005_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg005_s cn52xx; -+ struct cvmx_pciercx_cfg005_s cn52xxp1; -+ struct cvmx_pciercx_cfg005_s cn56xx; -+ struct cvmx_pciercx_cfg005_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg006 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg006_s { -+ uint32_t slt:8; -+ uint32_t subbnum:8; -+ uint32_t sbnum:8; -+ uint32_t pbnum:8; -+ } s; -+ struct cvmx_pciercx_cfg006_s cn52xx; -+ struct cvmx_pciercx_cfg006_s cn52xxp1; -+ struct cvmx_pciercx_cfg006_s cn56xx; -+ struct cvmx_pciercx_cfg006_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg007 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg007_s { -+ uint32_t dpe:1; -+ uint32_t sse:1; -+ uint32_t rma:1; -+ uint32_t rta:1; -+ uint32_t sta:1; -+ uint32_t devt:2; -+ uint32_t mdpe:1; -+ uint32_t fbb:1; -+ uint32_t reserved_22_22:1; -+ uint32_t m66:1; -+ uint32_t reserved_16_20:5; -+ uint32_t lio_limi:4; -+ uint32_t reserved_9_11:3; -+ uint32_t io32b:1; -+ uint32_t lio_base:4; -+ uint32_t reserved_1_3:3; -+ uint32_t io32a:1; -+ } s; -+ struct cvmx_pciercx_cfg007_s cn52xx; -+ struct cvmx_pciercx_cfg007_s cn52xxp1; -+ struct cvmx_pciercx_cfg007_s cn56xx; -+ struct cvmx_pciercx_cfg007_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg008 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg008_s { -+ uint32_t ml_addr:12; -+ uint32_t reserved_16_19:4; -+ uint32_t mb_addr:12; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pciercx_cfg008_s cn52xx; -+ struct cvmx_pciercx_cfg008_s cn52xxp1; -+ struct cvmx_pciercx_cfg008_s cn56xx; -+ struct cvmx_pciercx_cfg008_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg009 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg009_s { -+ uint32_t lmem_limit:12; -+ uint32_t reserved_17_19:3; -+ uint32_t mem64b:1; -+ uint32_t lmem_base:12; -+ uint32_t reserved_1_3:3; -+ uint32_t mem64a:1; -+ } s; -+ struct cvmx_pciercx_cfg009_s cn52xx; -+ struct cvmx_pciercx_cfg009_s cn52xxp1; -+ struct cvmx_pciercx_cfg009_s cn56xx; -+ struct cvmx_pciercx_cfg009_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg010 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg010_s { -+ uint32_t umem_base:32; -+ } s; -+ struct cvmx_pciercx_cfg010_s cn52xx; -+ struct cvmx_pciercx_cfg010_s cn52xxp1; -+ struct cvmx_pciercx_cfg010_s cn56xx; -+ struct cvmx_pciercx_cfg010_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg011 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg011_s { -+ uint32_t umem_limit:32; -+ } s; -+ struct cvmx_pciercx_cfg011_s cn52xx; -+ struct cvmx_pciercx_cfg011_s cn52xxp1; -+ struct cvmx_pciercx_cfg011_s cn56xx; -+ struct cvmx_pciercx_cfg011_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg012 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg012_s { -+ uint32_t uio_limit:16; -+ uint32_t uio_base:16; -+ } s; -+ struct cvmx_pciercx_cfg012_s cn52xx; -+ struct cvmx_pciercx_cfg012_s cn52xxp1; -+ struct cvmx_pciercx_cfg012_s cn56xx; -+ struct cvmx_pciercx_cfg012_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg013 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg013_s { -+ uint32_t reserved_8_31:24; -+ uint32_t cp:8; -+ } s; -+ struct cvmx_pciercx_cfg013_s cn52xx; -+ struct cvmx_pciercx_cfg013_s cn52xxp1; -+ struct cvmx_pciercx_cfg013_s cn56xx; -+ struct cvmx_pciercx_cfg013_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg014 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg014_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg014_s cn52xx; -+ struct cvmx_pciercx_cfg014_s cn52xxp1; -+ struct cvmx_pciercx_cfg014_s cn56xx; -+ struct cvmx_pciercx_cfg014_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg015 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg015_s { -+ uint32_t reserved_28_31:4; -+ uint32_t dtsees:1; -+ uint32_t dts:1; -+ uint32_t sdt:1; -+ uint32_t pdt:1; -+ uint32_t fbbe:1; -+ uint32_t sbrst:1; -+ uint32_t mam:1; -+ uint32_t vga16d:1; -+ uint32_t vgae:1; -+ uint32_t isae:1; -+ uint32_t see:1; -+ uint32_t pere:1; -+ uint32_t inta:8; -+ uint32_t il:8; -+ } s; -+ struct cvmx_pciercx_cfg015_s cn52xx; -+ struct cvmx_pciercx_cfg015_s cn52xxp1; -+ struct cvmx_pciercx_cfg015_s cn56xx; -+ struct cvmx_pciercx_cfg015_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg016 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg016_s { -+ uint32_t pmes:5; -+ uint32_t d2s:1; -+ uint32_t d1s:1; -+ uint32_t auxc:3; -+ uint32_t dsi:1; -+ uint32_t reserved_20_20:1; -+ uint32_t pme_clock:1; -+ uint32_t pmsv:3; -+ uint32_t ncp:8; -+ uint32_t pmcid:8; -+ } s; -+ struct cvmx_pciercx_cfg016_s cn52xx; -+ struct cvmx_pciercx_cfg016_s cn52xxp1; -+ struct cvmx_pciercx_cfg016_s cn56xx; -+ struct cvmx_pciercx_cfg016_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg017 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg017_s { -+ uint32_t pmdia:8; -+ uint32_t bpccee:1; -+ uint32_t bd3h:1; -+ uint32_t reserved_16_21:6; -+ uint32_t pmess:1; -+ uint32_t pmedsia:2; -+ uint32_t pmds:4; -+ uint32_t pmeens:1; -+ uint32_t reserved_4_7:4; -+ uint32_t nsr:1; -+ uint32_t reserved_2_2:1; -+ uint32_t ps:2; -+ } s; -+ struct cvmx_pciercx_cfg017_s cn52xx; -+ struct cvmx_pciercx_cfg017_s cn52xxp1; -+ struct cvmx_pciercx_cfg017_s cn56xx; -+ struct cvmx_pciercx_cfg017_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg020 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg020_s { -+ uint32_t reserved_24_31:8; -+ uint32_t m64:1; -+ uint32_t mme:3; -+ uint32_t mmc:3; -+ uint32_t msien:1; -+ uint32_t ncp:8; -+ uint32_t msicid:8; -+ } s; -+ struct cvmx_pciercx_cfg020_s cn52xx; -+ struct cvmx_pciercx_cfg020_s cn52xxp1; -+ struct cvmx_pciercx_cfg020_s cn56xx; -+ struct cvmx_pciercx_cfg020_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg021 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg021_s { -+ uint32_t lmsi:30; -+ uint32_t reserved_0_1:2; -+ } s; -+ struct cvmx_pciercx_cfg021_s cn52xx; -+ struct cvmx_pciercx_cfg021_s cn52xxp1; -+ struct cvmx_pciercx_cfg021_s cn56xx; -+ struct cvmx_pciercx_cfg021_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg022 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg022_s { -+ uint32_t umsi:32; -+ } s; -+ struct cvmx_pciercx_cfg022_s cn52xx; -+ struct cvmx_pciercx_cfg022_s cn52xxp1; -+ struct cvmx_pciercx_cfg022_s cn56xx; -+ struct cvmx_pciercx_cfg022_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg023 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg023_s { -+ uint32_t reserved_16_31:16; -+ uint32_t msimd:16; -+ } s; -+ struct cvmx_pciercx_cfg023_s cn52xx; -+ struct cvmx_pciercx_cfg023_s cn52xxp1; -+ struct cvmx_pciercx_cfg023_s cn56xx; -+ struct cvmx_pciercx_cfg023_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg028 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg028_s { -+ uint32_t reserved_30_31:2; -+ uint32_t imn:5; -+ uint32_t si:1; -+ uint32_t dpt:4; -+ uint32_t pciecv:4; -+ uint32_t ncp:8; -+ uint32_t pcieid:8; -+ } s; -+ struct cvmx_pciercx_cfg028_s cn52xx; -+ struct cvmx_pciercx_cfg028_s cn52xxp1; -+ struct cvmx_pciercx_cfg028_s cn56xx; -+ struct cvmx_pciercx_cfg028_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg029 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg029_s { -+ uint32_t reserved_28_31:4; -+ uint32_t cspls:2; -+ uint32_t csplv:8; -+ uint32_t reserved_16_17:2; -+ uint32_t rber:1; -+ uint32_t reserved_12_14:3; -+ uint32_t el1al:3; -+ uint32_t el0al:3; -+ uint32_t etfs:1; -+ uint32_t pfs:2; -+ uint32_t mpss:3; -+ } s; -+ struct cvmx_pciercx_cfg029_s cn52xx; -+ struct cvmx_pciercx_cfg029_s cn52xxp1; -+ struct cvmx_pciercx_cfg029_s cn56xx; -+ struct cvmx_pciercx_cfg029_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg030 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg030_s { -+ uint32_t reserved_22_31:10; -+ uint32_t tp:1; -+ uint32_t ap_d:1; -+ uint32_t ur_d:1; -+ uint32_t fe_d:1; -+ uint32_t nfe_d:1; -+ uint32_t ce_d:1; -+ uint32_t reserved_15_15:1; -+ uint32_t mrrs:3; -+ uint32_t ns_en:1; -+ uint32_t ap_en:1; -+ uint32_t pf_en:1; -+ uint32_t etf_en:1; -+ uint32_t mps:3; -+ uint32_t ro_en:1; -+ uint32_t ur_en:1; -+ uint32_t fe_en:1; -+ uint32_t nfe_en:1; -+ uint32_t ce_en:1; -+ } s; -+ struct cvmx_pciercx_cfg030_s cn52xx; -+ struct cvmx_pciercx_cfg030_s cn52xxp1; -+ struct cvmx_pciercx_cfg030_s cn56xx; -+ struct cvmx_pciercx_cfg030_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg031 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg031_s { -+ uint32_t pnum:8; -+ uint32_t reserved_22_23:2; -+ uint32_t lbnc:1; -+ uint32_t dllarc:1; -+ uint32_t sderc:1; -+ uint32_t cpm:1; -+ uint32_t l1el:3; -+ uint32_t l0el:3; -+ uint32_t aslpms:2; -+ uint32_t mlw:6; -+ uint32_t mls:4; -+ } s; -+ struct cvmx_pciercx_cfg031_s cn52xx; -+ struct cvmx_pciercx_cfg031_s cn52xxp1; -+ struct cvmx_pciercx_cfg031_s cn56xx; -+ struct cvmx_pciercx_cfg031_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg032 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg032_s { -+ uint32_t lab:1; -+ uint32_t lbm:1; -+ uint32_t dlla:1; -+ uint32_t scc:1; -+ uint32_t lt:1; -+ uint32_t reserved_26_26:1; -+ uint32_t nlw:6; -+ uint32_t ls:4; -+ uint32_t reserved_12_15:4; -+ uint32_t lab_int_enb:1; -+ uint32_t lbm_int_enb:1; -+ uint32_t hawd:1; -+ uint32_t ecpm:1; -+ uint32_t es:1; -+ uint32_t ccc:1; -+ uint32_t rl:1; -+ uint32_t ld:1; -+ uint32_t rcb:1; -+ uint32_t reserved_2_2:1; -+ uint32_t aslpc:2; -+ } s; -+ struct cvmx_pciercx_cfg032_s cn52xx; -+ struct cvmx_pciercx_cfg032_s cn52xxp1; -+ struct cvmx_pciercx_cfg032_s cn56xx; -+ struct cvmx_pciercx_cfg032_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg033 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg033_s { -+ uint32_t ps_num:13; -+ uint32_t nccs:1; -+ uint32_t emip:1; -+ uint32_t sp_ls:2; -+ uint32_t sp_lv:8; -+ uint32_t hp_c:1; -+ uint32_t hp_s:1; -+ uint32_t pip:1; -+ uint32_t aip:1; -+ uint32_t mrlsp:1; -+ uint32_t pcp:1; -+ uint32_t abp:1; -+ } s; -+ struct cvmx_pciercx_cfg033_s cn52xx; -+ struct cvmx_pciercx_cfg033_s cn52xxp1; -+ struct cvmx_pciercx_cfg033_s cn56xx; -+ struct cvmx_pciercx_cfg033_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg034 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg034_s { -+ uint32_t reserved_25_31:7; -+ uint32_t dlls_c:1; -+ uint32_t emis:1; -+ uint32_t pds:1; -+ uint32_t mrlss:1; -+ uint32_t ccint_d:1; -+ uint32_t pd_c:1; -+ uint32_t mrls_c:1; -+ uint32_t pf_d:1; -+ uint32_t abp_d:1; -+ uint32_t reserved_13_15:3; -+ uint32_t dlls_en:1; -+ uint32_t emic:1; -+ uint32_t pcc:1; -+ uint32_t pic:2; -+ uint32_t aic:2; -+ uint32_t hpint_en:1; -+ uint32_t ccint_en:1; -+ uint32_t pd_en:1; -+ uint32_t mrls_en:1; -+ uint32_t pf_en:1; -+ uint32_t abp_en:1; -+ } s; -+ struct cvmx_pciercx_cfg034_s cn52xx; -+ struct cvmx_pciercx_cfg034_s cn52xxp1; -+ struct cvmx_pciercx_cfg034_s cn56xx; -+ struct cvmx_pciercx_cfg034_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg035 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg035_s { -+ uint32_t reserved_17_31:15; -+ uint32_t crssv:1; -+ uint32_t reserved_5_15:11; -+ uint32_t crssve:1; -+ uint32_t pmeie:1; -+ uint32_t sefee:1; -+ uint32_t senfee:1; -+ uint32_t secee:1; -+ } s; -+ struct cvmx_pciercx_cfg035_s cn52xx; -+ struct cvmx_pciercx_cfg035_s cn52xxp1; -+ struct cvmx_pciercx_cfg035_s cn56xx; -+ struct cvmx_pciercx_cfg035_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg036 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg036_s { -+ uint32_t reserved_18_31:14; -+ uint32_t pme_pend:1; -+ uint32_t pme_stat:1; -+ uint32_t pme_rid:16; -+ } s; -+ struct cvmx_pciercx_cfg036_s cn52xx; -+ struct cvmx_pciercx_cfg036_s cn52xxp1; -+ struct cvmx_pciercx_cfg036_s cn56xx; -+ struct cvmx_pciercx_cfg036_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg037 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg037_s { -+ uint32_t reserved_5_31:27; -+ uint32_t ctds:1; -+ uint32_t ctrs:4; -+ } s; -+ struct cvmx_pciercx_cfg037_s cn52xx; -+ struct cvmx_pciercx_cfg037_s cn52xxp1; -+ struct cvmx_pciercx_cfg037_s cn56xx; -+ struct cvmx_pciercx_cfg037_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg038 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg038_s { -+ uint32_t reserved_5_31:27; -+ uint32_t ctd:1; -+ uint32_t ctv:4; -+ } s; -+ struct cvmx_pciercx_cfg038_s cn52xx; -+ struct cvmx_pciercx_cfg038_s cn52xxp1; -+ struct cvmx_pciercx_cfg038_s cn56xx; -+ struct cvmx_pciercx_cfg038_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg039 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg039_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg039_s cn52xx; -+ struct cvmx_pciercx_cfg039_s cn52xxp1; -+ struct cvmx_pciercx_cfg039_s cn56xx; -+ struct cvmx_pciercx_cfg039_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg040 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg040_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg040_s cn52xx; -+ struct cvmx_pciercx_cfg040_s cn52xxp1; -+ struct cvmx_pciercx_cfg040_s cn56xx; -+ struct cvmx_pciercx_cfg040_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg041 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg041_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg041_s cn52xx; -+ struct cvmx_pciercx_cfg041_s cn52xxp1; -+ struct cvmx_pciercx_cfg041_s cn56xx; -+ struct cvmx_pciercx_cfg041_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg042 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg042_s { -+ uint32_t reserved_0_31:32; -+ } s; -+ struct cvmx_pciercx_cfg042_s cn52xx; -+ struct cvmx_pciercx_cfg042_s cn52xxp1; -+ struct cvmx_pciercx_cfg042_s cn56xx; -+ struct cvmx_pciercx_cfg042_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg064 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg064_s { -+ uint32_t nco:12; -+ uint32_t cv:4; -+ uint32_t pcieec:16; -+ } s; -+ struct cvmx_pciercx_cfg064_s cn52xx; -+ struct cvmx_pciercx_cfg064_s cn52xxp1; -+ struct cvmx_pciercx_cfg064_s cn56xx; -+ struct cvmx_pciercx_cfg064_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg065 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg065_s { -+ uint32_t reserved_21_31:11; -+ uint32_t ures:1; -+ uint32_t ecrces:1; -+ uint32_t mtlps:1; -+ uint32_t ros:1; -+ uint32_t ucs:1; -+ uint32_t cas:1; -+ uint32_t cts:1; -+ uint32_t fcpes:1; -+ uint32_t ptlps:1; -+ uint32_t reserved_6_11:6; -+ uint32_t sdes:1; -+ uint32_t dlpes:1; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pciercx_cfg065_s cn52xx; -+ struct cvmx_pciercx_cfg065_s cn52xxp1; -+ struct cvmx_pciercx_cfg065_s cn56xx; -+ struct cvmx_pciercx_cfg065_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg066 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg066_s { -+ uint32_t reserved_21_31:11; -+ uint32_t urem:1; -+ uint32_t ecrcem:1; -+ uint32_t mtlpm:1; -+ uint32_t rom:1; -+ uint32_t ucm:1; -+ uint32_t cam:1; -+ uint32_t ctm:1; -+ uint32_t fcpem:1; -+ uint32_t ptlpm:1; -+ uint32_t reserved_6_11:6; -+ uint32_t sdem:1; -+ uint32_t dlpem:1; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pciercx_cfg066_s cn52xx; -+ struct cvmx_pciercx_cfg066_s cn52xxp1; -+ struct cvmx_pciercx_cfg066_s cn56xx; -+ struct cvmx_pciercx_cfg066_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg067 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg067_s { -+ uint32_t reserved_21_31:11; -+ uint32_t ures:1; -+ uint32_t ecrces:1; -+ uint32_t mtlps:1; -+ uint32_t ros:1; -+ uint32_t ucs:1; -+ uint32_t cas:1; -+ uint32_t cts:1; -+ uint32_t fcpes:1; -+ uint32_t ptlps:1; -+ uint32_t reserved_6_11:6; -+ uint32_t sdes:1; -+ uint32_t dlpes:1; -+ uint32_t reserved_0_3:4; -+ } s; -+ struct cvmx_pciercx_cfg067_s cn52xx; -+ struct cvmx_pciercx_cfg067_s cn52xxp1; -+ struct cvmx_pciercx_cfg067_s cn56xx; -+ struct cvmx_pciercx_cfg067_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg068 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg068_s { -+ uint32_t reserved_14_31:18; -+ uint32_t anfes:1; -+ uint32_t rtts:1; -+ uint32_t reserved_9_11:3; -+ uint32_t rnrs:1; -+ uint32_t bdllps:1; -+ uint32_t btlps:1; -+ uint32_t reserved_1_5:5; -+ uint32_t res:1; -+ } s; -+ struct cvmx_pciercx_cfg068_s cn52xx; -+ struct cvmx_pciercx_cfg068_s cn52xxp1; -+ struct cvmx_pciercx_cfg068_s cn56xx; -+ struct cvmx_pciercx_cfg068_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg069 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg069_s { -+ uint32_t reserved_14_31:18; -+ uint32_t anfem:1; -+ uint32_t rttm:1; -+ uint32_t reserved_9_11:3; -+ uint32_t rnrm:1; -+ uint32_t bdllpm:1; -+ uint32_t btlpm:1; -+ uint32_t reserved_1_5:5; -+ uint32_t rem:1; -+ } s; -+ struct cvmx_pciercx_cfg069_s cn52xx; -+ struct cvmx_pciercx_cfg069_s cn52xxp1; -+ struct cvmx_pciercx_cfg069_s cn56xx; -+ struct cvmx_pciercx_cfg069_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg070 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg070_s { -+ uint32_t reserved_9_31:23; -+ uint32_t ce:1; -+ uint32_t cc:1; -+ uint32_t ge:1; -+ uint32_t gc:1; -+ uint32_t fep:5; -+ } s; -+ struct cvmx_pciercx_cfg070_s cn52xx; -+ struct cvmx_pciercx_cfg070_s cn52xxp1; -+ struct cvmx_pciercx_cfg070_s cn56xx; -+ struct cvmx_pciercx_cfg070_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg071 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg071_s { -+ uint32_t dword1:32; -+ } s; -+ struct cvmx_pciercx_cfg071_s cn52xx; -+ struct cvmx_pciercx_cfg071_s cn52xxp1; -+ struct cvmx_pciercx_cfg071_s cn56xx; -+ struct cvmx_pciercx_cfg071_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg072 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg072_s { -+ uint32_t dword2:32; -+ } s; -+ struct cvmx_pciercx_cfg072_s cn52xx; -+ struct cvmx_pciercx_cfg072_s cn52xxp1; -+ struct cvmx_pciercx_cfg072_s cn56xx; -+ struct cvmx_pciercx_cfg072_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg073 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg073_s { -+ uint32_t dword3:32; -+ } s; -+ struct cvmx_pciercx_cfg073_s cn52xx; -+ struct cvmx_pciercx_cfg073_s cn52xxp1; -+ struct cvmx_pciercx_cfg073_s cn56xx; -+ struct cvmx_pciercx_cfg073_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg074 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg074_s { -+ uint32_t dword4:32; -+ } s; -+ struct cvmx_pciercx_cfg074_s cn52xx; -+ struct cvmx_pciercx_cfg074_s cn52xxp1; -+ struct cvmx_pciercx_cfg074_s cn56xx; -+ struct cvmx_pciercx_cfg074_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg075 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg075_s { -+ uint32_t reserved_3_31:29; -+ uint32_t fere:1; -+ uint32_t nfere:1; -+ uint32_t cere:1; -+ } s; -+ struct cvmx_pciercx_cfg075_s cn52xx; -+ struct cvmx_pciercx_cfg075_s cn52xxp1; -+ struct cvmx_pciercx_cfg075_s cn56xx; -+ struct cvmx_pciercx_cfg075_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg076 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg076_s { -+ uint32_t aeimn:5; -+ uint32_t reserved_7_26:20; -+ uint32_t femr:1; -+ uint32_t nfemr:1; -+ uint32_t fuf:1; -+ uint32_t multi_efnfr:1; -+ uint32_t efnfr:1; -+ uint32_t multi_ecr:1; -+ uint32_t ecr:1; -+ } s; -+ struct cvmx_pciercx_cfg076_s cn52xx; -+ struct cvmx_pciercx_cfg076_s cn52xxp1; -+ struct cvmx_pciercx_cfg076_s cn56xx; -+ struct cvmx_pciercx_cfg076_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg077 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg077_s { -+ uint32_t efnfsi:16; -+ uint32_t ecsi:16; -+ } s; -+ struct cvmx_pciercx_cfg077_s cn52xx; -+ struct cvmx_pciercx_cfg077_s cn52xxp1; -+ struct cvmx_pciercx_cfg077_s cn56xx; -+ struct cvmx_pciercx_cfg077_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg448 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg448_s { -+ uint32_t rtl:16; -+ uint32_t rtltl:16; -+ } s; -+ struct cvmx_pciercx_cfg448_s cn52xx; -+ struct cvmx_pciercx_cfg448_s cn52xxp1; -+ struct cvmx_pciercx_cfg448_s cn56xx; -+ struct cvmx_pciercx_cfg448_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg449 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg449_s { -+ uint32_t omr:32; -+ } s; -+ struct cvmx_pciercx_cfg449_s cn52xx; -+ struct cvmx_pciercx_cfg449_s cn52xxp1; -+ struct cvmx_pciercx_cfg449_s cn56xx; -+ struct cvmx_pciercx_cfg449_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg450 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg450_s { -+ uint32_t lpec:8; -+ uint32_t reserved_22_23:2; -+ uint32_t link_state:6; -+ uint32_t force_link:1; -+ uint32_t reserved_8_14:7; -+ uint32_t link_num:8; -+ } s; -+ struct cvmx_pciercx_cfg450_s cn52xx; -+ struct cvmx_pciercx_cfg450_s cn52xxp1; -+ struct cvmx_pciercx_cfg450_s cn56xx; -+ struct cvmx_pciercx_cfg450_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg451 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg451_s { -+ uint32_t reserved_30_31:2; -+ uint32_t l1el:3; -+ uint32_t l0el:3; -+ uint32_t n_fts_cc:8; -+ uint32_t n_fts:8; -+ uint32_t ack_freq:8; -+ } s; -+ struct cvmx_pciercx_cfg451_s cn52xx; -+ struct cvmx_pciercx_cfg451_s cn52xxp1; -+ struct cvmx_pciercx_cfg451_s cn56xx; -+ struct cvmx_pciercx_cfg451_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg452 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg452_s { -+ uint32_t reserved_26_31:6; -+ uint32_t eccrc:1; -+ uint32_t reserved_22_24:3; -+ uint32_t lme:6; -+ uint32_t reserved_8_15:8; -+ uint32_t flm:1; -+ uint32_t reserved_6_6:1; -+ uint32_t dllle:1; -+ uint32_t reserved_4_4:1; -+ uint32_t ra:1; -+ uint32_t le:1; -+ uint32_t sd:1; -+ uint32_t omr:1; -+ } s; -+ struct cvmx_pciercx_cfg452_s cn52xx; -+ struct cvmx_pciercx_cfg452_s cn52xxp1; -+ struct cvmx_pciercx_cfg452_s cn56xx; -+ struct cvmx_pciercx_cfg452_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg453 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg453_s { -+ uint32_t dlld:1; -+ uint32_t reserved_26_30:5; -+ uint32_t ack_nak:1; -+ uint32_t fcd:1; -+ uint32_t ilst:24; -+ } s; -+ struct cvmx_pciercx_cfg453_s cn52xx; -+ struct cvmx_pciercx_cfg453_s cn52xxp1; -+ struct cvmx_pciercx_cfg453_s cn56xx; -+ struct cvmx_pciercx_cfg453_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg454 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg454_s { -+ uint32_t reserved_29_31:3; -+ uint32_t tmfcwt:5; -+ uint32_t tmanlt:5; -+ uint32_t tmrt:5; -+ uint32_t reserved_11_13:3; -+ uint32_t nskps:3; -+ uint32_t reserved_4_7:4; -+ uint32_t ntss:4; -+ } s; -+ struct cvmx_pciercx_cfg454_s cn52xx; -+ struct cvmx_pciercx_cfg454_s cn52xxp1; -+ struct cvmx_pciercx_cfg454_s cn56xx; -+ struct cvmx_pciercx_cfg454_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg455 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg455_s { -+ uint32_t m_cfg0_filt:1; -+ uint32_t m_io_filt:1; -+ uint32_t msg_ctrl:1; -+ uint32_t m_cpl_ecrc_filt:1; -+ uint32_t m_ecrc_filt:1; -+ uint32_t m_cpl_len_err:1; -+ uint32_t m_cpl_attr_err:1; -+ uint32_t m_cpl_tc_err:1; -+ uint32_t m_cpl_fun_err:1; -+ uint32_t m_cpl_rid_err:1; -+ uint32_t m_cpl_tag_err:1; -+ uint32_t m_lk_filt:1; -+ uint32_t m_cfg1_filt:1; -+ uint32_t m_bar_match:1; -+ uint32_t m_pois_filt:1; -+ uint32_t m_fun:1; -+ uint32_t dfcwt:1; -+ uint32_t reserved_11_14:4; -+ uint32_t skpiv:11; -+ } s; -+ struct cvmx_pciercx_cfg455_s cn52xx; -+ struct cvmx_pciercx_cfg455_s cn52xxp1; -+ struct cvmx_pciercx_cfg455_s cn56xx; -+ struct cvmx_pciercx_cfg455_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg456 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg456_s { -+ uint32_t reserved_2_31:30; -+ uint32_t m_vend1_drp:1; -+ uint32_t m_vend0_drp:1; -+ } s; -+ struct cvmx_pciercx_cfg456_s cn52xx; -+ struct cvmx_pciercx_cfg456_s cn52xxp1; -+ struct cvmx_pciercx_cfg456_s cn56xx; -+ struct cvmx_pciercx_cfg456_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg458 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg458_s { -+ uint32_t dbg_info_l32:32; -+ } s; -+ struct cvmx_pciercx_cfg458_s cn52xx; -+ struct cvmx_pciercx_cfg458_s cn52xxp1; -+ struct cvmx_pciercx_cfg458_s cn56xx; -+ struct cvmx_pciercx_cfg458_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg459 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg459_s { -+ uint32_t dbg_info_u32:32; -+ } s; -+ struct cvmx_pciercx_cfg459_s cn52xx; -+ struct cvmx_pciercx_cfg459_s cn52xxp1; -+ struct cvmx_pciercx_cfg459_s cn56xx; -+ struct cvmx_pciercx_cfg459_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg460 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg460_s { -+ uint32_t reserved_20_31:12; -+ uint32_t tphfcc:8; -+ uint32_t tpdfcc:12; -+ } s; -+ struct cvmx_pciercx_cfg460_s cn52xx; -+ struct cvmx_pciercx_cfg460_s cn52xxp1; -+ struct cvmx_pciercx_cfg460_s cn56xx; -+ struct cvmx_pciercx_cfg460_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg461 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg461_s { -+ uint32_t reserved_20_31:12; -+ uint32_t tchfcc:8; -+ uint32_t tcdfcc:12; -+ } s; -+ struct cvmx_pciercx_cfg461_s cn52xx; -+ struct cvmx_pciercx_cfg461_s cn52xxp1; -+ struct cvmx_pciercx_cfg461_s cn56xx; -+ struct cvmx_pciercx_cfg461_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg462 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg462_s { -+ uint32_t reserved_20_31:12; -+ uint32_t tchfcc:8; -+ uint32_t tcdfcc:12; -+ } s; -+ struct cvmx_pciercx_cfg462_s cn52xx; -+ struct cvmx_pciercx_cfg462_s cn52xxp1; -+ struct cvmx_pciercx_cfg462_s cn56xx; -+ struct cvmx_pciercx_cfg462_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg463 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg463_s { -+ uint32_t reserved_3_31:29; -+ uint32_t rqne:1; -+ uint32_t trbne:1; -+ uint32_t rtlpfccnr:1; -+ } s; -+ struct cvmx_pciercx_cfg463_s cn52xx; -+ struct cvmx_pciercx_cfg463_s cn52xxp1; -+ struct cvmx_pciercx_cfg463_s cn56xx; -+ struct cvmx_pciercx_cfg463_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg464 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg464_s { -+ uint32_t wrr_vc3:8; -+ uint32_t wrr_vc2:8; -+ uint32_t wrr_vc1:8; -+ uint32_t wrr_vc0:8; -+ } s; -+ struct cvmx_pciercx_cfg464_s cn52xx; -+ struct cvmx_pciercx_cfg464_s cn52xxp1; -+ struct cvmx_pciercx_cfg464_s cn56xx; -+ struct cvmx_pciercx_cfg464_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg465 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg465_s { -+ uint32_t wrr_vc7:8; -+ uint32_t wrr_vc6:8; -+ uint32_t wrr_vc5:8; -+ uint32_t wrr_vc4:8; -+ } s; -+ struct cvmx_pciercx_cfg465_s cn52xx; -+ struct cvmx_pciercx_cfg465_s cn52xxp1; -+ struct cvmx_pciercx_cfg465_s cn56xx; -+ struct cvmx_pciercx_cfg465_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg466 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg466_s { -+ uint32_t rx_queue_order:1; -+ uint32_t type_ordering:1; -+ uint32_t reserved_24_29:6; -+ uint32_t queue_mode:3; -+ uint32_t reserved_20_20:1; -+ uint32_t header_credits:8; -+ uint32_t data_credits:12; -+ } s; -+ struct cvmx_pciercx_cfg466_s cn52xx; -+ struct cvmx_pciercx_cfg466_s cn52xxp1; -+ struct cvmx_pciercx_cfg466_s cn56xx; -+ struct cvmx_pciercx_cfg466_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg467 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg467_s { -+ uint32_t reserved_24_31:8; -+ uint32_t queue_mode:3; -+ uint32_t reserved_20_20:1; -+ uint32_t header_credits:8; -+ uint32_t data_credits:12; -+ } s; -+ struct cvmx_pciercx_cfg467_s cn52xx; -+ struct cvmx_pciercx_cfg467_s cn52xxp1; -+ struct cvmx_pciercx_cfg467_s cn56xx; -+ struct cvmx_pciercx_cfg467_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg468 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg468_s { -+ uint32_t reserved_24_31:8; -+ uint32_t queue_mode:3; -+ uint32_t reserved_20_20:1; -+ uint32_t header_credits:8; -+ uint32_t data_credits:12; -+ } s; -+ struct cvmx_pciercx_cfg468_s cn52xx; -+ struct cvmx_pciercx_cfg468_s cn52xxp1; -+ struct cvmx_pciercx_cfg468_s cn56xx; -+ struct cvmx_pciercx_cfg468_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg490 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg490_s { -+ uint32_t reserved_26_31:6; -+ uint32_t header_depth:10; -+ uint32_t reserved_14_15:2; -+ uint32_t data_depth:14; -+ } s; -+ struct cvmx_pciercx_cfg490_s cn52xx; -+ struct cvmx_pciercx_cfg490_s cn52xxp1; -+ struct cvmx_pciercx_cfg490_s cn56xx; -+ struct cvmx_pciercx_cfg490_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg491 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg491_s { -+ uint32_t reserved_26_31:6; -+ uint32_t header_depth:10; -+ uint32_t reserved_14_15:2; -+ uint32_t data_depth:14; -+ } s; -+ struct cvmx_pciercx_cfg491_s cn52xx; -+ struct cvmx_pciercx_cfg491_s cn52xxp1; -+ struct cvmx_pciercx_cfg491_s cn56xx; -+ struct cvmx_pciercx_cfg491_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg492 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg492_s { -+ uint32_t reserved_26_31:6; -+ uint32_t header_depth:10; -+ uint32_t reserved_14_15:2; -+ uint32_t data_depth:14; -+ } s; -+ struct cvmx_pciercx_cfg492_s cn52xx; -+ struct cvmx_pciercx_cfg492_s cn52xxp1; -+ struct cvmx_pciercx_cfg492_s cn56xx; -+ struct cvmx_pciercx_cfg492_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg516 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg516_s { -+ uint32_t phy_stat:32; -+ } s; -+ struct cvmx_pciercx_cfg516_s cn52xx; -+ struct cvmx_pciercx_cfg516_s cn52xxp1; -+ struct cvmx_pciercx_cfg516_s cn56xx; -+ struct cvmx_pciercx_cfg516_s cn56xxp1; -+}; -+ -+union cvmx_pciercx_cfg517 { -+ uint32_t u32; -+ struct cvmx_pciercx_cfg517_s { -+ uint32_t phy_ctrl:32; -+ } s; -+ struct cvmx_pciercx_cfg517_s cn52xx; -+ struct cvmx_pciercx_cfg517_s cn52xxp1; -+ struct cvmx_pciercx_cfg517_s cn56xx; -+ struct cvmx_pciercx_cfg517_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-pescx-defs.h -@@ -0,0 +1,410 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PESCX_DEFS_H__ -+#define __CVMX_PESCX_DEFS_H__ -+ -+#define CVMX_PESCX_BIST_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000018ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_BIST_STATUS2(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000418ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_CFG_RD(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000030ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_CFG_WR(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000028ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_CPL_LUT_VALID(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000098ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_CTL_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000000ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_CTL_STATUS2(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000400ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_DBG_INFO(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000008ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_DBG_INFO_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C80000A0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_DIAG_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000020ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_P2N_BAR0_START(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000080ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_P2N_BAR1_START(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000088ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_P2N_BAR2_START(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000090ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_P2P_BARX_END(offset,block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000048ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_P2P_BARX_START(offset,block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000040ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PESCX_TLP_CREDITS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800C8000038ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_pescx_bist_status { -+ uint64_t u64; -+ struct cvmx_pescx_bist_status_s { -+ uint64_t reserved_13_63:51; -+ uint64_t rqdata5:1; -+ uint64_t ctlp_or:1; -+ uint64_t ntlp_or:1; -+ uint64_t ptlp_or:1; -+ uint64_t retry:1; -+ uint64_t rqdata0:1; -+ uint64_t rqdata1:1; -+ uint64_t rqdata2:1; -+ uint64_t rqdata3:1; -+ uint64_t rqdata4:1; -+ uint64_t rqhdr1:1; -+ uint64_t rqhdr0:1; -+ uint64_t sot:1; -+ } s; -+ struct cvmx_pescx_bist_status_s cn52xx; -+ struct cvmx_pescx_bist_status_cn52xxp1 { -+ uint64_t reserved_12_63:52; -+ uint64_t ctlp_or:1; -+ uint64_t ntlp_or:1; -+ uint64_t ptlp_or:1; -+ uint64_t retry:1; -+ uint64_t rqdata0:1; -+ uint64_t rqdata1:1; -+ uint64_t rqdata2:1; -+ uint64_t rqdata3:1; -+ uint64_t rqdata4:1; -+ uint64_t rqhdr1:1; -+ uint64_t rqhdr0:1; -+ uint64_t sot:1; -+ } cn52xxp1; -+ struct cvmx_pescx_bist_status_s cn56xx; -+ struct cvmx_pescx_bist_status_cn52xxp1 cn56xxp1; -+}; -+ -+union cvmx_pescx_bist_status2 { -+ uint64_t u64; -+ struct cvmx_pescx_bist_status2_s { -+ uint64_t reserved_14_63:50; -+ uint64_t cto_p2e:1; -+ uint64_t e2p_cpl:1; -+ uint64_t e2p_n:1; -+ uint64_t e2p_p:1; -+ uint64_t e2p_rsl:1; -+ uint64_t dbg_p2e:1; -+ uint64_t peai_p2e:1; -+ uint64_t rsl_p2e:1; -+ uint64_t pef_tpf1:1; -+ uint64_t pef_tpf0:1; -+ uint64_t pef_tnf:1; -+ uint64_t pef_tcf1:1; -+ uint64_t pef_tc0:1; -+ uint64_t ppf:1; -+ } s; -+ struct cvmx_pescx_bist_status2_s cn52xx; -+ struct cvmx_pescx_bist_status2_s cn52xxp1; -+ struct cvmx_pescx_bist_status2_s cn56xx; -+ struct cvmx_pescx_bist_status2_s cn56xxp1; -+}; -+ -+union cvmx_pescx_cfg_rd { -+ uint64_t u64; -+ struct cvmx_pescx_cfg_rd_s { -+ uint64_t data:32; -+ uint64_t addr:32; -+ } s; -+ struct cvmx_pescx_cfg_rd_s cn52xx; -+ struct cvmx_pescx_cfg_rd_s cn52xxp1; -+ struct cvmx_pescx_cfg_rd_s cn56xx; -+ struct cvmx_pescx_cfg_rd_s cn56xxp1; -+}; -+ -+union cvmx_pescx_cfg_wr { -+ uint64_t u64; -+ struct cvmx_pescx_cfg_wr_s { -+ uint64_t data:32; -+ uint64_t addr:32; -+ } s; -+ struct cvmx_pescx_cfg_wr_s cn52xx; -+ struct cvmx_pescx_cfg_wr_s cn52xxp1; -+ struct cvmx_pescx_cfg_wr_s cn56xx; -+ struct cvmx_pescx_cfg_wr_s cn56xxp1; -+}; -+ -+union cvmx_pescx_cpl_lut_valid { -+ uint64_t u64; -+ struct cvmx_pescx_cpl_lut_valid_s { -+ uint64_t reserved_32_63:32; -+ uint64_t tag:32; -+ } s; -+ struct cvmx_pescx_cpl_lut_valid_s cn52xx; -+ struct cvmx_pescx_cpl_lut_valid_s cn52xxp1; -+ struct cvmx_pescx_cpl_lut_valid_s cn56xx; -+ struct cvmx_pescx_cpl_lut_valid_s cn56xxp1; -+}; -+ -+union cvmx_pescx_ctl_status { -+ uint64_t u64; -+ struct cvmx_pescx_ctl_status_s { -+ uint64_t reserved_28_63:36; -+ uint64_t dnum:5; -+ uint64_t pbus:8; -+ uint64_t qlm_cfg:2; -+ uint64_t lane_swp:1; -+ uint64_t pm_xtoff:1; -+ uint64_t pm_xpme:1; -+ uint64_t ob_p_cmd:1; -+ uint64_t reserved_7_8:2; -+ uint64_t nf_ecrc:1; -+ uint64_t dly_one:1; -+ uint64_t lnk_enb:1; -+ uint64_t ro_ctlp:1; -+ uint64_t reserved_2_2:1; -+ uint64_t inv_ecrc:1; -+ uint64_t inv_lcrc:1; -+ } s; -+ struct cvmx_pescx_ctl_status_s cn52xx; -+ struct cvmx_pescx_ctl_status_s cn52xxp1; -+ struct cvmx_pescx_ctl_status_cn56xx { -+ uint64_t reserved_28_63:36; -+ uint64_t dnum:5; -+ uint64_t pbus:8; -+ uint64_t qlm_cfg:2; -+ uint64_t reserved_12_12:1; -+ uint64_t pm_xtoff:1; -+ uint64_t pm_xpme:1; -+ uint64_t ob_p_cmd:1; -+ uint64_t reserved_7_8:2; -+ uint64_t nf_ecrc:1; -+ uint64_t dly_one:1; -+ uint64_t lnk_enb:1; -+ uint64_t ro_ctlp:1; -+ uint64_t reserved_2_2:1; -+ uint64_t inv_ecrc:1; -+ uint64_t inv_lcrc:1; -+ } cn56xx; -+ struct cvmx_pescx_ctl_status_cn56xx cn56xxp1; -+}; -+ -+union cvmx_pescx_ctl_status2 { -+ uint64_t u64; -+ struct cvmx_pescx_ctl_status2_s { -+ uint64_t reserved_2_63:62; -+ uint64_t pclk_run:1; -+ uint64_t pcierst:1; -+ } s; -+ struct cvmx_pescx_ctl_status2_s cn52xx; -+ struct cvmx_pescx_ctl_status2_cn52xxp1 { -+ uint64_t reserved_1_63:63; -+ uint64_t pcierst:1; -+ } cn52xxp1; -+ struct cvmx_pescx_ctl_status2_s cn56xx; -+ struct cvmx_pescx_ctl_status2_cn52xxp1 cn56xxp1; -+}; -+ -+union cvmx_pescx_dbg_info { -+ uint64_t u64; -+ struct cvmx_pescx_dbg_info_s { -+ uint64_t reserved_31_63:33; -+ uint64_t ecrc_e:1; -+ uint64_t rawwpp:1; -+ uint64_t racpp:1; -+ uint64_t ramtlp:1; -+ uint64_t rarwdns:1; -+ uint64_t caar:1; -+ uint64_t racca:1; -+ uint64_t racur:1; -+ uint64_t rauc:1; -+ uint64_t rqo:1; -+ uint64_t fcuv:1; -+ uint64_t rpe:1; -+ uint64_t fcpvwt:1; -+ uint64_t dpeoosd:1; -+ uint64_t rtwdle:1; -+ uint64_t rdwdle:1; -+ uint64_t mre:1; -+ uint64_t rte:1; -+ uint64_t acto:1; -+ uint64_t rvdm:1; -+ uint64_t rumep:1; -+ uint64_t rptamrc:1; -+ uint64_t rpmerc:1; -+ uint64_t rfemrc:1; -+ uint64_t rnfemrc:1; -+ uint64_t rcemrc:1; -+ uint64_t rpoison:1; -+ uint64_t recrce:1; -+ uint64_t rtlplle:1; -+ uint64_t rtlpmal:1; -+ uint64_t spoison:1; -+ } s; -+ struct cvmx_pescx_dbg_info_s cn52xx; -+ struct cvmx_pescx_dbg_info_s cn52xxp1; -+ struct cvmx_pescx_dbg_info_s cn56xx; -+ struct cvmx_pescx_dbg_info_s cn56xxp1; -+}; -+ -+union cvmx_pescx_dbg_info_en { -+ uint64_t u64; -+ struct cvmx_pescx_dbg_info_en_s { -+ uint64_t reserved_31_63:33; -+ uint64_t ecrc_e:1; -+ uint64_t rawwpp:1; -+ uint64_t racpp:1; -+ uint64_t ramtlp:1; -+ uint64_t rarwdns:1; -+ uint64_t caar:1; -+ uint64_t racca:1; -+ uint64_t racur:1; -+ uint64_t rauc:1; -+ uint64_t rqo:1; -+ uint64_t fcuv:1; -+ uint64_t rpe:1; -+ uint64_t fcpvwt:1; -+ uint64_t dpeoosd:1; -+ uint64_t rtwdle:1; -+ uint64_t rdwdle:1; -+ uint64_t mre:1; -+ uint64_t rte:1; -+ uint64_t acto:1; -+ uint64_t rvdm:1; -+ uint64_t rumep:1; -+ uint64_t rptamrc:1; -+ uint64_t rpmerc:1; -+ uint64_t rfemrc:1; -+ uint64_t rnfemrc:1; -+ uint64_t rcemrc:1; -+ uint64_t rpoison:1; -+ uint64_t recrce:1; -+ uint64_t rtlplle:1; -+ uint64_t rtlpmal:1; -+ uint64_t spoison:1; -+ } s; -+ struct cvmx_pescx_dbg_info_en_s cn52xx; -+ struct cvmx_pescx_dbg_info_en_s cn52xxp1; -+ struct cvmx_pescx_dbg_info_en_s cn56xx; -+ struct cvmx_pescx_dbg_info_en_s cn56xxp1; -+}; -+ -+union cvmx_pescx_diag_status { -+ uint64_t u64; -+ struct cvmx_pescx_diag_status_s { -+ uint64_t reserved_4_63:60; -+ uint64_t pm_dst:1; -+ uint64_t pm_stat:1; -+ uint64_t pm_en:1; -+ uint64_t aux_en:1; -+ } s; -+ struct cvmx_pescx_diag_status_s cn52xx; -+ struct cvmx_pescx_diag_status_s cn52xxp1; -+ struct cvmx_pescx_diag_status_s cn56xx; -+ struct cvmx_pescx_diag_status_s cn56xxp1; -+}; -+ -+union cvmx_pescx_p2n_bar0_start { -+ uint64_t u64; -+ struct cvmx_pescx_p2n_bar0_start_s { -+ uint64_t addr:50; -+ uint64_t reserved_0_13:14; -+ } s; -+ struct cvmx_pescx_p2n_bar0_start_s cn52xx; -+ struct cvmx_pescx_p2n_bar0_start_s cn52xxp1; -+ struct cvmx_pescx_p2n_bar0_start_s cn56xx; -+ struct cvmx_pescx_p2n_bar0_start_s cn56xxp1; -+}; -+ -+union cvmx_pescx_p2n_bar1_start { -+ uint64_t u64; -+ struct cvmx_pescx_p2n_bar1_start_s { -+ uint64_t addr:38; -+ uint64_t reserved_0_25:26; -+ } s; -+ struct cvmx_pescx_p2n_bar1_start_s cn52xx; -+ struct cvmx_pescx_p2n_bar1_start_s cn52xxp1; -+ struct cvmx_pescx_p2n_bar1_start_s cn56xx; -+ struct cvmx_pescx_p2n_bar1_start_s cn56xxp1; -+}; -+ -+union cvmx_pescx_p2n_bar2_start { -+ uint64_t u64; -+ struct cvmx_pescx_p2n_bar2_start_s { -+ uint64_t addr:25; -+ uint64_t reserved_0_38:39; -+ } s; -+ struct cvmx_pescx_p2n_bar2_start_s cn52xx; -+ struct cvmx_pescx_p2n_bar2_start_s cn52xxp1; -+ struct cvmx_pescx_p2n_bar2_start_s cn56xx; -+ struct cvmx_pescx_p2n_bar2_start_s cn56xxp1; -+}; -+ -+union cvmx_pescx_p2p_barx_end { -+ uint64_t u64; -+ struct cvmx_pescx_p2p_barx_end_s { -+ uint64_t addr:52; -+ uint64_t reserved_0_11:12; -+ } s; -+ struct cvmx_pescx_p2p_barx_end_s cn52xx; -+ struct cvmx_pescx_p2p_barx_end_s cn52xxp1; -+ struct cvmx_pescx_p2p_barx_end_s cn56xx; -+ struct cvmx_pescx_p2p_barx_end_s cn56xxp1; -+}; -+ -+union cvmx_pescx_p2p_barx_start { -+ uint64_t u64; -+ struct cvmx_pescx_p2p_barx_start_s { -+ uint64_t addr:52; -+ uint64_t reserved_0_11:12; -+ } s; -+ struct cvmx_pescx_p2p_barx_start_s cn52xx; -+ struct cvmx_pescx_p2p_barx_start_s cn52xxp1; -+ struct cvmx_pescx_p2p_barx_start_s cn56xx; -+ struct cvmx_pescx_p2p_barx_start_s cn56xxp1; -+}; -+ -+union cvmx_pescx_tlp_credits { -+ uint64_t u64; -+ struct cvmx_pescx_tlp_credits_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pescx_tlp_credits_cn52xx { -+ uint64_t reserved_56_63:8; -+ uint64_t peai_ppf:8; -+ uint64_t pesc_cpl:8; -+ uint64_t pesc_np:8; -+ uint64_t pesc_p:8; -+ uint64_t npei_cpl:8; -+ uint64_t npei_np:8; -+ uint64_t npei_p:8; -+ } cn52xx; -+ struct cvmx_pescx_tlp_credits_cn52xxp1 { -+ uint64_t reserved_38_63:26; -+ uint64_t peai_ppf:8; -+ uint64_t pesc_cpl:5; -+ uint64_t pesc_np:5; -+ uint64_t pesc_p:5; -+ uint64_t npei_cpl:5; -+ uint64_t npei_np:5; -+ uint64_t npei_p:5; -+ } cn52xxp1; -+ struct cvmx_pescx_tlp_credits_cn52xx cn56xx; -+ struct cvmx_pescx_tlp_credits_cn52xxp1 cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-pexp-defs.h -@@ -0,0 +1,229 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * cvmx-pexp-defs.h -+ * -+ * Configuration and status register (CSR) definitions for -+ * OCTEON PEXP. -+ * -+ */ -+#ifndef __CVMX_PEXP_DEFS_H__ -+#define __CVMX_PEXP_DEFS_H__ -+ -+#define CVMX_PEXP_NPEI_BAR1_INDEXX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000008000ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_BIST_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011F0000008580ull) -+#define CVMX_PEXP_NPEI_BIST_STATUS2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008680ull) -+#define CVMX_PEXP_NPEI_CTL_PORT0 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008250ull) -+#define CVMX_PEXP_NPEI_CTL_PORT1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008260ull) -+#define CVMX_PEXP_NPEI_CTL_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011F0000008570ull) -+#define CVMX_PEXP_NPEI_CTL_STATUS2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC00ull) -+#define CVMX_PEXP_NPEI_DATA_OUT_CNT \ -+ CVMX_ADD_IO_SEG(0x00011F00000085F0ull) -+#define CVMX_PEXP_NPEI_DBG_DATA \ -+ CVMX_ADD_IO_SEG(0x00011F0000008510ull) -+#define CVMX_PEXP_NPEI_DBG_SELECT \ -+ CVMX_ADD_IO_SEG(0x00011F0000008500ull) -+#define CVMX_PEXP_NPEI_DMA0_INT_LEVEL \ -+ CVMX_ADD_IO_SEG(0x00011F00000085C0ull) -+#define CVMX_PEXP_NPEI_DMA1_INT_LEVEL \ -+ CVMX_ADD_IO_SEG(0x00011F00000085D0ull) -+#define CVMX_PEXP_NPEI_DMAX_COUNTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000008450ull + (((offset) & 7) * 16)) -+#define CVMX_PEXP_NPEI_DMAX_DBELL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F00000083B0ull + (((offset) & 7) * 16)) -+#define CVMX_PEXP_NPEI_DMAX_IBUFF_SADDR(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000008400ull + (((offset) & 7) * 16)) -+#define CVMX_PEXP_NPEI_DMAX_NADDR(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F00000084A0ull + (((offset) & 7) * 16)) -+#define CVMX_PEXP_NPEI_DMA_CNTS \ -+ CVMX_ADD_IO_SEG(0x00011F00000085E0ull) -+#define CVMX_PEXP_NPEI_DMA_CONTROL \ -+ CVMX_ADD_IO_SEG(0x00011F00000083A0ull) -+#define CVMX_PEXP_NPEI_INT_A_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000008560ull) -+#define CVMX_PEXP_NPEI_INT_A_ENB2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BCE0ull) -+#define CVMX_PEXP_NPEI_INT_A_SUM \ -+ CVMX_ADD_IO_SEG(0x00011F0000008550ull) -+#define CVMX_PEXP_NPEI_INT_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000008540ull) -+#define CVMX_PEXP_NPEI_INT_ENB2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BCD0ull) -+#define CVMX_PEXP_NPEI_INT_INFO \ -+ CVMX_ADD_IO_SEG(0x00011F0000008590ull) -+#define CVMX_PEXP_NPEI_INT_SUM \ -+ CVMX_ADD_IO_SEG(0x00011F0000008530ull) -+#define CVMX_PEXP_NPEI_INT_SUM2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BCC0ull) -+#define CVMX_PEXP_NPEI_LAST_WIN_RDATA0 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008600ull) -+#define CVMX_PEXP_NPEI_LAST_WIN_RDATA1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008610ull) -+#define CVMX_PEXP_NPEI_MEM_ACCESS_CTL \ -+ CVMX_ADD_IO_SEG(0x00011F00000084F0ull) -+#define CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000008280ull + (((offset) & 31) * 16) - 16 * 12) -+#define CVMX_PEXP_NPEI_MSI_ENB0 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC50ull) -+#define CVMX_PEXP_NPEI_MSI_ENB1 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC60ull) -+#define CVMX_PEXP_NPEI_MSI_ENB2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC70ull) -+#define CVMX_PEXP_NPEI_MSI_ENB3 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC80ull) -+#define CVMX_PEXP_NPEI_MSI_RCV0 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC10ull) -+#define CVMX_PEXP_NPEI_MSI_RCV1 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC20ull) -+#define CVMX_PEXP_NPEI_MSI_RCV2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC30ull) -+#define CVMX_PEXP_NPEI_MSI_RCV3 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC40ull) -+#define CVMX_PEXP_NPEI_MSI_RD_MAP \ -+ CVMX_ADD_IO_SEG(0x00011F000000BCA0ull) -+#define CVMX_PEXP_NPEI_MSI_W1C_ENB0 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BCF0ull) -+#define CVMX_PEXP_NPEI_MSI_W1C_ENB1 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD00ull) -+#define CVMX_PEXP_NPEI_MSI_W1C_ENB2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD10ull) -+#define CVMX_PEXP_NPEI_MSI_W1C_ENB3 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD20ull) -+#define CVMX_PEXP_NPEI_MSI_W1S_ENB0 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD30ull) -+#define CVMX_PEXP_NPEI_MSI_W1S_ENB1 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD40ull) -+#define CVMX_PEXP_NPEI_MSI_W1S_ENB2 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD50ull) -+#define CVMX_PEXP_NPEI_MSI_W1S_ENB3 \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD60ull) -+#define CVMX_PEXP_NPEI_MSI_WR_MAP \ -+ CVMX_ADD_IO_SEG(0x00011F000000BC90ull) -+#define CVMX_PEXP_NPEI_PCIE_CREDIT_CNT \ -+ CVMX_ADD_IO_SEG(0x00011F000000BD70ull) -+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV \ -+ CVMX_ADD_IO_SEG(0x00011F000000BCB0ull) -+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008650ull) -+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008660ull) -+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B3 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008670ull) -+#define CVMX_PEXP_NPEI_PKTX_CNTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000A400ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_INSTR_BADDR(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000A800ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000AC00ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000B000ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_INSTR_HEADER(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000B400ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_IN_BP(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000B800ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_SLIST_BADDR(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000009400ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000009800ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F0000009C00ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKT_CNT_INT \ -+ CVMX_ADD_IO_SEG(0x00011F0000009110ull) -+#define CVMX_PEXP_NPEI_PKT_CNT_INT_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000009130ull) -+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ES \ -+ CVMX_ADD_IO_SEG(0x00011F00000090B0ull) -+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_NS \ -+ CVMX_ADD_IO_SEG(0x00011F00000090A0ull) -+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ROR \ -+ CVMX_ADD_IO_SEG(0x00011F0000009090ull) -+#define CVMX_PEXP_NPEI_PKT_DPADDR \ -+ CVMX_ADD_IO_SEG(0x00011F0000009080ull) -+#define CVMX_PEXP_NPEI_PKT_INPUT_CONTROL \ -+ CVMX_ADD_IO_SEG(0x00011F0000009150ull) -+#define CVMX_PEXP_NPEI_PKT_INSTR_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000009000ull) -+#define CVMX_PEXP_NPEI_PKT_INSTR_RD_SIZE \ -+ CVMX_ADD_IO_SEG(0x00011F0000009190ull) -+#define CVMX_PEXP_NPEI_PKT_INSTR_SIZE \ -+ CVMX_ADD_IO_SEG(0x00011F0000009020ull) -+#define CVMX_PEXP_NPEI_PKT_INT_LEVELS \ -+ CVMX_ADD_IO_SEG(0x00011F0000009100ull) -+#define CVMX_PEXP_NPEI_PKT_IN_BP \ -+ CVMX_ADD_IO_SEG(0x00011F00000086B0ull) -+#define CVMX_PEXP_NPEI_PKT_IN_DONEX_CNTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011F000000A000ull + (((offset) & 31) * 16)) -+#define CVMX_PEXP_NPEI_PKT_IN_INSTR_COUNTS \ -+ CVMX_ADD_IO_SEG(0x00011F00000086A0ull) -+#define CVMX_PEXP_NPEI_PKT_IN_PCIE_PORT \ -+ CVMX_ADD_IO_SEG(0x00011F00000091A0ull) -+#define CVMX_PEXP_NPEI_PKT_IPTR \ -+ CVMX_ADD_IO_SEG(0x00011F0000009070ull) -+#define CVMX_PEXP_NPEI_PKT_OUTPUT_WMARK \ -+ CVMX_ADD_IO_SEG(0x00011F0000009160ull) -+#define CVMX_PEXP_NPEI_PKT_OUT_BMODE \ -+ CVMX_ADD_IO_SEG(0x00011F00000090D0ull) -+#define CVMX_PEXP_NPEI_PKT_OUT_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000009010ull) -+#define CVMX_PEXP_NPEI_PKT_PCIE_PORT \ -+ CVMX_ADD_IO_SEG(0x00011F00000090E0ull) -+#define CVMX_PEXP_NPEI_PKT_PORT_IN_RST \ -+ CVMX_ADD_IO_SEG(0x00011F0000008690ull) -+#define CVMX_PEXP_NPEI_PKT_SLIST_ES \ -+ CVMX_ADD_IO_SEG(0x00011F0000009050ull) -+#define CVMX_PEXP_NPEI_PKT_SLIST_ID_SIZE \ -+ CVMX_ADD_IO_SEG(0x00011F0000009180ull) -+#define CVMX_PEXP_NPEI_PKT_SLIST_NS \ -+ CVMX_ADD_IO_SEG(0x00011F0000009040ull) -+#define CVMX_PEXP_NPEI_PKT_SLIST_ROR \ -+ CVMX_ADD_IO_SEG(0x00011F0000009030ull) -+#define CVMX_PEXP_NPEI_PKT_TIME_INT \ -+ CVMX_ADD_IO_SEG(0x00011F0000009120ull) -+#define CVMX_PEXP_NPEI_PKT_TIME_INT_ENB \ -+ CVMX_ADD_IO_SEG(0x00011F0000009140ull) -+#define CVMX_PEXP_NPEI_RSL_INT_BLOCKS \ -+ CVMX_ADD_IO_SEG(0x00011F0000008520ull) -+#define CVMX_PEXP_NPEI_SCRATCH_1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008270ull) -+#define CVMX_PEXP_NPEI_STATE1 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008620ull) -+#define CVMX_PEXP_NPEI_STATE2 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008630ull) -+#define CVMX_PEXP_NPEI_STATE3 \ -+ CVMX_ADD_IO_SEG(0x00011F0000008640ull) -+#define CVMX_PEXP_NPEI_WINDOW_CTL \ -+ CVMX_ADD_IO_SEG(0x00011F0000008380ull) -+ -+#endif diff --git a/target/linux/octeon/patches/003_pci_pcie_support.patch b/target/linux/octeon/patches/003_pci_pcie_support.patch deleted file mode 100644 index 32ba634c38..0000000000 --- a/target/linux/octeon/patches/003_pci_pcie_support.patch +++ /dev/null @@ -1,5002 +0,0 @@ -This patch adds support for PCI and PCIe to the base Cavium OCTEON -processor support. - -Signed-off-by: David Daney ---- - arch/mips/Kconfig | 2 + - arch/mips/cavium-octeon/Makefile | 4 + - arch/mips/cavium-octeon/dma-octeon.c | 310 ++++++- - arch/mips/cavium-octeon/executive/Makefile | 2 + - .../cavium-octeon/executive/cvmx-helper-errata.c | 379 +++++++ - .../cavium-octeon/executive/cvmx-helper-util.c | 502 ++++++++++ - arch/mips/cavium-octeon/executive/cvmx-pcie.c | 1053 ++++++++++++++++++++ - arch/mips/cavium-octeon/msi.c | 288 ++++++ - arch/mips/cavium-octeon/octeon-irq.c | 2 + - arch/mips/cavium-octeon/pci-common.c | 137 +++ - arch/mips/cavium-octeon/pci-common.h | 39 + - arch/mips/cavium-octeon/pci.c | 568 +++++++++++ - arch/mips/cavium-octeon/pcie.c | 441 ++++++++ - arch/mips/include/asm/octeon/cvmx-asm.h | 3 +- - arch/mips/include/asm/octeon/cvmx-helper-errata.h | 92 ++ - arch/mips/include/asm/octeon/cvmx-helper-util.h | 266 +++++ - arch/mips/include/asm/octeon/cvmx-packet.h | 16 +- - arch/mips/include/asm/octeon/cvmx-pcie.h | 284 ++++++ - arch/mips/include/asm/octeon/cvmx-wqe.h | 422 ++++++++ - arch/mips/include/asm/octeon/cvmx.h | 12 + - arch/mips/include/asm/octeon/octeon.h | 2 + - 21 files changed, 4816 insertions(+), 8 deletions(-) - create mode 100644 arch/mips/cavium-octeon/executive/cvmx-helper-errata.c - create mode 100644 arch/mips/cavium-octeon/executive/cvmx-helper-util.c - create mode 100644 arch/mips/cavium-octeon/executive/cvmx-pcie.c - create mode 100644 arch/mips/cavium-octeon/msi.c - create mode 100644 arch/mips/cavium-octeon/pci-common.c - create mode 100644 arch/mips/cavium-octeon/pci-common.h - create mode 100644 arch/mips/cavium-octeon/pci.c - create mode 100644 arch/mips/cavium-octeon/pcie.c - create mode 100644 arch/mips/include/asm/octeon/cvmx-helper-errata.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-helper-util.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-pcie.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-wqe.h - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -618,6 +618,8 @@ config CAVIUM_OCTEON_REFERENCE_BOARD - select SYS_HAS_EARLY_PRINTK - select SYS_HAS_CPU_CAVIUM_OCTEON - select SWAP_IO_SPACE -+ select HW_HAS_PCI -+ select ARCH_SUPPORTS_MSI - help - This option supports all of the Octeon reference boards from Cavium - Networks. It builds a kernel that dynamically determines the Octeon ---- a/arch/mips/cavium-octeon/Makefile -+++ b/arch/mips/cavium-octeon/Makefile -@@ -14,5 +14,9 @@ obj-y += dma-octeon.o flash_setup.o - obj-y += octeon-memcpy.o - - obj-$(CONFIG_SMP) += smp.o -+obj-$(CONFIG_PCI) += pci-common.o -+obj-$(CONFIG_PCI) += pci.o -+obj-$(CONFIG_PCI) += pcie.o -+obj-$(CONFIG_PCI_MSI) += msi.o - - EXTRA_CFLAGS += -Werror ---- a/arch/mips/cavium-octeon/dma-octeon.c -+++ b/arch/mips/cavium-octeon/dma-octeon.c -@@ -13,20 +13,326 @@ - */ - #include - #include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include - - #include - -+#ifdef CONFIG_PCI -+#include "pci-common.h" -+#endif -+ -+#define BAR2_PCI_ADDRESS 0x8000000000ul -+ -+struct bar1_index_state { -+ int16_t ref_count; /* Number of PCI mappings using this index */ -+ uint16_t address_bits; /* Upper bits of physical address. This is -+ shifted 22 bits */ -+}; -+ -+#ifdef CONFIG_PCI -+static DEFINE_SPINLOCK(bar1_lock); -+static struct bar1_index_state bar1_state[32]; -+#endif -+ - dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) - { -+#ifndef CONFIG_PCI - /* Without PCI/PCIe this function can be called for Octeon internal - devices such as USB. These devices all support 64bit addressing */ - mb(); - return virt_to_phys(ptr); -+#else -+ unsigned long flags; -+ uint64_t dma_mask; -+ int64_t start_index; -+ dma_addr_t result = -1; -+ uint64_t physical = virt_to_phys(ptr); -+ int64_t index; -+ -+ mb(); -+ /* -+ * Use the DMA masks to determine the allowed memory -+ * region. For us it doesn't limit the actual memory, just the -+ * address visible over PCI. Devices with limits need to use -+ * lower indexed Bar1 entries. -+ */ -+ if (dev) { -+ dma_mask = dev->coherent_dma_mask; -+ if (dev->dma_mask) -+ dma_mask = *dev->dma_mask; -+ } else -+ dma_mask = 0xfffffffful; -+ -+ /* -+ * Platform devices, such as the internal USB, skip all -+ * translation and use Octeon physical addresses directly. -+ */ -+ if (dev->bus == &platform_bus_type) -+ return physical; -+ -+ switch (octeon_dma_bar_type) { -+ case OCTEON_DMA_BAR_TYPE_PCIE: -+ if (unlikely(physical < (16ul << 10))) -+ panic("dma_map_single: Not allowed to map first 16KB." -+ " It interferes with BAR0 special area\n"); -+ else if ((physical + size >= (256ul << 20)) && -+ (physical < (512ul << 20))) -+ panic("dma_map_single: Not allowed to map bootbus\n"); -+ else if ((physical + size >= 0x400000000ull) && -+ physical < 0x410000000ull) -+ panic("dma_map_single: " -+ "Attempt to map illegal memory address 0x%lx\n", -+ physical); -+ else if (physical >= 0x420000000ull) -+ panic("dma_map_single: " -+ "Attempt to map illegal memory address 0x%lx\n", -+ physical); -+ else if ((physical + size >= -+ (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20)) -+ && physical < (4ull<<30)) -+ pr_warning("dma_map_single: Warning: " -+ "Mapping memory address that might " -+ "conflict with devices 0x%lx-0x%lx\n", -+ physical, physical+size-1); -+ /* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */ -+ if ((physical >= 0x410000000ull) && physical < 0x420000000ull) -+ result = physical - 0x400000000ull; -+ else -+ result = physical; -+ if (((result+size-1) & dma_mask) != result+size-1) -+ panic("dma_map_single: Attempt to map address " -+ "0x%lx-0x%lx, which can't be accessed according " -+ "to the dma mask 0x%lx\n", -+ physical, physical+size-1, dma_mask); -+ goto done; -+ -+ case OCTEON_DMA_BAR_TYPE_BIG: -+#ifdef CONFIG_64BIT -+ /* If the device supports 64bit addressing, then use BAR2 */ -+ if (dma_mask > BAR2_PCI_ADDRESS) { -+ result = physical + BAR2_PCI_ADDRESS; -+ goto done; -+ } -+#endif -+ if (unlikely(physical < (4ul << 10))) { -+ panic("dma_map_single: Not allowed to map first 4KB. " -+ "It interferes with BAR0 special area\n"); -+ } else if (physical < (256ul << 20)) { -+ if (unlikely(physical + size > (256ul << 20))) -+ panic("dma_map_single: Requested memory spans " -+ "Bar0 0:256MB and bootbus\n"); -+ result = physical; -+ goto done; -+ } else if (unlikely(physical < (512ul << 20))) { -+ panic("dma_map_single: Not allowed to map bootbus\n"); -+ } else if (physical < (2ul << 30)) { -+ if (unlikely(physical + size > (2ul << 30))) -+ panic("dma_map_single: Requested memory spans " -+ "Bar0 512MB:2GB and BAR1\n"); -+ result = physical; -+ goto done; -+ } else if (physical < (2ul << 30) + (128 << 20)) { -+ /* Fall through */ -+ } else if (physical < -+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) { -+ if (unlikely -+ (physical + size > -+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20))) -+ panic("dma_map_single: Requested memory " -+ "extends past Bar1 (4GB-%luMB)\n", -+ OCTEON_PCI_BAR1_HOLE_SIZE); -+ result = physical; -+ goto done; -+ } else if ((physical >= 0x410000000ull) && -+ (physical < 0x420000000ull)) { -+ if (unlikely(physical + size > 0x420000000ull)) -+ panic("dma_map_single: Requested memory spans " -+ "non existant memory\n"); -+ /* BAR0 fixed mapping 256MB:512MB -> -+ * 16GB+256MB:16GB+512MB */ -+ result = physical - 0x400000000ull; -+ goto done; -+ } else { -+ /* Continued below switch statement */ -+ } -+ break; -+ -+ case OCTEON_DMA_BAR_TYPE_SMALL: -+#ifdef CONFIG_64BIT -+ /* If the device supports 64bit addressing, then use BAR2 */ -+ if (dma_mask > BAR2_PCI_ADDRESS) { -+ result = physical + BAR2_PCI_ADDRESS; -+ goto done; -+ } -+#endif -+ /* Continued below switch statement */ -+ break; -+ -+ default: -+ panic("dma_map_single: Invalid octeon_dma_bar_type\n"); -+ } -+ -+ /* Don't allow mapping to span multiple Bar entries. The hardware guys -+ won't guarantee that DMA across boards work */ -+ if (unlikely((physical >> 22) != ((physical + size - 1) >> 22))) -+ panic("dma_map_single: " -+ "Requested memory spans more than one Bar1 entry\n"); -+ -+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) -+ start_index = 31; -+ else if (unlikely(dma_mask < (1ul << 27))) -+ start_index = (dma_mask >> 22); -+ else -+ start_index = 31; -+ -+ /* Only one processor can access the Bar register at once */ -+ spin_lock_irqsave(&bar1_lock, flags); -+ -+ /* Look through Bar1 for existing mapping that will work */ -+ for (index = start_index; index >= 0; index--) { -+ if ((bar1_state[index].address_bits == physical >> 22) && -+ (bar1_state[index].ref_count)) { -+ /* An existing mapping will work, use it */ -+ bar1_state[index].ref_count++; -+ if (unlikely(bar1_state[index].ref_count < 0)) -+ panic("dma_map_single: " -+ "Bar1[%d] reference count overflowed\n", -+ (int) index); -+ result = (index << 22) | (physical & ((1 << 22) - 1)); -+ /* Large BAR1 is offset at 2GB */ -+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) -+ result += 2ul << 30; -+ goto done_unlock; -+ } -+ } -+ -+ /* No existing mappings, look for a free entry */ -+ for (index = start_index; index >= 0; index--) { -+ if (unlikely(bar1_state[index].ref_count == 0)) { -+ union cvmx_pci_bar1_indexx bar1_index; -+ /* We have a free entry, use it */ -+ bar1_state[index].ref_count = 1; -+ bar1_state[index].address_bits = physical >> 22; -+ bar1_index.u32 = 0; -+ /* Address bits[35:22] sent to L2C */ -+ bar1_index.s.addr_idx = physical >> 22; -+ /* Don't put PCI accesses in L2. */ -+ bar1_index.s.ca = 1; -+ /* Endian Swap Mode */ -+ bar1_index.s.end_swp = 1; -+ /* Set '1' when the selected address range is valid. */ -+ bar1_index.s.addr_v = 1; -+ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), -+ bar1_index.u32); -+ /* An existing mapping will work, use it */ -+ result = (index << 22) | (physical & ((1 << 22) - 1)); -+ /* Large BAR1 is offset at 2GB */ -+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) -+ result += 2ul << 30; -+ goto done_unlock; -+ } -+ } -+ -+ pr_err("dma_map_single: " -+ "Can't find empty BAR1 index for physical mapping 0x%llx\n", -+ (unsigned long long) physical); -+ -+done_unlock: -+ spin_unlock_irqrestore(&bar1_lock, flags); -+done: -+ pr_debug("dma_map_single 0x%lx->0x%lx\n", physical, result); -+ return result; -+#endif - } - - void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr) - { -- /* Without PCI/PCIe this function can be called for Octeon internal -- * devices such as USB. These devices all support 64bit addressing */ -+#ifndef CONFIG_PCI -+ /* -+ * Without PCI/PCIe this function can be called for Octeon internal -+ * devices such as USB. These devices all support 64bit addressing. -+ */ -+ return; -+#else -+ unsigned long flags; -+ uint64_t index; -+ -+ /* -+ * Platform devices, such as the internal USB, skip all -+ * translation and use Octeon physical addresses directly. -+ */ -+ if (dev->bus == &platform_bus_type) -+ return; -+ -+ switch (octeon_dma_bar_type) { -+ case OCTEON_DMA_BAR_TYPE_PCIE: -+ /* Nothing to do, all mappings are static */ -+ goto done; -+ -+ case OCTEON_DMA_BAR_TYPE_BIG: -+#ifdef CONFIG_64BIT -+ /* Nothing to do for addresses using BAR2 */ -+ if (dma_addr >= BAR2_PCI_ADDRESS) -+ goto done; -+#endif -+ if (unlikely(dma_addr < (4ul << 10))) -+ panic("dma_unmap_single: Unexpect DMA address 0x%lx\n", -+ dma_addr); -+ else if (dma_addr < (2ul << 30)) -+ /* Nothing to do for addresses using BAR0 */ -+ goto done; -+ else if (dma_addr < (2ul << 30) + (128ul << 20)) -+ /* Need to unmap, fall through */ -+ index = (dma_addr - (2ul << 30)) >> 22; -+ else if (dma_addr < -+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) -+ goto done; /* Nothing to do for the rest of BAR1 */ -+ else -+ panic("dma_unmap_single: Unexpect DMA address 0x%lx\n", -+ dma_addr); -+ /* Continued below switch statement */ -+ break; -+ -+ case OCTEON_DMA_BAR_TYPE_SMALL: -+#ifdef CONFIG_64BIT -+ /* Nothing to do for addresses using BAR2 */ -+ if (dma_addr >= BAR2_PCI_ADDRESS) -+ goto done; -+#endif -+ index = dma_addr >> 22; -+ /* Continued below switch statement */ -+ break; -+ -+ default: -+ panic("dma_unmap_single: Invalid octeon_dma_bar_type\n"); -+ } -+ -+ if (unlikely(index > 31)) -+ panic("dma_unmap_single: " -+ "Attempt to unmap an invalid address (0x%llx)\n", -+ (unsigned long long) dma_addr); -+ -+ spin_lock_irqsave(&bar1_lock, flags); -+ bar1_state[index].ref_count--; -+ if (bar1_state[index].ref_count == 0) -+ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); -+ else if (unlikely(bar1_state[index].ref_count < 0)) -+ panic("dma_unmap_single: Bar1[%u] reference count < 0\n", -+ (int) index); -+ spin_unlock_irqrestore(&bar1_lock, flags); -+done: -+ pr_debug("dma_unmap_single 0x%lx\n", dma_addr); - return; -+#endif - } ---- a/arch/mips/cavium-octeon/executive/Makefile -+++ b/arch/mips/cavium-octeon/executive/Makefile -@@ -11,3 +11,5 @@ - - obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o - -+obj-$(CONFIG_PCI) += cvmx-pcie.o -+obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-util.o ---- /dev/null -+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c -@@ -0,0 +1,379 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Fixes and workaround for Octeon chip errata. This file -+ * contains functions called by cvmx-helper to workaround known -+ * chip errata. For the most part, code doesn't need to call -+ * these functions directly. -+ * -+ */ -+#include -+ -+#include -+ -+#ifdef CVMX_ENABLE_PKO_FUNCTIONS -+ -+/** -+ * @INTERNAL -+ * Function to adjust internal IPD pointer alignments -+ * -+ * Returns 0 on success -+ * !0 on failure -+ */ -+int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) -+{ -+#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \ -+ (CVMX_FPA_PACKET_POOL_SIZE - 8 - CVMX_HELPER_FIRST_MBUFF_SKIP) -+#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \ -+ (CVMX_FPA_PACKET_POOL_SIZE - 8 - CVMX_HELPER_NOT_FIRST_MBUFF_SKIP) -+#define FIX_IPD_OUTPORT 0 -+ /* Ports 0-15 are interface 0, 16-31 are interface 1 */ -+#define INTERFACE(port) (port >> 4) -+#define INDEX(port) (port & 0xf) -+ uint64_t *p64; -+ cvmx_pko_command_word0_t pko_command; -+ cvmx_buf_ptr_t g_buffer, pkt_buffer; -+ cvmx_wqe_t *work; -+ int size, num_segs = 0, wqe_pcnt, pkt_pcnt; -+ cvmx_gmxx_prtx_cfg_t gmx_cfg; -+ int retry_cnt; -+ int retry_loop_cnt; -+ int mtu; -+ int i; -+ cvmx_helper_link_info_t link_info; -+ -+ /* Save values for restore at end */ -+ uint64_t prtx_cfg = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t tx_ptr_en = -+ cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t rx_ptr_en = -+ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t rxx_jabber = -+ cvmx_read_csr(CVMX_GMXX_RXX_JABBER(INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t frame_max = -+ cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX(INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ -+ /* Configure port to gig FDX as required for loopback mode */ -+ cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT); -+ -+ /* -+ * Disable reception on all ports so if traffic is present it -+ * will not interfere. -+ */ -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0); -+ -+ cvmx_wait(100000000ull); -+ -+ for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) { -+ retry_cnt = 100000; -+ wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT); -+ pkt_pcnt = (wqe_pcnt >> 7) & 0x7f; -+ wqe_pcnt &= 0x7f; -+ -+ num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3; -+ -+ if (num_segs == 0) -+ goto fix_ipd_exit; -+ -+ num_segs += 1; -+ -+ size = -+ FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES + -+ ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) - -+ (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2); -+ -+ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), -+ 1 << INDEX(FIX_IPD_OUTPORT)); -+ CVMX_SYNC; -+ -+ g_buffer.u64 = 0; -+ g_buffer.s.addr = -+ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL)); -+ if (g_buffer.s.addr == 0) { -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT buffer " -+ "allocation failure.\n"); -+ goto fix_ipd_exit; -+ } -+ -+ g_buffer.s.pool = CVMX_FPA_WQE_POOL; -+ g_buffer.s.size = num_segs; -+ -+ pkt_buffer.u64 = 0; -+ pkt_buffer.s.addr = -+ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL)); -+ if (pkt_buffer.s.addr == 0) { -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT buffer " -+ "allocation failure.\n"); -+ goto fix_ipd_exit; -+ } -+ pkt_buffer.s.i = 1; -+ pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL; -+ pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES; -+ -+ p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr); -+ p64[0] = 0xffffffffffff0000ull; -+ p64[1] = 0x08004510ull; -+ p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull; -+ p64[3] = 0x3a5fc0a81073c0a8ull; -+ -+ for (i = 0; i < num_segs; i++) { -+ if (i > 0) -+ pkt_buffer.s.size = -+ FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES; -+ -+ if (i == (num_segs - 1)) -+ pkt_buffer.s.i = 0; -+ -+ *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr + -+ 8 * i) = pkt_buffer.u64; -+ } -+ -+ /* Build the PKO command */ -+ pko_command.u64 = 0; -+ pko_command.s.segs = num_segs; -+ pko_command.s.total_bytes = size; -+ pko_command.s.dontfree = 0; -+ pko_command.s.gather = 1; -+ -+ gmx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ 1 << INDEX(FIX_IPD_OUTPORT)); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ 1 << INDEX(FIX_IPD_OUTPORT)); -+ -+ mtu = -+ cvmx_read_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); -+ -+#if CVMX_PKO_USE_FAU_FOR_OUTPUT_QUEUES -+ cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, -+ cvmx_pko_get_base_queue -+ (FIX_IPD_OUTPORT), -+ CVMX_PKO_LOCK_NONE); -+ cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, -+ cvmx_pko_get_base_queue -+ (FIX_IPD_OUTPORT), pko_command, -+ g_buffer, CVMX_PKO_LOCK_NONE); -+#else -+ cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, -+ cvmx_pko_get_base_queue -+ (FIX_IPD_OUTPORT), -+ CVMX_PKO_LOCK_CMD_QUEUE); -+ cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, -+ cvmx_pko_get_base_queue -+ (FIX_IPD_OUTPORT), pko_command, -+ g_buffer, CVMX_PKO_LOCK_CMD_QUEUE); -+#endif -+ CVMX_SYNC; -+ -+ do { -+ work = cvmx_pow_work_request_sync(CVMX_POW_WAIT); -+ retry_cnt--; -+ } while ((work == NULL) && (retry_cnt > 0)); -+ -+ if (!retry_cnt) -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " -+ "get_work() timeout occured.\n"); -+ -+ /* Free packet */ -+ if (work) -+ cvmx_helper_free_packet_data(work); -+ } -+ -+fix_ipd_exit: -+ -+ /* Return CSR configs to saved values */ -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), -+ prtx_cfg); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ tx_ptr_en); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ rx_ptr_en); -+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), -+ rxx_jabber); -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), -+ frame_max); -+ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0); -+ /* Set link to down so autonegotiation will set it up again */ -+ link_info.u64 = 0; -+ cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info); -+ -+ /* -+ * Bring the link back up as autonegotiation is not done in -+ * user applications. -+ */ -+ cvmx_helper_link_autoconf(FIX_IPD_OUTPORT); -+ -+ CVMX_SYNC; -+ if (num_segs) -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n"); -+ -+ return !!num_segs; -+ -+} -+ -+/** -+ * @INTERNAL -+ * Workaround ASX setup errata with CN38XX pass1 -+ * -+ * @interface: Interface to setup -+ * @port: Port to setup (0..3) -+ * @cpu_clock_hz: -+ * Chip frequency in Hertz -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_errata_asx_pass1(int interface, int port, int cpu_clock_hz) -+{ -+ /* Set hi water mark as per errata GMX-4 */ -+ if (cpu_clock_hz >= 325000000 && cpu_clock_hz < 375000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 12); -+ else if (cpu_clock_hz >= 375000000 && cpu_clock_hz < 437000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 11); -+ else if (cpu_clock_hz >= 437000000 && cpu_clock_hz < 550000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 10); -+ else if (cpu_clock_hz >= 550000000 && cpu_clock_hz < 687000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 9); -+ else -+ cvmx_dprintf("Illegal clock frequency (%d). " -+ "CVMX_ASXX_TX_HI_WATERX not set\n", -+ cpu_clock_hz); -+ return 0; -+} -+ -+/** -+ * This function needs to be called on all Octeon chips with -+ * errata PKI-100. -+ * -+ * The Size field is 8 too large in WQE and next pointers -+ * -+ * The Size field generated by IPD is 8 larger than it should -+ * be. The Size field is <55:40> of both: -+ * - WORD3 in the work queue entry, and -+ * - the next buffer pointer (which precedes the packet data -+ * in each buffer). -+ * -+ * @work: Work queue entry to fix -+ * Returns Zero on success. Negative on failure -+ */ -+int cvmx_helper_fix_ipd_packet_chain(cvmx_wqe_t *work) -+{ -+ uint64_t number_buffers = work->word2.s.bufs; -+ -+ /* We only need to do this if the work has buffers */ -+ if (number_buffers) { -+ cvmx_buf_ptr_t buffer_ptr = work->packet_ptr; -+ /* Check for errata PKI-100 */ -+ if ((buffer_ptr.s.pool == 0) && -+ (((uint64_t) buffer_ptr.s.size + -+ ((uint64_t) buffer_ptr.s.back << 7) + -+ ((uint64_t) buffer_ptr.s.addr & 0x7F)) != -+ (CVMX_FPA_PACKET_POOL_SIZE + 8))) { -+ /* fix is not needed */ -+ return 0; -+ } -+ /* Decrement the work packet pointer */ -+ buffer_ptr.s.size -= 8; -+ work->packet_ptr = buffer_ptr; -+ -+ /* -+ * Now loop through decrementing the size for each -+ * additional buffer. -+ */ -+ while (--number_buffers) { -+ /* Chain pointers are 8 bytes before the data */ -+ cvmx_buf_ptr_t *ptr = -+ (cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); -+ buffer_ptr = *ptr; -+ buffer_ptr.s.size -= 8; -+ *ptr = buffer_ptr; -+ } -+ } -+ /* -+ * Make sure that these write go out before other operations -+ * such as FPA frees. -+ */ -+ CVMX_SYNCWS; -+ return 0; -+} -+ -+#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ -+ -+/** -+ * Due to errata G-720, the 2nd order CDR circuit on CN52XX pass -+ * 1 doesn't work properly. The following code disables 2nd order -+ * CDR for the specified QLM. -+ * -+ * @qlm: QLM to disable 2nd order CDR for. -+ */ -+void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm) -+{ -+ int lane; -+ cvmx_helper_qlm_jtag_init(); -+ /* We need to load all four lanes of the QLM, a total of 1072 bits */ -+ for (lane = 0; lane < 4; lane++) { -+ /* -+ * Each lane has 268 bits. We need to set -+ * cfg_cdr_incx<67:64> = 3 and cfg_cdr_secord<77> = -+ * 1. All other bits are zero. Bits go in LSB first, -+ * so start off with the zeros for bits <63:0>. -+ */ -+ cvmx_helper_qlm_jtag_shift_zeros(qlm, 63 - 0 + 1); -+ /* cfg_cdr_incx<67:64>=3 */ -+ cvmx_helper_qlm_jtag_shift(qlm, 67 - 64 + 1, 3); -+ /* Zeros for bits <76:68> */ -+ cvmx_helper_qlm_jtag_shift_zeros(qlm, 76 - 68 + 1); -+ /* cfg_cdr_secord<77>=1 */ -+ cvmx_helper_qlm_jtag_shift(qlm, 77 - 77 + 1, 1); -+ /* Zeros for bits <267:78> */ -+ cvmx_helper_qlm_jtag_shift_zeros(qlm, 267 - 78 + 1); -+ } -+ cvmx_helper_qlm_jtag_update(qlm); -+} ---- /dev/null -+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c -@@ -0,0 +1,502 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Small helper utilities. -+ * -+ */ -+ -+#include -+ -+#include -+ -+#ifdef CVMX_ENABLE_HELPER_FUNCTIONS -+ -+/** -+ * Get the version of the CVMX libraries. -+ * -+ * Returns Version string. Note this buffer is allocated statically -+ * and will be shared by all callers. -+ */ -+const char *cvmx_helper_get_version(void) -+{ -+ return OCTEON_SDK_VERSION_STRING; -+} -+ -+/** -+ * Convert a interface mode into a human readable string -+ * -+ * @mode: Mode to convert -+ * -+ * Returns String -+ */ -+const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t -+ mode) -+{ -+ switch (mode) { -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ return "DISABLED"; -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ return "RGMII"; -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ return "GMII"; -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ return "SPI"; -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ return "PCIE"; -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ return "XAUI"; -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ return "SGMII"; -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ return "PICMG"; -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ return "NPI"; -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ return "LOOP"; -+ } -+ return "UNKNOWN"; -+} -+ -+/** -+ * Debug routine to dump the packet structure to the console -+ * -+ * @work: Work queue entry containing the packet to dump -+ */ -+int cvmx_helper_dump_packet(cvmx_wqe_t *work) -+{ -+ uint64_t count; -+ uint64_t remaining_bytes; -+ cvmx_buf_ptr_t buffer_ptr; -+ uint64_t start_of_buffer; -+ uint8_t *data_address; -+ uint8_t *end_of_data; -+ -+ cvmx_dprintf("Packet Length: %u\n", work->len); -+ cvmx_dprintf(" Input Port: %u\n", work->ipprt); -+ cvmx_dprintf(" QoS: %u\n", work->qos); -+ cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs); -+ -+ if (work->word2.s.bufs == 0) { -+ cvmx_ipd_wqe_fpa_queue_t wqe_pool; -+ wqe_pool.u64 = cvmx_read_csr(CVMX_IPD_WQE_FPA_QUEUE); -+ buffer_ptr.u64 = 0; -+ buffer_ptr.s.pool = wqe_pool.s.wqe_pool; -+ buffer_ptr.s.size = 128; -+ buffer_ptr.s.addr = cvmx_ptr_to_phys(work->packet_data); -+ if (cvmx_likely(!work->word2.s.not_IP)) { -+ if (work->word2.s.is_v6) -+ buffer_ptr.s.addr += 2; -+ else -+ buffer_ptr.s.addr += 6; -+ } -+ } else -+ buffer_ptr = work->packet_ptr; -+ remaining_bytes = work->len; -+ -+ while (remaining_bytes) { -+ start_of_buffer = -+ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; -+ cvmx_dprintf(" Buffer Start:%llx\n", -+ (unsigned long long)start_of_buffer); -+ cvmx_dprintf(" Buffer I : %u\n", buffer_ptr.s.i); -+ cvmx_dprintf(" Buffer Back: %u\n", buffer_ptr.s.back); -+ cvmx_dprintf(" Buffer Pool: %u\n", buffer_ptr.s.pool); -+ cvmx_dprintf(" Buffer Data: %llx\n", -+ (unsigned long long)buffer_ptr.s.addr); -+ cvmx_dprintf(" Buffer Size: %u\n", buffer_ptr.s.size); -+ -+ cvmx_dprintf("\t\t"); -+ data_address = (uint8_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr); -+ end_of_data = data_address + buffer_ptr.s.size; -+ count = 0; -+ while (data_address < end_of_data) { -+ if (remaining_bytes == 0) -+ break; -+ else -+ remaining_bytes--; -+ cvmx_dprintf("%02x", (unsigned int)*data_address); -+ data_address++; -+ if (remaining_bytes && (count == 7)) { -+ cvmx_dprintf("\n\t\t"); -+ count = 0; -+ } else -+ count++; -+ } -+ cvmx_dprintf("\n"); -+ -+ if (remaining_bytes) -+ buffer_ptr = -+ *(cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s. -+ addr - 8); -+ } -+ return 0; -+} -+ -+/** -+ * Setup Random Early Drop on a specific input queue -+ * -+ * @queue: Input queue to setup RED on (0-7) -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh) -+{ -+ cvmx_ipd_qos_red_marks_t red_marks; -+ cvmx_ipd_red_quex_param_t red_param; -+ -+ /* -+ * Set RED to begin dropping packets when there are -+ * pass_thresh buffers left. It will linearly drop more -+ * packets until reaching drop_thresh buffers. -+ */ -+ red_marks.u64 = 0; -+ red_marks.s.drop = drop_thresh; -+ red_marks.s.pass = pass_thresh; -+ cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64); -+ -+ /* Use the actual queue 0 counter, not the average */ -+ red_param.u64 = 0; -+ red_param.s.prb_con = -+ (255ul << 24) / (red_marks.s.pass - red_marks.s.drop); -+ red_param.s.avg_con = 1; -+ red_param.s.new_con = 255; -+ red_param.s.use_pcnt = 1; -+ cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64); -+ return 0; -+} -+ -+/** -+ * Setup Random Early Drop to automatically begin dropping packets. -+ * -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) -+{ -+ cvmx_ipd_portx_bp_page_cnt_t page_cnt; -+ cvmx_ipd_bp_prt_red_end_t ipd_bp_prt_red_end; -+ cvmx_ipd_red_port_enable_t red_port_enable; -+ int queue; -+ int interface; -+ int port; -+ -+ /* Disable backpressure based on queued buffers. It needs SW support */ -+ page_cnt.u64 = 0; -+ page_cnt.s.bp_enb = 0; -+ page_cnt.s.page_cnt = 100; -+ for (interface = 0; interface < 2; interface++) { -+ for (port = cvmx_helper_get_first_ipd_port(interface); -+ port < cvmx_helper_get_last_ipd_port(interface); port++) -+ cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), -+ page_cnt.u64); -+ } -+ -+ for (queue = 0; queue < 8; queue++) -+ cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh); -+ -+ /* Shutoff the dropping based on the per port page count. SW isn't -+ decrementing it right now */ -+ ipd_bp_prt_red_end.u64 = 0; -+ ipd_bp_prt_red_end.s.prt_enb = 0; -+ cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64); -+ -+ red_port_enable.u64 = 0; -+ red_port_enable.s.prt_enb = 0xfffffffffull; -+ red_port_enable.s.avg_dly = 10000; -+ red_port_enable.s.prb_dly = 10000; -+ cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64); -+ -+ return 0; -+} -+ -+/** -+ * Setup the common GMX settings that determine the number of -+ * ports. These setting apply to almost all configurations of all -+ * chips. -+ * -+ * @interface: Interface to configure -+ * @num_ports: Number of ports on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_setup_gmx(int interface, int num_ports) -+{ -+ cvmx_gmxx_tx_prts_t gmx_tx_prts; -+ cvmx_gmxx_rx_prts_t gmx_rx_prts; -+ cvmx_pko_reg_gmx_port_mode_t pko_mode; -+ -+ /* Tell GMX the number of TX ports on this interface */ -+ gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface)); -+ gmx_tx_prts.s.prts = num_ports; -+ cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64); -+ -+ /* -+ * Tell GMX the number of RX ports on this interface. This only -+ * applies to *GMII and XAUI ports. -+ */ -+ if (cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_RGMII -+ || cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_SGMII -+ || cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_GMII -+ || cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_XAUI) { -+ if (num_ports > 4) { -+ cvmx_dprintf("__cvmx_helper_setup_gmx: " -+ "Illegal num_ports\n"); -+ return -1; -+ } -+ -+ gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface)); -+ gmx_rx_prts.s.prts = num_ports; -+ cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64); -+ } -+ -+ /* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX and 31XX */ -+ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)) -+ return 0; -+ -+ /* Tell PKO the number of ports on this interface */ -+ pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE); -+ if (interface == 0) { -+ if (num_ports == 1) -+ pko_mode.s.mode0 = 4; -+ else if (num_ports == 2) -+ pko_mode.s.mode0 = 3; -+ else if (num_ports <= 4) -+ pko_mode.s.mode0 = 2; -+ else if (num_ports <= 8) -+ pko_mode.s.mode0 = 1; -+ else -+ pko_mode.s.mode0 = 0; -+ } else { -+ if (num_ports == 1) -+ pko_mode.s.mode1 = 4; -+ else if (num_ports == 2) -+ pko_mode.s.mode1 = 3; -+ else if (num_ports <= 4) -+ pko_mode.s.mode1 = 2; -+ else if (num_ports <= 8) -+ pko_mode.s.mode1 = 1; -+ else -+ pko_mode.s.mode1 = 0; -+ } -+ cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64); -+ return 0; -+} -+ -+/** -+ * Returns the IPD/PKO port number for a port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * @port: Port on the interface -+ * -+ * Returns IPD/PKO port number -+ */ -+int cvmx_helper_get_ipd_port(int interface, int port) -+{ -+ switch (interface) { -+ case 0: -+ return port; -+ case 1: -+ return port + 16; -+ case 2: -+ return port + 32; -+ case 3: -+ return port + 36; -+ } -+ return -1; -+} -+ -+#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ -+ -+/** -+ * Returns the interface number for an IPD/PKO port number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface number -+ */ -+int cvmx_helper_get_interface_num(int ipd_port) -+{ -+ if (ipd_port < 16) -+ return 0; -+ else if (ipd_port < 32) -+ return 1; -+ else if (ipd_port < 36) -+ return 2; -+ else if (ipd_port < 40) -+ return 3; -+ else -+ cvmx_dprintf("cvmx_helper_get_interface_num: " -+ "Illegal IPD port number\n"); -+ -+ return -1; -+} -+ -+/** -+ * Returns the interface index number for an IPD/PKO port -+ * number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface index number -+ */ -+int cvmx_helper_get_interface_index_num(int ipd_port) -+{ -+ if (ipd_port < 32) -+ return ipd_port & 15; -+ else if (ipd_port < 36) -+ return ipd_port & 3; -+ else if (ipd_port < 40) -+ return ipd_port & 3; -+ else -+ cvmx_dprintf("cvmx_helper_get_interface_index_num: " -+ "Illegal IPD port number\n"); -+ -+ return -1; -+} -+ -+/** -+ * Initialize the internal QLM JTAG logic to allow programming -+ * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions. -+ * These functions should only be used at the direction of Cavium -+ * Networks. Programming incorrect values into the JTAG chain -+ * can cause chip damage. -+ */ -+void cvmx_helper_qlm_jtag_init(void) -+{ -+ union cvmx_ciu_qlm_jtgc jtgc; -+ int clock_div = 0; -+ int divisor = cvmx_sysinfo_get()->cpu_clock_hz / (25 * 1000000); -+ divisor = (divisor - 1) >> 2; -+ /* Convert the divisor into a power of 2 shift */ -+ CVMX_CLZ(clock_div, divisor); -+ clock_div = 32 - clock_div; -+ -+ /* -+ * Clock divider for QLM JTAG operations. eclk is divided by -+ * 2^(CLK_DIV + 2). -+ */ -+ jtgc.u64 = 0; -+ jtgc.s.clk_div = clock_div; -+ jtgc.s.mux_sel = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ jtgc.s.bypass = 0x3; -+ else -+ jtgc.s.bypass = 0xf; -+ cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); -+ cvmx_read_csr(CVMX_CIU_QLM_JTGC); -+} -+ -+/** -+ * Write up to 32bits into the QLM jtag chain. Bits are shifted -+ * into the MSB and out the LSB, so you should shift in the low -+ * order bits followed by the high order bits. The JTAG chain is -+ * 4 * 268 bits long, or 1072. -+ * -+ * @qlm: QLM to shift value into -+ * @bits: Number of bits to shift in (1-32). -+ * @data: Data to shift in. Bit 0 enters the chain first, followed by -+ * bit 1, etc. -+ * -+ * Returns The low order bits of the JTAG chain that shifted out of the -+ * circle. -+ */ -+uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data) -+{ -+ union cvmx_ciu_qlm_jtgd jtgd; -+ jtgd.u64 = 0; -+ jtgd.s.shift = 1; -+ jtgd.s.shft_cnt = bits - 1; -+ jtgd.s.shft_reg = data; -+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) -+ jtgd.s.select = 1 << qlm; -+ cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); -+ do { -+ jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); -+ } while (jtgd.s.shift); -+ return jtgd.s.shft_reg >> (32 - bits); -+} -+ -+/** -+ * Shift long sequences of zeros into the QLM JTAG chain. It is -+ * common to need to shift more than 32 bits of zeros into the -+ * chain. This function is a convience wrapper around -+ * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of -+ * zeros at a time. -+ * -+ * @qlm: QLM to shift zeros into -+ * @bits: -+ */ -+void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits) -+{ -+ while (bits > 0) { -+ int n = bits; -+ if (n > 32) -+ n = 32; -+ cvmx_helper_qlm_jtag_shift(qlm, n, 0); -+ bits -= n; -+ } -+} -+ -+/** -+ * Program the QLM JTAG chain into all lanes of the QLM. You must -+ * have already shifted in 268*4, or 1072 bits into the JTAG -+ * chain. Updating invalid values can possibly cause chip damage. -+ * -+ * @qlm: QLM to program -+ */ -+void cvmx_helper_qlm_jtag_update(int qlm) -+{ -+ union cvmx_ciu_qlm_jtgd jtgd; -+ -+ /* Update the new data */ -+ jtgd.u64 = 0; -+ jtgd.s.update = 1; -+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) -+ jtgd.s.select = 1 << qlm; -+ cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); -+ do { -+ jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); -+ } while (jtgd.s.update); -+} ---- /dev/null -+++ b/arch/mips/cavium-octeon/executive/cvmx-pcie.c -@@ -0,0 +1,1053 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Interface to PCIe as a host(RC) or target(EP) -+ * -+ */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * Return the Core virtual base address for PCIe IO access. IOs are -+ * read/written as an offset from this address. -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns 64bit Octeon IO base address for read/write -+ */ -+uint64_t cvmx_pcie_get_io_base_address(int pcie_port) -+{ -+ union cvmx_pcie_address pcie_addr; -+ pcie_addr.u64 = 0; -+ pcie_addr.io.upper = 0; -+ pcie_addr.io.io = 1; -+ pcie_addr.io.did = 3; -+ pcie_addr.io.subdid = 2; -+ pcie_addr.io.es = 1; -+ pcie_addr.io.port = pcie_port; -+ return pcie_addr.u64; -+} -+ -+/** -+ * Size of the IO address region returned at address -+ * cvmx_pcie_get_io_base_address() -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns Size of the IO window -+ */ -+uint64_t cvmx_pcie_get_io_size(int pcie_port) -+{ -+ return 1ull << 32; -+} -+ -+/** -+ * Return the Core virtual base address for PCIe MEM access. Memory is -+ * read/written as an offset from this address. -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns 64bit Octeon IO base address for read/write -+ */ -+uint64_t cvmx_pcie_get_mem_base_address(int pcie_port) -+{ -+ union cvmx_pcie_address pcie_addr; -+ pcie_addr.u64 = 0; -+ pcie_addr.mem.upper = 0; -+ pcie_addr.mem.io = 1; -+ pcie_addr.mem.did = 3; -+ pcie_addr.mem.subdid = 3 + pcie_port; -+ return pcie_addr.u64; -+} -+ -+/** -+ * Size of the Mem address region returned at address -+ * cvmx_pcie_get_mem_base_address() -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns Size of the Mem window -+ */ -+uint64_t cvmx_pcie_get_mem_size(int pcie_port) -+{ -+ return 1ull << 36; -+} -+ -+/** -+ * Initialize the RC config space CSRs -+ * -+ * @pcie_port: PCIe port to initialize -+ */ -+static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) -+{ -+ union cvmx_pciercx_cfg030 pciercx_cfg030; -+ union cvmx_npei_ctl_status2 npei_ctl_status2; -+ union cvmx_pciercx_cfg070 pciercx_cfg070; -+ union cvmx_pciercx_cfg001 pciercx_cfg001; -+ union cvmx_pciercx_cfg032 pciercx_cfg032; -+ union cvmx_pciercx_cfg006 pciercx_cfg006; -+ union cvmx_pciercx_cfg008 pciercx_cfg008; -+ union cvmx_pciercx_cfg009 pciercx_cfg009; -+ union cvmx_pciercx_cfg010 pciercx_cfg010; -+ union cvmx_pciercx_cfg011 pciercx_cfg011; -+ union cvmx_pciercx_cfg035 pciercx_cfg035; -+ union cvmx_pciercx_cfg075 pciercx_cfg075; -+ union cvmx_pciercx_cfg034 pciercx_cfg034; -+ -+ /* Max Payload Size (PCIE*_CFG030[MPS]) */ -+ /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ -+ /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ -+ /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ -+ pciercx_cfg030.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); -+ /* -+ * Max payload size = 128 bytes for best Octeon DMA -+ * performance. -+ */ -+ pciercx_cfg030.s.mps = 0; -+ /* -+ * Max read request size = 128 bytes for best Octeon DMA -+ * performance. -+ */ -+ pciercx_cfg030.s.mrrs = 0; -+ /* Enable relaxed ordering. */ -+ pciercx_cfg030.s.ro_en = 1; -+ /* Enable no snoop. */ -+ pciercx_cfg030.s.ns_en = 1; -+ /* Correctable error reporting enable. */ -+ pciercx_cfg030.s.ce_en = 1; -+ /* Non-fatal error reporting enable. */ -+ pciercx_cfg030.s.nfe_en = 1; -+ /* Fatal error reporting enable. */ -+ pciercx_cfg030.s.fe_en = 1; -+ /* Unsupported request reporting enable. */ -+ pciercx_cfg030.s.ur_en = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), -+ pciercx_cfg030.u32); -+ -+ /* -+ * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match -+ * PCIE*_CFG030[MPS] -+ * -+ * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not -+ * exceed PCIE*_CFG030[MRRS]. -+ */ -+ npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); -+ /* Max payload size = 128 bytes for best Octeon DMA performance */ -+ npei_ctl_status2.s.mps = 0; -+ /* Max read request size = 128 bytes for best Octeon DMA performance */ -+ npei_ctl_status2.s.mrrs = 0; -+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); -+ -+ /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ -+ pciercx_cfg070.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); -+ pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ -+ pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), -+ pciercx_cfg070.u32); -+ -+ /* -+ * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should -+ * always be set. -+ * -+ * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error -+ * Message Enable (PCIE*_CFG001[SEE]) -+ */ -+ pciercx_cfg001.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); -+ pciercx_cfg001.s.msae = 1; /* Memory space enable. */ -+ pciercx_cfg001.s.me = 1; /* Bus master enable. */ -+ pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ -+ pciercx_cfg001.s.see = 1; /* SERR# enable */ -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), -+ pciercx_cfg001.u32); -+ -+ /* Advanced Error Recovery Message Enables */ -+ /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0); -+ /* Use CVMX_PCIERCX_CFG067 hardware default */ -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); -+ -+ /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ -+ pciercx_cfg032.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); -+ pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), -+ pciercx_cfg032.u32); -+ -+ /* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */ -+ -+ /* -+ * Link Width Mode (PCIERCn_CFG452[LME]) - Set during -+ * cvmx_pcie_rc_initialize_link() -+ * -+ * Primary Bus Number (PCIERCn_CFG006[PBNUM]) -+ * -+ * We set the primary bus number to 1 so IDT bridges are -+ * happy. They don't like zero. -+ */ -+ pciercx_cfg006.u32 = 0; -+ pciercx_cfg006.s.pbnum = 1; -+ pciercx_cfg006.s.sbnum = 1; -+ pciercx_cfg006.s.subbnum = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), -+ pciercx_cfg006.u32); -+ -+ /* -+ * Memory-mapped I/O BAR (PCIERCn_CFG008) -+ * Most applications should disable the memory-mapped I/O BAR by -+ * setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR] -+ */ -+ pciercx_cfg008.u32 = 0; -+ pciercx_cfg008.s.mb_addr = 0x100; -+ pciercx_cfg008.s.ml_addr = 0; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), -+ pciercx_cfg008.u32); -+ -+ /* -+ * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) -+ * Most applications should disable the prefetchable BAR by setting -+ * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < -+ * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] -+ */ -+ pciercx_cfg009.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); -+ pciercx_cfg010.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); -+ pciercx_cfg011.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); -+ pciercx_cfg009.s.lmem_base = 0x100; -+ pciercx_cfg009.s.lmem_limit = 0; -+ pciercx_cfg010.s.umem_base = 0x100; -+ pciercx_cfg011.s.umem_limit = 0; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), -+ pciercx_cfg009.u32); -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), -+ pciercx_cfg010.u32); -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), -+ pciercx_cfg011.u32); -+ -+ /* -+ * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) -+ * PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) -+ */ -+ pciercx_cfg035.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); -+ /* System error on correctable error enable. */ -+ pciercx_cfg035.s.secee = 1; -+ /* System error on fatal error enable. */ -+ pciercx_cfg035.s.sefee = 1; -+ /* System error on non-fatal error enable. */ -+ pciercx_cfg035.s.senfee = 1; -+ /* PME interrupt enable. */ -+ pciercx_cfg035.s.pmeie = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), -+ pciercx_cfg035.u32); -+ -+ /* -+ * Advanced Error Recovery Interrupt Enables -+ * (PCIERCn_CFG075[CERE,NFERE,FERE]) -+ */ -+ pciercx_cfg075.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); -+ /* Correctable error reporting enable. */ -+ pciercx_cfg075.s.cere = 1; -+ /* Non-fatal error reporting enable. */ -+ pciercx_cfg075.s.nfere = 1; -+ /* Fatal error reporting enable. */ -+ pciercx_cfg075.s.fere = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), -+ pciercx_cfg075.u32); -+ -+ /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], -+ * PCIERCn_CFG034[DLLS_EN,CCINT_EN]) -+ */ -+ pciercx_cfg034.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); -+ /* Hot-plug interrupt enable. */ -+ pciercx_cfg034.s.hpint_en = 1; -+ /* Data Link Layer state changed enable */ -+ pciercx_cfg034.s.dlls_en = 1; -+ /* Command completed interrupt enable. */ -+ pciercx_cfg034.s.ccint_en = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), -+ pciercx_cfg034.u32); -+} -+ -+/** -+ * Initialize a host mode PCIe link. This function takes a PCIe -+ * port from reset to a link up state. Software can then begin -+ * configuring the rest of the link. -+ * -+ * @pcie_port: PCIe port to initialize -+ * -+ * Returns Zero on success -+ */ -+static int __cvmx_pcie_rc_initialize_link(int pcie_port) -+{ -+ uint64_t start_cycle; -+ union cvmx_pescx_ctl_status pescx_ctl_status; -+ union cvmx_pciercx_cfg452 pciercx_cfg452; -+ union cvmx_pciercx_cfg032 pciercx_cfg032; -+ union cvmx_pciercx_cfg448 pciercx_cfg448; -+ -+ /* Set the lane width */ -+ pciercx_cfg452.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); -+ pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); -+ if (pescx_ctl_status.s.qlm_cfg == 0) { -+ /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ -+ pciercx_cfg452.s.lme = 0xf; -+ } else { -+ /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ -+ pciercx_cfg452.s.lme = 0x7; -+ } -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), -+ pciercx_cfg452.u32); -+ -+ /* -+ * CN52XX pass 1.x has an errata where length mismatches on UR -+ * responses can cause bus errors on 64bit memory -+ * reads. Turning off length error checking fixes this. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { -+ union cvmx_pciercx_cfg455 pciercx_cfg455; -+ pciercx_cfg455.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, -+ CVMX_PCIERCX_CFG455(pcie_port)); -+ pciercx_cfg455.s.m_cpl_len_err = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), -+ pciercx_cfg455.u32); -+ } -+ -+ /* Lane swap needs to be manually enabled for CN52XX */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) { -+ pescx_ctl_status.s.lane_swp = 1; -+ cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), -+ pescx_ctl_status.u64); -+ } -+ -+ /* Bring up the link */ -+ pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); -+ pescx_ctl_status.s.lnk_enb = 1; -+ cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); -+ -+ /* -+ * CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to -+ * be disabled. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) -+ __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); -+ -+ /* Wait for the link to come up */ -+ cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port); -+ start_cycle = cvmx_get_cycle(); -+ do { -+ if (cvmx_get_cycle() - start_cycle > -+ 2 * cvmx_sysinfo_get()->cpu_clock_hz) { -+ cvmx_dprintf("PCIe: Port %d link timeout\n", -+ pcie_port); -+ return -1; -+ } -+ cvmx_wait(10000); -+ pciercx_cfg032.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, -+ CVMX_PCIERCX_CFG032(pcie_port)); -+ } while (pciercx_cfg032.s.dlla == 0); -+ -+ /* Display the link status */ -+ cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, -+ pciercx_cfg032.s.nlw); -+ -+ /* -+ * Update the Replay Time Limit. Empirically, some PCIe -+ * devices take a little longer to respond than expected under -+ * load. As a workaround for this we configure the Replay Time -+ * Limit to the value expected for a 512 byte MPS instead of -+ * our actual 256 byte MPS. The numbers below are directly -+ * from the PCIe spec table 3-4. -+ */ -+ pciercx_cfg448.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); -+ switch (pciercx_cfg032.s.nlw) { -+ case 1: /* 1 lane */ -+ pciercx_cfg448.s.rtl = 1677; -+ break; -+ case 2: /* 2 lanes */ -+ pciercx_cfg448.s.rtl = 867; -+ break; -+ case 4: /* 4 lanes */ -+ pciercx_cfg448.s.rtl = 462; -+ break; -+ case 8: /* 8 lanes */ -+ pciercx_cfg448.s.rtl = 258; -+ break; -+ } -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), -+ pciercx_cfg448.u32); -+ -+ return 0; -+} -+ -+/** -+ * Initialize a PCIe port for use in host(RC) mode. It doesn't -+ * enumerate the bus. -+ * -+ * @pcie_port: PCIe port to initialize -+ * -+ * Returns Zero on success -+ */ -+int cvmx_pcie_rc_initialize(int pcie_port) -+{ -+ int i; -+ union cvmx_ciu_soft_prst ciu_soft_prst; -+ union cvmx_pescx_bist_status pescx_bist_status; -+ union cvmx_pescx_bist_status2 pescx_bist_status2; -+ union cvmx_npei_ctl_status npei_ctl_status; -+ union cvmx_npei_mem_access_ctl npei_mem_access_ctl; -+ union cvmx_npei_mem_access_subidx mem_access_subid; -+ union cvmx_npei_dbg_data npei_dbg_data; -+ union cvmx_pescx_ctl_status2 pescx_ctl_status2; -+ -+ /* -+ * Make sure we aren't trying to setup a target mode interface -+ * in host mode. -+ */ -+ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); -+ if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) { -+ cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called " -+ "on port0, but port0 is not in host mode\n"); -+ return -1; -+ } -+ -+ /* -+ * Make sure a CN52XX isn't trying to bring up port 1 when it -+ * is disabled. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); -+ if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) { -+ cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() " -+ "called on port1, but port1 is disabled\n"); -+ return -1; -+ } -+ } -+ -+ /* -+ * PCIe switch arbitration mode. '0' == fixed priority NPEI, -+ * PCIe0, then PCIe1. '1' == round robin. -+ */ -+ npei_ctl_status.s.arb = 1; -+ /* Allow up to 0x20 config retries */ -+ npei_ctl_status.s.cfg_rtry = 0x20; -+ /* -+ * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS -+ * don't reset. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { -+ npei_ctl_status.s.p0_ntags = 0x20; -+ npei_ctl_status.s.p1_ntags = 0x20; -+ } -+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); -+ -+ /* Bring the PCIe out of reset */ -+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) { -+ /* -+ * The EBH5200 board swapped the PCIe reset lines on -+ * the board. As a workaround for this bug, we bring -+ * both PCIe ports out of reset at the same time -+ * instead of on separate calls. So for port 0, we -+ * bring both out of reset and do nothing on port 1. -+ */ -+ if (pcie_port == 0) { -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ /* -+ * After a chip reset the PCIe will also be in -+ * reset. If it isn't, most likely someone is -+ * trying to init it again without a proper -+ * PCIe reset. -+ */ -+ if (ciu_soft_prst.s.soft_prst == 0) { -+ /* Reset the ports */ -+ ciu_soft_prst.s.soft_prst = 1; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, -+ ciu_soft_prst.u64); -+ ciu_soft_prst.u64 = -+ cvmx_read_csr(CVMX_CIU_SOFT_PRST1); -+ ciu_soft_prst.s.soft_prst = 1; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, -+ ciu_soft_prst.u64); -+ /* Wait until pcie resets the ports. */ -+ udelay(2000); -+ } -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); -+ ciu_soft_prst.s.soft_prst = 0; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ ciu_soft_prst.s.soft_prst = 0; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); -+ } -+ } else { -+ /* -+ * The normal case: The PCIe ports are completely -+ * separate and can be brought out of reset -+ * independently. -+ */ -+ if (pcie_port) -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); -+ else -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ /* -+ * After a chip reset the PCIe will also be in -+ * reset. If it isn't, most likely someone is trying -+ * to init it again without a proper PCIe reset. -+ */ -+ if (ciu_soft_prst.s.soft_prst == 0) { -+ /* Reset the port */ -+ ciu_soft_prst.s.soft_prst = 1; -+ if (pcie_port) -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, -+ ciu_soft_prst.u64); -+ else -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, -+ ciu_soft_prst.u64); -+ /* Wait until pcie resets the ports. */ -+ udelay(2000); -+ } -+ if (pcie_port) { -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); -+ ciu_soft_prst.s.soft_prst = 0; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); -+ } else { -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ ciu_soft_prst.s.soft_prst = 0; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); -+ } -+ } -+ -+ /* -+ * Wait for PCIe reset to complete. Due to errata PCIE-700, we -+ * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a -+ * fixed number of cycles. -+ */ -+ cvmx_wait(400000); -+ -+ /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and -+ CN52XX, so we only probe it on newer chips */ -+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) -+ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { -+ /* Clear PCLK_RUN so we can check if the clock is running */ -+ pescx_ctl_status2.u64 = -+ cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); -+ pescx_ctl_status2.s.pclk_run = 1; -+ cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), -+ pescx_ctl_status2.u64); -+ /* -+ * Now that we cleared PCLK_RUN, wait for it to be set -+ * again telling us the clock is running. -+ */ -+ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), -+ union cvmx_pescx_ctl_status2, -+ pclk_run, ==, 1, 10000)) { -+ cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", -+ pcie_port); -+ return -1; -+ } -+ } -+ -+ /* -+ * Check and make sure PCIe came out of reset. If it doesn't -+ * the board probably hasn't wired the clocks up and the -+ * interface should be skipped. -+ */ -+ pescx_ctl_status2.u64 = -+ cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); -+ if (pescx_ctl_status2.s.pcierst) { -+ cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", -+ pcie_port); -+ return -1; -+ } -+ -+ /* -+ * Check BIST2 status. If any bits are set skip this interface. This -+ * is an attempt to catch PCIE-813 on pass 1 parts. -+ */ -+ pescx_bist_status2.u64 = -+ cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); -+ if (pescx_bist_status2.u64) { -+ cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this " -+ "port isn't hooked up, skipping.\n", -+ pcie_port); -+ return -1; -+ } -+ -+ /* Check BIST status */ -+ pescx_bist_status.u64 = -+ cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); -+ if (pescx_bist_status.u64) -+ cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", -+ pcie_port, CAST64(pescx_bist_status.u64)); -+ -+ /* Initialize the config space CSRs */ -+ __cvmx_pcie_rc_initialize_config_space(pcie_port); -+ -+ /* Bring the link up */ -+ if (__cvmx_pcie_rc_initialize_link(pcie_port)) { -+ cvmx_dprintf -+ ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n"); -+ return -1; -+ } -+ -+ /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ -+ npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); -+ /* Allow 16 words to combine */ -+ npei_mem_access_ctl.s.max_word = 0; -+ /* Wait up to 127 cycles for more data */ -+ npei_mem_access_ctl.s.timer = 127; -+ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); -+ -+ /* Setup Mem access SubDIDs */ -+ mem_access_subid.u64 = 0; -+ /* Port the request is sent to. */ -+ mem_access_subid.s.port = pcie_port; -+ /* Due to an errata on pass 1 chips, no merging is allowed. */ -+ mem_access_subid.s.nmerge = 1; -+ /* Endian-swap for Reads. */ -+ mem_access_subid.s.esr = 1; -+ /* Endian-swap for Writes. */ -+ mem_access_subid.s.esw = 1; -+ /* No Snoop for Reads. */ -+ mem_access_subid.s.nsr = 1; -+ /* No Snoop for Writes. */ -+ mem_access_subid.s.nsw = 1; -+ /* Disable Relaxed Ordering for Reads. */ -+ mem_access_subid.s.ror = 0; -+ /* Disable Relaxed Ordering for Writes. */ -+ mem_access_subid.s.row = 0; -+ /* PCIe Adddress Bits <63:34>. */ -+ mem_access_subid.s.ba = 0; -+ -+ /* -+ * Setup mem access 12-15 for port 0, 16-19 for port 1, -+ * supplying 36 bits of address space. -+ */ -+ for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) { -+ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), -+ mem_access_subid.u64); -+ /* Set each SUBID to extend the addressable range */ -+ mem_access_subid.s.ba += 1; -+ } -+ -+ /* -+ * Disable the peer to peer forwarding register. This must be -+ * setup by the OS after it enumerates the bus and assigns -+ * addresses to the PCIe busses. -+ */ -+ for (i = 0; i < 4; i++) { -+ cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1); -+ cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1); -+ } -+ -+ /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ -+ cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); -+ -+ /* -+ * Disable Octeon's BAR1. It isn't needed in RC mode since -+ * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into -+ * the 2nd 256MB of memory. -+ */ -+ cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1); -+ -+ /* -+ * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take -+ * precedence where they overlap. It also overlaps with the -+ * device addresses, so make sure the peer to peer forwarding -+ * is set right. -+ */ -+ cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0); -+ -+ /* -+ * Setup BAR2 attributes -+ * -+ * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) -+ * - PTLP_RO,CTLP_RO should normally be set (except for debug). -+ * - WAIT_COM=0 will likely work for all applications. -+ * -+ * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]). -+ */ -+ if (pcie_port) { -+ union cvmx_npei_ctl_port1 npei_ctl_port; -+ npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1); -+ npei_ctl_port.s.bar2_enb = 1; -+ npei_ctl_port.s.bar2_esx = 1; -+ npei_ctl_port.s.bar2_cax = 0; -+ npei_ctl_port.s.ptlp_ro = 1; -+ npei_ctl_port.s.ctlp_ro = 1; -+ npei_ctl_port.s.wait_com = 0; -+ npei_ctl_port.s.waitl_com = 0; -+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64); -+ } else { -+ union cvmx_npei_ctl_port0 npei_ctl_port; -+ npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0); -+ npei_ctl_port.s.bar2_enb = 1; -+ npei_ctl_port.s.bar2_esx = 1; -+ npei_ctl_port.s.bar2_cax = 0; -+ npei_ctl_port.s.ptlp_ro = 1; -+ npei_ctl_port.s.ctlp_ro = 1; -+ npei_ctl_port.s.wait_com = 0; -+ npei_ctl_port.s.waitl_com = 0; -+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); -+ } -+ return 0; -+} -+ -+/** -+ * Shutdown a PCIe port and put it in reset -+ * -+ * @pcie_port: PCIe port to shutdown -+ * -+ * Returns Zero on success -+ */ -+int cvmx_pcie_rc_shutdown(int pcie_port) -+{ -+ /* Wait for all pending operations to complete */ -+ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CPL_LUT_VALID(pcie_port), -+ union cvmx_pescx_cpl_lut_valid, -+ tag, ==, 0, 2000)) -+ cvmx_dprintf("PCIe: Port %d shutdown timeout\n", pcie_port); -+ -+ /* Force reset */ -+ if (pcie_port) { -+ union cvmx_ciu_soft_prst ciu_soft_prst; -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); -+ ciu_soft_prst.s.soft_prst = 1; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); -+ } else { -+ union cvmx_ciu_soft_prst ciu_soft_prst; -+ ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ ciu_soft_prst.s.soft_prst = 1; -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); -+ } -+ return 0; -+} -+ -+/** -+ * Build a PCIe config space request address for a device -+ * -+ * @pcie_port: PCIe port to access -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns 64bit Octeon IO address -+ */ -+static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, -+ int dev, int fn, int reg) -+{ -+ union cvmx_pcie_address pcie_addr; -+ union cvmx_pciercx_cfg006 pciercx_cfg006; -+ -+ pciercx_cfg006.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port)); -+ if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0)) -+ return 0; -+ -+ pcie_addr.u64 = 0; -+ pcie_addr.config.upper = 2; -+ pcie_addr.config.io = 1; -+ pcie_addr.config.did = 3; -+ pcie_addr.config.subdid = 1; -+ pcie_addr.config.es = 1; -+ pcie_addr.config.port = pcie_port; -+ pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum); -+ pcie_addr.config.bus = bus; -+ pcie_addr.config.dev = dev; -+ pcie_addr.config.func = fn; -+ pcie_addr.config.reg = reg; -+ return pcie_addr.u64; -+} -+ -+/** -+ * Read 8bits from a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns Result of the read -+ */ -+uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, -+ int fn, int reg) -+{ -+ uint64_t address = -+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); -+ if (address) -+ return cvmx_read64_uint8(address); -+ else -+ return 0xff; -+} -+ -+/** -+ * Read 16bits from a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns Result of the read -+ */ -+uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, -+ int reg) -+{ -+ uint64_t address = -+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); -+ if (address) -+ return le16_to_cpu(cvmx_read64_uint16(address)); -+ else -+ return 0xffff; -+} -+ -+/** -+ * Read 32bits from a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns Result of the read -+ */ -+uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, -+ int reg) -+{ -+ uint64_t address = -+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); -+ if (address) -+ return le32_to_cpu(cvmx_read64_uint32(address)); -+ else -+ return 0xffffffff; -+} -+ -+/** -+ * Write 8bits to a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * @val: Value to write -+ */ -+void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, -+ int reg, uint8_t val) -+{ -+ uint64_t address = -+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); -+ if (address) -+ cvmx_write64_uint8(address, val); -+} -+ -+/** -+ * Write 16bits to a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * @val: Value to write -+ */ -+void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, -+ int reg, uint16_t val) -+{ -+ uint64_t address = -+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); -+ if (address) -+ cvmx_write64_uint16(address, cpu_to_le16(val)); -+} -+ -+/** -+ * Write 32bits to a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * @val: Value to write -+ */ -+void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, -+ int reg, uint32_t val) -+{ -+ uint64_t address = -+ __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); -+ if (address) -+ cvmx_write64_uint32(address, cpu_to_le32(val)); -+} -+ -+/** -+ * Read a PCIe config space register indirectly. This is used for -+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. -+ * -+ * @pcie_port: PCIe port to read from -+ * @cfg_offset: Address to read -+ * -+ * Returns Value read -+ */ -+uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) -+{ -+ union cvmx_pescx_cfg_rd pescx_cfg_rd; -+ pescx_cfg_rd.u64 = 0; -+ pescx_cfg_rd.s.addr = cfg_offset; -+ cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); -+ pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); -+ return pescx_cfg_rd.s.data; -+} -+ -+/** -+ * Write a PCIe config space register indirectly. This is used for -+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. -+ * -+ * @pcie_port: PCIe port to write to -+ * @cfg_offset: Address to write -+ * @val: Value to write -+ */ -+void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val) -+{ -+ union cvmx_pescx_cfg_wr pescx_cfg_wr; -+ pescx_cfg_wr.u64 = 0; -+ pescx_cfg_wr.s.addr = cfg_offset; -+ pescx_cfg_wr.s.data = val; -+ cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); -+} -+ -+/** -+ * Initialize a PCIe port for use in target(EP) mode. -+ * -+ * Returns Zero on success -+ */ -+int cvmx_pcie_ep_initialize(void) -+{ -+ int pcie_port = 0; -+ union cvmx_npei_ctl_status npei_ctl_status; -+ union cvmx_pciercx_cfg030 pciercx_cfg030; -+ union cvmx_npei_ctl_status2 npei_ctl_status2; -+ union cvmx_npei_mem_access_subidx mem_access_subid; -+ -+ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); -+ if (npei_ctl_status.s.host_mode) -+ return -1; -+ -+ /* Enable bus master and memory */ -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIEEP_CFG001, 0x6); -+ -+ /* -+ * Max Payload Size (PCIE*_CFG030[MPS]) -+ * Max Read Request Size (PCIE*_CFG030[MRRS]) -+ * Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] -+ * Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) -+ */ -+ pciercx_cfg030.u32 = -+ cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); -+ /* Max payload size = 128 bytes (Limit of most PCs) */ -+ pciercx_cfg030.s.mps = 0; -+ /* -+ * Max read request size = 128 bytes for best Octeon DMA -+ * performance. -+ */ -+ pciercx_cfg030.s.mrrs = 0; -+ /* Enable relaxed ordering. */ -+ pciercx_cfg030.s.ro_en = 1; -+ /* Enable no snoop. */ -+ pciercx_cfg030.s.ns_en = 1; -+ /* Correctable error reporting enable. */ -+ pciercx_cfg030.s.ce_en = 1; -+ /* Non-fatal error reporting enable. */ -+ pciercx_cfg030.s.nfe_en = 1; -+ /* Fatal error reporting enable. */ -+ pciercx_cfg030.s.fe_en = 1; -+ /* Unsupported request reporting enable. */ -+ pciercx_cfg030.s.ur_en = 1; -+ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), -+ pciercx_cfg030.u32); -+ -+ /* -+ * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match -+ * PCIE*_CFG030[MPS] -+ * -+ * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not -+ * exceed PCIE*_CFG030[MRRS] -+ */ -+ npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); -+ /* Max payload size = 128 bytes (Limit of most PCs) */ -+ npei_ctl_status2.s.mps = 0; -+ /* Max read request size = 128 bytes for best Octeon DMA performance */ -+ npei_ctl_status2.s.mrrs = 0; -+ cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); -+ -+ /* Setup Mem access SubDID 12 to access Host memory */ -+ mem_access_subid.u64 = 0; -+ /* Port the request is sent to. */ -+ mem_access_subid.s.port = pcie_port; -+ /* Merging is allowed in this window. */ -+ mem_access_subid.s.nmerge = 1; -+ /* Endian-swap for Reads. */ -+ mem_access_subid.s.esr = 0; -+ /* Endian-swap for Writes. */ -+ mem_access_subid.s.esw = 0; -+ /* No Snoop for Reads. */ -+ mem_access_subid.s.nsr = 1; -+ /* No Snoop for Writes. */ -+ mem_access_subid.s.nsw = 1; -+ /* Disable Relaxed Ordering for Reads. */ -+ mem_access_subid.s.ror = 0; -+ /* Disable Relaxed Ordering for Writes. */ -+ mem_access_subid.s.row = 0; -+ /* PCIe Adddress Bits <63:34>. */ -+ mem_access_subid.s.ba = 0; -+ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(12), -+ mem_access_subid.u64); -+ return 0; -+} ---- /dev/null -+++ b/arch/mips/cavium-octeon/msi.c -@@ -0,0 +1,288 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2005-2007 Cavium Networks -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "pci-common.h" -+ -+/* -+ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is -+ * in use. -+ */ -+static uint64_t msi_free_irq_bitmask; -+ -+/* -+ * Each bit in msi_multiple_irq_bitmask tells that the device using -+ * this bit in msi_free_irq_bitmask is also using the next bit. This -+ * is used so we can disable all of the MSI interrupts when a device -+ * uses multiple. -+ */ -+static uint64_t msi_multiple_irq_bitmask; -+ -+/* -+ * This lock controls updates to msi_free_irq_bitmask and -+ * msi_multiple_irq_bitmask. -+ */ -+static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); -+ -+ -+/** -+ * Called when a driver request MSI interrupts instead of the -+ * legacy INT A-D. This routine will allocate multiple interrupts -+ * for MSI devices that support them. A device can override this by -+ * programming the MSI control bits [6:4] before calling -+ * pci_enable_msi(). -+ * -+ * @param dev Device requesting MSI interrupts -+ * @param desc MSI descriptor -+ * -+ * Returns 0 on success. -+ */ -+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) -+{ -+ struct msi_msg msg; -+ uint16_t control; -+ int configured_private_bits; -+ int request_private_bits; -+ int irq; -+ int irq_step; -+ uint64_t search_mask; -+ -+ /* -+ * Read the MSI config to figure out how many IRQs this device -+ * wants. Most devices only want 1, which will give -+ * configured_private_bits and request_private_bits equal 0. -+ */ -+ pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, -+ &control); -+ -+ /* -+ * If the number of private bits has been configured then use -+ * that value instead of the requested number. This gives the -+ * driver the chance to override the number of interrupts -+ * before calling pci_enable_msi(). -+ */ -+ configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4; -+ if (configured_private_bits == 0) { -+ /* Nothing is configured, so use the hardware requested size */ -+ request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1; -+ } else { -+ /* -+ * Use the number of configured bits, assuming the -+ * driver wanted to override the hardware request -+ * value. -+ */ -+ request_private_bits = configured_private_bits; -+ } -+ -+ /* -+ * The PCI 2.3 spec mandates that there are at most 32 -+ * interrupts. If this device asks for more, only give it one. -+ */ -+ if (request_private_bits > 5) -+ request_private_bits = 0; -+ -+try_only_one: -+ /* -+ * The IRQs have to be aligned on a power of two based on the -+ * number being requested. -+ */ -+ irq_step = 1 << request_private_bits; -+ -+ /* Mask with one bit for each IRQ */ -+ search_mask = (1 << irq_step) - 1; -+ -+ /* -+ * We're going to search msi_free_irq_bitmask_lock for zero -+ * bits. This represents an MSI interrupt number that isn't in -+ * use. -+ */ -+ spin_lock(&msi_free_irq_bitmask_lock); -+ for (irq = 0; irq < 64; irq += irq_step) { -+ if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) { -+ msi_free_irq_bitmask |= search_mask << irq; -+ msi_multiple_irq_bitmask |= (search_mask >> 1) << irq; -+ break; -+ } -+ } -+ spin_unlock(&msi_free_irq_bitmask_lock); -+ -+ /* Make sure the search for available interrupts didn't fail */ -+ if (irq >= 64) { -+ if (request_private_bits) { -+ pr_err("arch_setup_msi_irq: Unable to find %d free " -+ "interrupts, trying just one", -+ 1 << request_private_bits); -+ request_private_bits = 0; -+ goto try_only_one; -+ } else -+ panic("arch_setup_msi_irq: Unable to find a free MSI " -+ "interrupt"); -+ } -+ -+ /* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */ -+ irq += OCTEON_IRQ_MSI_BIT0; -+ -+ switch (octeon_dma_bar_type) { -+ case OCTEON_DMA_BAR_TYPE_SMALL: -+ /* When not using big bar, Bar 0 is based at 128MB */ -+ msg.address_lo = -+ ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff; -+ msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32; -+ case OCTEON_DMA_BAR_TYPE_BIG: -+ /* When using big bar, Bar 0 is based at 0 */ -+ msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff; -+ msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32; -+ break; -+ case OCTEON_DMA_BAR_TYPE_PCIE: -+ /* When using PCIe, Bar 0 is based at 0 */ -+ /* FIXME CVMX_NPEI_MSI_RCV* other than 0? */ -+ msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; -+ msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; -+ break; -+ default: -+ panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n"); -+ } -+ msg.data = irq - OCTEON_IRQ_MSI_BIT0; -+ -+ /* Update the number of IRQs the device has available to it */ -+ control &= ~PCI_MSI_FLAGS_QSIZE; -+ control |= request_private_bits << 4; -+ pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, -+ control); -+ -+ set_irq_msi(irq, desc); -+ write_msi_msg(irq, &msg); -+ return 0; -+} -+ -+ -+/** -+ * Called when a device no longer needs its MSI interrupts. All -+ * MSI interrupts for the device are freed. -+ * -+ * @irq: The devices first irq number. There may be multple in sequence. -+ */ -+void arch_teardown_msi_irq(unsigned int irq) -+{ -+ int number_irqs; -+ uint64_t bitmask; -+ -+ if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63)) -+ panic("arch_teardown_msi_irq: Attempted to teardown illegal " -+ "MSI interrupt (%d)", irq); -+ irq -= OCTEON_IRQ_MSI_BIT0; -+ -+ /* -+ * Count the number of IRQs we need to free by looking at the -+ * msi_multiple_irq_bitmask. Each bit set means that the next -+ * IRQ is also owned by this device. -+ */ -+ number_irqs = 0; -+ while ((irq+number_irqs < 64) && -+ (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs)))) -+ number_irqs++; -+ number_irqs++; -+ /* Mask with one bit for each IRQ */ -+ bitmask = (1 << number_irqs) - 1; -+ /* Shift the mask to the correct bit location */ -+ bitmask <<= irq; -+ if ((msi_free_irq_bitmask & bitmask) != bitmask) -+ panic("arch_teardown_msi_irq: Attempted to teardown MSI " -+ "interrupt (%d) not in use", irq); -+ -+ /* Checks are done, update the in use bitmask */ -+ spin_lock(&msi_free_irq_bitmask_lock); -+ msi_free_irq_bitmask &= ~bitmask; -+ msi_multiple_irq_bitmask &= ~bitmask; -+ spin_unlock(&msi_free_irq_bitmask_lock); -+} -+ -+ -+/** -+ * Called by the interrupt handling code when an MSI interrupt -+ * occurs. -+ * -+ * @param cpl -+ * @param dev_id -+ * -+ * @return -+ */ -+static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) -+{ -+ uint64_t msi_bits; -+ int irq; -+ -+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) -+ msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0); -+ else -+ msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV); -+ irq = fls64(msi_bits); -+ if (irq) { -+ irq += OCTEON_IRQ_MSI_BIT0 - 1; -+ if (irq_desc[irq].action) { -+ do_IRQ(irq); -+ return IRQ_HANDLED; -+ } else { -+ pr_err("Spurious MSI interrupt %d\n", irq); -+ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { -+ /* These chips have PCIe */ -+ cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0, -+ 1ull << (irq - -+ OCTEON_IRQ_MSI_BIT0)); -+ } else { -+ /* These chips have PCI */ -+ cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV, -+ 1ull << (irq - -+ OCTEON_IRQ_MSI_BIT0)); -+ } -+ } -+ } -+ return IRQ_NONE; -+} -+ -+ -+/** -+ * Initializes the MSI interrupt handling code -+ * -+ * @return -+ */ -+int octeon_msi_initialize(void) -+{ -+ int r; -+ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { -+ r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, -+ IRQF_SHARED, -+ "MSI[0:63]", octeon_msi_interrupt); -+ } else if (octeon_is_pci_host()) { -+ r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, -+ IRQF_SHARED, -+ "MSI[0:15]", octeon_msi_interrupt); -+ r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, -+ IRQF_SHARED, -+ "MSI[16:31]", octeon_msi_interrupt); -+ r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, -+ IRQF_SHARED, -+ "MSI[32:47]", octeon_msi_interrupt); -+ r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, -+ IRQF_SHARED, -+ "MSI[48:63]", octeon_msi_interrupt); -+ } -+ return 0; -+} -+ -+subsys_initcall(octeon_msi_initialize); ---- a/arch/mips/cavium-octeon/octeon-irq.c -+++ b/arch/mips/cavium-octeon/octeon-irq.c -@@ -10,6 +10,8 @@ - #include - - #include -+#include -+#include - - DEFINE_RWLOCK(octeon_irq_ciu0_rwlock); - DEFINE_RWLOCK(octeon_irq_ciu1_rwlock); ---- /dev/null -+++ b/arch/mips/cavium-octeon/pci-common.c -@@ -0,0 +1,137 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2005-2007 Cavium Networks -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "pci-common.h" -+ -+typeof(pcibios_map_irq) *octeon_pcibios_map_irq; -+enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; -+ -+/** -+ * Map a PCI device to the appropriate interrupt line -+ * -+ * @param dev The Linux PCI device structure for the device to map -+ * @param slot The slot number for this device on __BUS 0__. Linux -+ * enumerates through all the bridges and figures out the -+ * slot on Bus 0 where this device eventually hooks to. -+ * @param pin The PCI interrupt pin read from the device, then swizzled -+ * as it goes through each bridge. -+ * @return Interrupt number for the device -+ */ -+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (octeon_pcibios_map_irq) -+ return octeon_pcibios_map_irq(dev, slot, pin); -+ else -+ panic("octeon_pcibios_map_irq doesn't point to a " -+ "pcibios_map_irq() function"); -+} -+ -+ -+/** -+ * Called to perform platform specific PCI setup -+ * -+ * @param dev -+ * @return -+ */ -+int pcibios_plat_dev_init(struct pci_dev *dev) -+{ -+ uint16_t config; -+ uint32_t dconfig; -+ int pos; -+ /* -+ * Force the Cache line setting to 64 bytes. The standard -+ * Linux bus scan doesn't seem to set it. Octeon really has -+ * 128 byte lines, but Intel bridges get really upset if you -+ * try and set values above 64 bytes. Value is specified in -+ * 32bit words. -+ */ -+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); -+ /* Set latency timers for all devices */ -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); -+ -+ /* Enable reporting System errors and parity errors on all devices */ -+ /* Enable parity checking and error reporting */ -+ pci_read_config_word(dev, PCI_COMMAND, &config); -+ config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; -+ pci_write_config_word(dev, PCI_COMMAND, config); -+ -+ if (dev->subordinate) { -+ /* Set latency timers on sub bridges */ -+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); -+ /* More bridge error detection */ -+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); -+ config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; -+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config); -+ } -+ -+ /* Enable the PCIe normal error reporting */ -+ pos = pci_find_capability(dev, PCI_CAP_ID_EXP); -+ if (pos) { -+ /* Update Device Control */ -+ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); -+ /* Correctable Error Reporting */ -+ config |= PCI_EXP_DEVCTL_CERE; -+ /* Non-Fatal Error Reporting */ -+ config |= PCI_EXP_DEVCTL_NFERE; -+ /* Fatal Error Reporting */ -+ config |= PCI_EXP_DEVCTL_FERE; -+ /* Unsupported Request */ -+ config |= PCI_EXP_DEVCTL_URRE; -+ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); -+ } -+ -+ /* Find the Advanced Error Reporting capability */ -+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); -+ if (pos) { -+ /* Clear Uncorrectable Error Status */ -+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, -+ &dconfig); -+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, -+ dconfig); -+ /* Enable reporting of all uncorrectable errors */ -+ /* Uncorrectable Error Mask - turned on bits disable errors */ -+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0); -+ /* -+ * Leave severity at HW default. This only controls if -+ * errors are reported as uncorrectable or -+ * correctable, not if the error is reported. -+ */ -+ /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */ -+ /* Clear Correctable Error Status */ -+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig); -+ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig); -+ /* Enable reporting of all correctable errors */ -+ /* Correctable Error Mask - turned on bits disable errors */ -+ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0); -+ /* Advanced Error Capabilities */ -+ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig); -+ /* ECRC Generation Enable */ -+ if (config & PCI_ERR_CAP_ECRC_GENC) -+ config |= PCI_ERR_CAP_ECRC_GENE; -+ /* ECRC Check Enable */ -+ if (config & PCI_ERR_CAP_ECRC_CHKC) -+ config |= PCI_ERR_CAP_ECRC_CHKE; -+ pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig); -+ /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */ -+ /* Report all errors to the root complex */ -+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, -+ PCI_ERR_ROOT_CMD_COR_EN | -+ PCI_ERR_ROOT_CMD_NONFATAL_EN | -+ PCI_ERR_ROOT_CMD_FATAL_EN); -+ /* Clear the Root status register */ -+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig); -+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig); -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/arch/mips/cavium-octeon/pci-common.h -@@ -0,0 +1,39 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2005-2007 Cavium Networks -+ */ -+#ifndef __OCTEON_PCI_COMMON_H__ -+#define __OCTEON_PCI_COMMON_H__ -+ -+#include -+ -+/* Some PCI cards require delays when accessing config space. */ -+#define PCI_CONFIG_SPACE_DELAY 10000 -+ -+/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the -+ Octeon specific version pointed to by this variable. This function needs to -+ change for PCI or PCIe based hosts */ -+extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq; -+ -+/* The following defines are only used when octeon_dma_bar_type = -+ OCTEON_DMA_BAR_TYPE_BIG */ -+#define OCTEON_PCI_BAR1_HOLE_BITS 5 -+#define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3)) -+ -+enum octeon_dma_bar_type { -+ OCTEON_DMA_BAR_TYPE_INVALID, -+ OCTEON_DMA_BAR_TYPE_SMALL, -+ OCTEON_DMA_BAR_TYPE_BIG, -+ OCTEON_DMA_BAR_TYPE_PCIE -+}; -+ -+/** -+ * This is a variable to tell the DMA mapping system in dma-octeon.c -+ * how to map PCI DMA addresses. -+ */ -+extern enum octeon_dma_bar_type octeon_dma_bar_type; -+ -+#endif ---- /dev/null -+++ b/arch/mips/cavium-octeon/pci.c -@@ -0,0 +1,568 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2005-2007 Cavium Networks -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "pci-common.h" -+ -+#define USE_OCTEON_INTERNAL_ARBITER -+ -+/* -+ * Octeon's PCI controller uses did=3, subdid=2 for PCI IO -+ * addresses. Use PCI endian swapping 1 so no address swapping is -+ * necessary. The Linux io routines will endian swap the data. -+ */ -+#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull -+#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32) -+ -+/* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */ -+#define OCTEON_PCI_MEMSPACE_OFFSET (0x00011b0000000000ull) -+ -+/** -+ * This is the bit decoding used for the Octeon PCI controller addresses -+ */ -+union octeon_pci_address { -+ uint64_t u64; -+ struct { -+ uint64_t upper:2; -+ uint64_t reserved:13; -+ uint64_t io:1; -+ uint64_t did:5; -+ uint64_t subdid:3; -+ uint64_t reserved2:4; -+ uint64_t endian_swap:2; -+ uint64_t reserved3:10; -+ uint64_t bus:8; -+ uint64_t dev:5; -+ uint64_t func:3; -+ uint64_t reg:8; -+ } s; -+}; -+ -+/** -+ * Return the mapping of PCI device number to IRQ line. Each -+ * character in the return string represents the interrupt -+ * line for the device at that position. Device 1 maps to the -+ * first character, etc. The characters A-D are used for PCI -+ * interrupts. -+ * -+ * Returns PCI interrupt mapping -+ */ -+const char *octeon_get_pci_interrupts(void) -+{ -+ /* -+ * Returning an empty string causes the interrupts to be -+ * routed based on the PCI specification. From the PCI spec: -+ * -+ * INTA# of Device Number 0 is connected to IRQW on the system -+ * board. (Device Number has no significance regarding being -+ * located on the system board or in a connector.) INTA# of -+ * Device Number 1 is connected to IRQX on the system -+ * board. INTA# of Device Number 2 is connected to IRQY on the -+ * system board. INTA# of Device Number 3 is connected to IRQZ -+ * on the system board. The table below describes how each -+ * agent's INTx# lines are connected to the system board -+ * interrupt lines. The following equation can be used to -+ * determine to which INTx# signal on the system board a given -+ * device's INTx# line(s) is connected. -+ * -+ * MB = (D + I) MOD 4 MB = System board Interrupt (IRQW = 0, -+ * IRQX = 1, IRQY = 2, and IRQZ = 3) D = Device Number I = -+ * Interrupt Number (INTA# = 0, INTB# = 1, INTC# = 2, and -+ * INTD# = 3) -+ */ -+ switch (octeon_bootinfo->board_type) { -+ case CVMX_BOARD_TYPE_NAO38: -+ /* This is really the NAC38 */ -+ return "AAAAADABAAAAAAAAAAAAAAAAAAAAAAAA"; -+ case CVMX_BOARD_TYPE_THUNDER: -+ return ""; -+ case CVMX_BOARD_TYPE_EBH3000: -+ return ""; -+ case CVMX_BOARD_TYPE_EBH3100: -+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: -+ return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; -+ case CVMX_BOARD_TYPE_BBGW_REF: -+ return "AABCD"; -+ default: -+ return ""; -+ } -+} -+ -+/** -+ * Map a PCI device to the appropriate interrupt line -+ * -+ * @dev: The Linux PCI device structure for the device to map -+ * @slot: The slot number for this device on __BUS 0__. Linux -+ * enumerates through all the bridges and figures out the -+ * slot on Bus 0 where this device eventually hooks to. -+ * @pin: The PCI interrupt pin read from the device, then swizzled -+ * as it goes through each bridge. -+ * Returns Interrupt number for the device -+ */ -+int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev, -+ u8 slot, u8 pin) -+{ -+ int irq_num; -+ const char *interrupts; -+ int dev_num; -+ -+ /* Get the board specific interrupt mapping */ -+ interrupts = octeon_get_pci_interrupts(); -+ -+ dev_num = dev->devfn >> 3; -+ if (dev_num < strlen(interrupts)) -+ irq_num = ((interrupts[dev_num] - 'A' + pin - 1) & 3) + -+ OCTEON_IRQ_PCI_INT0; -+ else -+ irq_num = ((slot + pin - 3) & 3) + OCTEON_IRQ_PCI_INT0; -+ return irq_num; -+} -+ -+ -+/** -+ * Read a value from configuration space -+ * -+ */ -+static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, -+ int reg, int size, u32 *val) -+{ -+ union octeon_pci_address pci_addr; -+ -+ pci_addr.u64 = 0; -+ pci_addr.s.upper = 2; -+ pci_addr.s.io = 1; -+ pci_addr.s.did = 3; -+ pci_addr.s.subdid = 1; -+ pci_addr.s.endian_swap = 1; -+ pci_addr.s.bus = bus->number; -+ pci_addr.s.dev = devfn >> 3; -+ pci_addr.s.func = devfn & 0x7; -+ pci_addr.s.reg = reg; -+ -+#if PCI_CONFIG_SPACE_DELAY -+ udelay(PCI_CONFIG_SPACE_DELAY); -+#endif -+ switch (size) { -+ case 4: -+ *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64)); -+ return PCIBIOS_SUCCESSFUL; -+ case 2: -+ *val = le16_to_cpu(cvmx_read64_uint16(pci_addr.u64)); -+ return PCIBIOS_SUCCESSFUL; -+ case 1: -+ *val = cvmx_read64_uint8(pci_addr.u64); -+ return PCIBIOS_SUCCESSFUL; -+ } -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+} -+ -+ -+/** -+ * Write a value to PCI configuration space -+ * -+ * @bus: -+ * @devfn: -+ * @reg: -+ * @size: -+ * @val: -+ * Returns -+ */ -+static int octeon_write_config(struct pci_bus *bus, unsigned int devfn, -+ int reg, int size, u32 val) -+{ -+ union octeon_pci_address pci_addr; -+ -+ pci_addr.u64 = 0; -+ pci_addr.s.upper = 2; -+ pci_addr.s.io = 1; -+ pci_addr.s.did = 3; -+ pci_addr.s.subdid = 1; -+ pci_addr.s.endian_swap = 1; -+ pci_addr.s.bus = bus->number; -+ pci_addr.s.dev = devfn >> 3; -+ pci_addr.s.func = devfn & 0x7; -+ pci_addr.s.reg = reg; -+ -+#if PCI_CONFIG_SPACE_DELAY -+ udelay(PCI_CONFIG_SPACE_DELAY); -+#endif -+ switch (size) { -+ case 4: -+ cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val)); -+ return PCIBIOS_SUCCESSFUL; -+ case 2: -+ cvmx_write64_uint16(pci_addr.u64, cpu_to_le16(val)); -+ return PCIBIOS_SUCCESSFUL; -+ case 1: -+ cvmx_write64_uint8(pci_addr.u64, val); -+ return PCIBIOS_SUCCESSFUL; -+ } -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+} -+ -+ -+static struct pci_ops octeon_pci_ops = { -+ octeon_read_config, -+ octeon_write_config, -+}; -+ -+static struct resource octeon_pci_mem_resource = { -+ .start = 0, -+ .end = 0, -+ .name = "Octeon PCI MEM", -+ .flags = IORESOURCE_MEM, -+}; -+ -+/* -+ * PCI ports must be above 16KB so the ISA bus filtering in the PCI-X to PCI -+ * bridge -+ */ -+static struct resource octeon_pci_io_resource = { -+ .start = 0x4000, -+ .end = OCTEON_PCI_IOSPACE_SIZE - 1, -+ .name = "Octeon PCI IO", -+ .flags = IORESOURCE_IO, -+}; -+ -+static struct pci_controller octeon_pci_controller = { -+ .pci_ops = &octeon_pci_ops, -+ .mem_resource = &octeon_pci_mem_resource, -+ .mem_offset = OCTEON_PCI_MEMSPACE_OFFSET, -+ .io_resource = &octeon_pci_io_resource, -+ .io_offset = 0, -+ .io_map_base = OCTEON_PCI_IOSPACE_BASE, -+}; -+ -+ -+/** -+ * Low level initialize the Octeon PCI controller -+ * -+ * Returns -+ */ -+static void octeon_pci_initialize(void) -+{ -+ union cvmx_pci_cfg01 cfg01; -+ union cvmx_npi_ctl_status ctl_status; -+ union cvmx_pci_ctl_status_2 ctl_status_2; -+ union cvmx_pci_cfg19 cfg19; -+ union cvmx_pci_cfg16 cfg16; -+ union cvmx_pci_cfg22 cfg22; -+ union cvmx_pci_cfg56 cfg56; -+ -+ /* Reset the PCI Bus */ -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1); -+ cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ -+ udelay(2000); /* Hold PCI reset for 2 ms */ -+ -+ ctl_status.u64 = 0; /* cvmx_read_csr(CVMX_NPI_CTL_STATUS); */ -+ ctl_status.s.max_word = 1; -+ ctl_status.s.timer = 1; -+ cvmx_write_csr(CVMX_NPI_CTL_STATUS, ctl_status.u64); -+ -+ /* Deassert PCI reset and advertize PCX Host Mode Device Capability -+ (64b) */ -+ cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4); -+ cvmx_read_csr(CVMX_CIU_SOFT_PRST); -+ -+ udelay(2000); /* Wait 2 ms after deasserting PCI reset */ -+ -+ ctl_status_2.u32 = 0; -+ ctl_status_2.s.tsr_hwm = 1; /* Initializes to 0. Must be set -+ before any PCI reads. */ -+ ctl_status_2.s.bar2pres = 1; /* Enable BAR2 */ -+ ctl_status_2.s.bar2_enb = 1; -+ ctl_status_2.s.bar2_cax = 1; /* Don't use L2 */ -+ ctl_status_2.s.bar2_esx = 1; -+ ctl_status_2.s.pmo_amod = 1; /* Round robin priority */ -+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { -+ /* BAR1 hole */ -+ ctl_status_2.s.bb1_hole = OCTEON_PCI_BAR1_HOLE_BITS; -+ ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */ -+ ctl_status_2.s.bb_ca = 1; /* Don't use L2 with big bars */ -+ ctl_status_2.s.bb_es = 1; /* Big bar in byte swap mode */ -+ ctl_status_2.s.bb1 = 1; /* BAR1 is big */ -+ ctl_status_2.s.bb0 = 1; /* BAR0 is big */ -+ } -+ -+ octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32); -+ udelay(2000); /* Wait 2 ms before doing PCI reads */ -+ -+ ctl_status_2.u32 = octeon_npi_read32(CVMX_NPI_PCI_CTL_STATUS_2); -+ pr_notice("PCI Status: %s %s-bit\n", -+ ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI", -+ ctl_status_2.s.ap_64ad ? "64" : "32"); -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ union cvmx_pci_cnt_reg cnt_reg_start; -+ union cvmx_pci_cnt_reg cnt_reg_end; -+ unsigned long cycles, pci_clock; -+ -+ cnt_reg_start.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); -+ cycles = read_c0_cvmcount(); -+ udelay(1000); -+ cnt_reg_end.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG); -+ cycles = read_c0_cvmcount() - cycles; -+ pci_clock = (cnt_reg_end.s.pcicnt - cnt_reg_start.s.pcicnt) / -+ (cycles / (mips_hpt_frequency / 1000000)); -+ pr_notice("PCI Clock: %lu MHz\n", pci_clock); -+ } -+ -+ /* -+ * TDOMC must be set to one in PCI mode. TDOMC should be set to 4 -+ * in PCI-X mode to allow four oustanding splits. Otherwise, -+ * should not change from its reset value. Don't write PCI_CFG19 -+ * in PCI mode (0x82000001 reset value), write it to 0x82000004 -+ * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero. -+ * MRBCM -> must be one. -+ */ -+ if (ctl_status_2.s.ap_pcix) { -+ cfg19.u32 = 0; -+ /* -+ * Target Delayed/Split request outstanding maximum -+ * count. [1..31] and 0=32. NOTE: If the user -+ * programs these bits beyond the Designed Maximum -+ * outstanding count, then the designed maximum table -+ * depth will be used instead. No additional -+ * Deferred/Split transactions will be accepted if -+ * this outstanding maximum count is -+ * reached. Furthermore, no additional deferred/split -+ * transactions will be accepted if the I/O delay/ I/O -+ * Split Request outstanding maximum is reached. -+ */ -+ cfg19.s.tdomc = 4; -+ /* -+ * Master Deferred Read Request Outstanding Max Count -+ * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC -+ * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101 -+ * 5 2 110 6 3 111 7 3 For example, if these bits are -+ * programmed to 100, the core can support 2 DAC -+ * cycles, 4 SAC cycles or a combination of 1 DAC and -+ * 2 SAC cycles. NOTE: For the PCI-X maximum -+ * outstanding split transactions, refer to -+ * CRE0[22:20]. -+ */ -+ cfg19.s.mdrrmc = 2; -+ /* -+ * Master Request (Memory Read) Byte Count/Byte Enable -+ * select. 0 = Byte Enables valid. In PCI mode, a -+ * burst transaction cannot be performed using Memory -+ * Read command=4?h6. 1 = DWORD Byte Count valid -+ * (default). In PCI Mode, the memory read byte -+ * enables are automatically generated by the -+ * core. Note: N3 Master Request transaction sizes are -+ * always determined through the -+ * am_attr[<35:32>|<7:0>] field. -+ */ -+ cfg19.s.mrbcm = 1; -+ octeon_npi_write32(CVMX_NPI_PCI_CFG19, cfg19.u32); -+ } -+ -+ -+ cfg01.u32 = 0; -+ cfg01.s.msae = 1; /* Memory Space Access Enable */ -+ cfg01.s.me = 1; /* Master Enable */ -+ cfg01.s.pee = 1; /* PERR# Enable */ -+ cfg01.s.see = 1; /* System Error Enable */ -+ cfg01.s.fbbe = 1; /* Fast Back to Back Transaction Enable */ -+ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); -+ -+#ifdef USE_OCTEON_INTERNAL_ARBITER -+ /* -+ * When OCTEON is a PCI host, most systems will use OCTEON's -+ * internal arbiter, so must enable it before any PCI/PCI-X -+ * traffic can occur. -+ */ -+ { -+ union cvmx_npi_pci_int_arb_cfg pci_int_arb_cfg; -+ -+ pci_int_arb_cfg.u64 = 0; -+ pci_int_arb_cfg.s.en = 1; /* Internal arbiter enable */ -+ cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64); -+ } -+#endif /* USE_OCTEON_INTERNAL_ARBITER */ -+ -+ /* -+ * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE, -+ * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to -+ * 1..7. -+ */ -+ cfg16.u32 = 0; -+ cfg16.s.mltd = 1; /* Master Latency Timer Disable */ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG16, cfg16.u32); -+ -+ /* -+ * Should be written to 0x4ff00. MTTV -> must be zero. -+ * FLUSH -> must be 1. MRV -> should be 0xFF. -+ */ -+ cfg22.u32 = 0; -+ /* Master Retry Value [1..255] and 0=infinite */ -+ cfg22.s.mrv = 0xff; -+ /* -+ * AM_DO_FLUSH_I control NOTE: This bit MUST BE ONE for proper -+ * N3K operation. -+ */ -+ cfg22.s.flush = 1; -+ octeon_npi_write32(CVMX_NPI_PCI_CFG22, cfg22.u32); -+ -+ /* -+ * MOST Indicates the maximum number of outstanding splits (in -1 -+ * notation) when OCTEON is in PCI-X mode. PCI-X performance is -+ * affected by the MOST selection. Should generally be written -+ * with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807, -+ * depending on the desired MOST of 3, 2, 1, or 0, respectively. -+ */ -+ cfg56.u32 = 0; -+ cfg56.s.pxcid = 7; /* RO - PCI-X Capability ID */ -+ cfg56.s.ncp = 0xe8; /* RO - Next Capability Pointer */ -+ cfg56.s.dpere = 1; /* Data Parity Error Recovery Enable */ -+ cfg56.s.roe = 1; /* Relaxed Ordering Enable */ -+ cfg56.s.mmbc = 1; /* Maximum Memory Byte Count -+ [0=512B,1=1024B,2=2048B,3=4096B] */ -+ cfg56.s.most = 3; /* Maximum outstanding Split transactions [0=1 -+ .. 7=32] */ -+ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG56, cfg56.u32); -+ -+ /* -+ * Affects PCI performance when OCTEON services reads to its -+ * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are -+ * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and -+ * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700, -+ * these values need to be changed so they won't possibly prefetch off -+ * of the end of memory if PCI is DMAing a buffer at the end of -+ * memory. Note that these values differ from their reset values. -+ */ -+ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_6, 0x21); -+ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_C, 0x31); -+ octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_E, 0x31); -+} -+ -+ -+/** -+ * Initialize the Octeon PCI controller -+ * -+ * Returns -+ */ -+static int __init octeon_pci_setup(void) -+{ -+ union cvmx_npi_mem_access_subidx mem_access; -+ int index; -+ -+ /* Only these chips have PCI */ -+ if (octeon_has_feature(OCTEON_FEATURE_PCIE)) -+ return 0; -+ -+ /* Point pcibios_map_irq() to the PCI version of it */ -+ octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq; -+ -+ /* Only use the big bars on chips that support it */ -+ if (OCTEON_IS_MODEL(OCTEON_CN31XX) || -+ OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) || -+ OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) -+ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_SMALL; -+ else -+ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG; -+ -+ /* PCI I/O and PCI MEM values */ -+ set_io_port_base(OCTEON_PCI_IOSPACE_BASE); -+ ioport_resource.start = 0; -+ ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; -+ if (!octeon_is_pci_host()) { -+ pr_notice("Not in host mode, PCI Controller not initialized\n"); -+ return 0; -+ } -+ -+ pr_notice("%s Octeon big bar support\n", -+ (octeon_dma_bar_type == -+ OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling"); -+ -+ octeon_pci_initialize(); -+ -+ mem_access.u64 = 0; -+ mem_access.s.esr = 1; /* Endian-Swap on read. */ -+ mem_access.s.esw = 1; /* Endian-Swap on write. */ -+ mem_access.s.nsr = 0; /* No-Snoop on read. */ -+ mem_access.s.nsw = 0; /* No-Snoop on write. */ -+ mem_access.s.ror = 0; /* Relax Read on read. */ -+ mem_access.s.row = 0; /* Relax Order on write. */ -+ mem_access.s.ba = 0; /* PCI Address bits [63:36]. */ -+ cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, mem_access.u64); -+ -+ /* -+ * Remap the Octeon BAR 2 above all 32 bit devices -+ * (0x8000000000ul). This is done here so it is remapped -+ * before the readl()'s below. We don't want BAR2 overlapping -+ * with BAR0/BAR1 during these reads. -+ */ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0); -+ octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80); -+ -+ /* Disable the BAR1 movable mappings */ -+ for (index = 0; index < 32; index++) -+ octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); -+ -+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) { -+ /* Remap the Octeon BAR 0 to 0-2GB */ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG04, 0); -+ octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); -+ -+ /* -+ * Remap the Octeon BAR 1 to map 2GB-4GB (minus the -+ * BAR 1 hole). -+ */ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30); -+ octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); -+ -+ /* Devices go after BAR1 */ -+ octeon_pci_mem_resource.start = -+ OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) - -+ (OCTEON_PCI_BAR1_HOLE_SIZE << 20); -+ octeon_pci_mem_resource.end = -+ octeon_pci_mem_resource.start + (1ul << 30); -+ } else { -+ /* Remap the Octeon BAR 0 to map 128MB-(128MB+4KB) */ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG04, 128ul << 20); -+ octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0); -+ -+ /* Remap the Octeon BAR 1 to map 0-128MB */ -+ octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0); -+ octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0); -+ -+ /* Devices go after BAR0 */ -+ octeon_pci_mem_resource.start = -+ OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) + -+ (4ul << 10); -+ octeon_pci_mem_resource.end = -+ octeon_pci_mem_resource.start + (1ul << 30); -+ } -+ -+ register_pci_controller(&octeon_pci_controller); -+ -+ /* -+ * Clear any errors that might be pending from before the bus -+ * was setup properly. -+ */ -+ cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1); -+ return 0; -+} -+ -+arch_initcall(octeon_pci_setup); ---- /dev/null -+++ b/arch/mips/cavium-octeon/pcie.c -@@ -0,0 +1,441 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2007, 2008 Cavium Networks -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "pci-common.h" -+ -+/** -+ * Map a PCI device to the appropriate interrupt line -+ * -+ * @param dev The Linux PCI device structure for the device to map -+ * @param slot The slot number for this device on __BUS 0__. Linux -+ * enumerates through all the bridges and figures out the -+ * slot on Bus 0 where this device eventually hooks to. -+ * @param pin The PCI interrupt pin read from the device, then swizzled -+ * as it goes through each bridge. -+ * @return Interrupt number for the device -+ */ -+int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, -+ u8 slot, u8 pin) -+{ -+ /* -+ * The EBH5600 board with the PCI to PCIe bridge mistakenly -+ * wires the first slot for both device id 2 and interrupt -+ * A. According to the PCI spec, device id 2 should be C. The -+ * following kludge attempts to fix this. -+ */ -+ if (strstr(octeon_board_type_string(), "EBH5600") && -+ dev->bus && dev->bus->parent) { -+ /* -+ * Iterate all the way up the device chain and find -+ * the root bus. -+ */ -+ while (dev->bus && dev->bus->parent) -+ dev = to_pci_dev(dev->bus->bridge); -+ /* If the root bus is number 0 and the PEX 8114 is the -+ * root, assume we are behind the miswired bus. We -+ * need to correct the swizzle level by two. Yuck. -+ */ -+ if ((dev->bus->number == 0) && -+ (dev->vendor == 0x10b5) && (dev->device == 0x8114)) { -+ /* -+ * The pin field is one based, not zero. We -+ * need to swizzle it by minus two. -+ */ -+ pin = ((pin - 3) & 3) + 1; -+ } -+ } -+ /* -+ * The -1 is because pin starts with one, not zero. It might -+ * be that this equation needs to include the slot number, but -+ * I don't have hardware to check that against. -+ */ -+ return pin - 1 + OCTEON_IRQ_PCI_INT0; -+} -+ -+/** -+ * Read a value from configuration space -+ * -+ * @param bus -+ * @param devfn -+ * @param reg -+ * @param size -+ * @param val -+ * @return -+ */ -+static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, -+ unsigned int devfn, int reg, int size, -+ u32 *val) -+{ -+ union octeon_cvmemctl cvmmemctl; -+ union octeon_cvmemctl cvmmemctl_save; -+ int bus_number = bus->number; -+ -+ /* -+ * We need to force the bus number to be zero on the root -+ * bus. Linux numbers the 2nd root bus to start after all -+ * buses on root 0. -+ */ -+ if (bus->parent == NULL) -+ bus_number = 0; -+ -+ /* -+ * PCIe only has a single device connected to Octeon. It is -+ * always device ID 0. Don't bother doing reads for other -+ * device IDs on the first segment. -+ */ -+ if ((bus_number == 0) && (devfn >> 3 != 0)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ -+ /* -+ * The following is a workaround for the CN57XX, CN56XX, -+ * CN55XX, and CN54XX errata with PCIe config reads from non -+ * existent devices. These chips will hang the PCIe link if a -+ * config read is performed that causes a UR response. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || -+ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) { -+ /* -+ * For our EBH5600 board, port 0 has a bridge with two -+ * PCI-X slots. We need a new special checks to make -+ * sure we only probe valid stuff. The PCIe->PCI-X -+ * bridge only respondes to device ID 0, function -+ * 0-1 -+ */ -+ if ((bus_number == 0) && (devfn >= 2)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ /* -+ * The PCI-X slots are device ID 2,3. Choose one of -+ * the below "if" blocks based on what is plugged into -+ * the board. -+ */ -+#if 1 -+ /* Use this option if you aren't using either slot */ -+ if (bus_number == 1) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+#elif 0 -+ /* -+ * Use this option if you are using the first slot but -+ * not the second. -+ */ -+ if ((bus_number == 1) && (devfn >> 3 != 2)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+#elif 0 -+ /* -+ * Use this option if you are using the second slot -+ * but not the first. -+ */ -+ if ((bus_number == 1) && (devfn >> 3 != 3)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+#elif 0 -+ /* Use this opion if you are using both slots */ -+ if ((bus_number == 1) && -+ !((devfn == (2 << 3)) || (devfn == (3 << 3)))) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+#endif -+ -+ /* -+ * The following #if gives a more complicated -+ * example. This is the required checks for running a -+ * Nitrox CN16XX-NHBX in the slot of the EBH5600. This -+ * card has a PLX PCIe bridge with four Nitrox PLX -+ * parts behind it. -+ */ -+#if 0 -+ /* PLX bridge with 4 ports */ -+ if ((bus_number == 3) && -+ !((devfn >> 3 >= 1) && (devfn >> 3 <= 4))) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ /* Nitrox behind PLX 1 */ -+ if ((bus_number == 4) && (devfn >> 3 != 0)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ /* Nitrox behind PLX 2 */ -+ if ((bus_number == 5) && (devfn >> 3 != 0)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ /* Nitrox behind PLX 3 */ -+ if ((bus_number == 6) && (devfn >> 3 != 0)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ /* Nitrox behind PLX 4 */ -+ if ((bus_number == 7) && (devfn >> 3 != 0)) -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+#endif -+ /* -+ * Shorten the DID timeout so bus errors for PCIe -+ * config reads from non existent devices happen -+ * faster. This allows us to continue booting even if -+ * the above "if" checks are wrong. Once one of these -+ * errors happens, the PCIe port is dead. -+ */ -+ cvmmemctl_save.u64 = __read_64bit_c0_register($11, 7); -+ cvmmemctl.u64 = cvmmemctl_save.u64; -+ cvmmemctl.s.didtto = 2; -+ __write_64bit_c0_register($11, 7, cvmmemctl.u64); -+ } -+ -+ switch (size) { -+ case 4: -+ *val = cvmx_pcie_config_read32(pcie_port, bus_number, -+ devfn >> 3, devfn & 0x7, reg); -+ break; -+ case 2: -+ *val = cvmx_pcie_config_read16(pcie_port, bus_number, -+ devfn >> 3, devfn & 0x7, reg); -+ break; -+ case 1: -+ *val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3, -+ devfn & 0x7, reg); -+ break; -+ default: -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+ } -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || -+ OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) -+ __write_64bit_c0_register($11, 7, cvmmemctl_save.u64); -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int octeon_pcie0_read_config(struct pci_bus *bus, unsigned int devfn, -+ int reg, int size, u32 *val) -+{ -+ return octeon_pcie_read_config(0, bus, devfn, reg, size, val); -+} -+ -+static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn, -+ int reg, int size, u32 *val) -+{ -+ return octeon_pcie_read_config(1, bus, devfn, reg, size, val); -+} -+ -+ -+ -+/** -+ * Write a value to PCI configuration space -+ * -+ * @param bus -+ * @param devfn -+ * @param reg -+ * @param size -+ * @param val -+ * @return -+ */ -+static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus, -+ unsigned int devfn, int reg, -+ int size, u32 val) -+{ -+ int bus_number = bus->number; -+ /* -+ * We need to force the bus number to be zero on the root -+ * bus. Linux numbers the 2nd root bus to start after all -+ * busses on root 0. -+ */ -+ if (bus->parent == NULL) -+ bus_number = 0; -+ -+ switch (size) { -+ case 4: -+ cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3, -+ devfn & 0x7, reg, val); -+ return PCIBIOS_SUCCESSFUL; -+ case 2: -+ cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3, -+ devfn & 0x7, reg, val); -+ return PCIBIOS_SUCCESSFUL; -+ case 1: -+ cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3, -+ devfn & 0x7, reg, val); -+ return PCIBIOS_SUCCESSFUL; -+ } -+#if PCI_CONFIG_SPACE_DELAY -+ udelay(PCI_CONFIG_SPACE_DELAY); -+#endif -+ return PCIBIOS_FUNC_NOT_SUPPORTED; -+} -+ -+static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn, -+ int reg, int size, u32 val) -+{ -+ return octeon_pcie_write_config(0, bus, devfn, reg, size, val); -+} -+ -+static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn, -+ int reg, int size, u32 val) -+{ -+ return octeon_pcie_write_config(1, bus, devfn, reg, size, val); -+} -+ -+static struct pci_ops octeon_pcie0_ops = { -+ octeon_pcie0_read_config, -+ octeon_pcie0_write_config, -+}; -+ -+static struct resource octeon_pcie0_mem_resource = { -+ .name = "Octeon PCIe0 MEM", -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct resource octeon_pcie0_io_resource = { -+ .name = "Octeon PCIe0 IO", -+ .flags = IORESOURCE_IO, -+}; -+ -+static struct pci_controller octeon_pcie0_controller = { -+ .pci_ops = &octeon_pcie0_ops, -+ .mem_resource = &octeon_pcie0_mem_resource, -+ .io_resource = &octeon_pcie0_io_resource, -+}; -+ -+static struct pci_ops octeon_pcie1_ops = { -+ octeon_pcie1_read_config, -+ octeon_pcie1_write_config, -+}; -+ -+static struct resource octeon_pcie1_mem_resource = { -+ .name = "Octeon PCIe1 MEM", -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct resource octeon_pcie1_io_resource = { -+ .name = "Octeon PCIe1 IO", -+ .flags = IORESOURCE_IO, -+}; -+ -+static struct pci_controller octeon_pcie1_controller = { -+ .pci_ops = &octeon_pcie1_ops, -+ .mem_resource = &octeon_pcie1_mem_resource, -+ .io_resource = &octeon_pcie1_io_resource, -+}; -+ -+ -+/** -+ * Initialize the Octeon PCIe controllers -+ * -+ * @return -+ */ -+static int __init octeon_pcie_setup(void) -+{ -+ union cvmx_npei_ctl_status npei_ctl_status; -+ int result; -+ -+ /* These chips don't have PCIe */ -+ if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) -+ return 0; -+ -+ /* Point pcibios_map_irq() to the PCIe version of it */ -+ octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq; -+ -+ /* Use the PCIe based DMA mappings */ -+ octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE; -+ -+ /* -+ * PCIe I/O range. It is based on port 0 but includes up until -+ * port 1's end. -+ */ -+ set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0))); -+ ioport_resource.start = 0; -+ ioport_resource.end = -+ cvmx_pcie_get_io_base_address(1) - -+ cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1; -+ -+ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); -+ if (npei_ctl_status.s.host_mode) { -+ pr_notice("PCIe: Initializing port 0\n"); -+ result = cvmx_pcie_rc_initialize(0); -+ if (result == 0) { -+ /* Memory offsets are physical addresses */ -+ octeon_pcie0_controller.mem_offset = -+ cvmx_pcie_get_mem_base_address(0); -+ /* IO offsets are Mips virtual addresses */ -+ octeon_pcie0_controller.io_map_base = -+ CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address -+ (0)); -+ octeon_pcie0_controller.io_offset = 0; -+ /* -+ * To keep things similar to PCI, we start -+ * device addresses at the same place as PCI -+ * uisng big bar support. This normally -+ * translates to 4GB-256MB, which is the same -+ * as most x86 PCs. -+ */ -+ octeon_pcie0_controller.mem_resource->start = -+ cvmx_pcie_get_mem_base_address(0) + -+ (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); -+ octeon_pcie0_controller.mem_resource->end = -+ cvmx_pcie_get_mem_base_address(0) + -+ cvmx_pcie_get_mem_size(0) - 1; -+ /* -+ * Ports must be above 16KB for the ISA bus -+ * filtering in the PCI-X to PCI bridge. -+ */ -+ octeon_pcie0_controller.io_resource->start = 4 << 10; -+ octeon_pcie0_controller.io_resource->end = -+ cvmx_pcie_get_io_size(0) - 1; -+ register_pci_controller(&octeon_pcie0_controller); -+ } -+ } else { -+ pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n"); -+ } -+ -+ /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ union cvmx_npei_dbg_data npei_dbg_data; -+ npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); -+ if (npei_dbg_data.cn52xx.qlm0_link_width) -+ return 0; -+ } -+ -+ pr_notice("PCIe: Initializing port 1\n"); -+ result = cvmx_pcie_rc_initialize(1); -+ if (result == 0) { -+ /* Memory offsets are physical addresses */ -+ octeon_pcie1_controller.mem_offset = -+ cvmx_pcie_get_mem_base_address(1); -+ /* IO offsets are Mips virtual addresses */ -+ octeon_pcie1_controller.io_map_base = -+ CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1)); -+ octeon_pcie1_controller.io_offset = -+ cvmx_pcie_get_io_base_address(1) - -+ cvmx_pcie_get_io_base_address(0); -+ /* -+ * To keep things similar to PCI, we start device -+ * addresses at the same place as PCI uisng big bar -+ * support. This normally translates to 4GB-256MB, -+ * which is the same as most x86 PCs. -+ */ -+ octeon_pcie1_controller.mem_resource->start = -+ cvmx_pcie_get_mem_base_address(1) + (4ul << 30) - -+ (OCTEON_PCI_BAR1_HOLE_SIZE << 20); -+ octeon_pcie1_controller.mem_resource->end = -+ cvmx_pcie_get_mem_base_address(1) + -+ cvmx_pcie_get_mem_size(1) - 1; -+ /* -+ * Ports must be above 16KB for the ISA bus filtering -+ * in the PCI-X to PCI bridge. -+ */ -+ octeon_pcie1_controller.io_resource->start = -+ cvmx_pcie_get_io_base_address(1) - -+ cvmx_pcie_get_io_base_address(0); -+ octeon_pcie1_controller.io_resource->end = -+ octeon_pcie1_controller.io_resource->start + -+ cvmx_pcie_get_io_size(1) - 1; -+ register_pci_controller(&octeon_pcie1_controller); -+ } -+ return 0; -+} -+ -+arch_initcall(octeon_pcie_setup); ---- a/arch/mips/include/asm/octeon/cvmx-asm.h -+++ b/arch/mips/include/asm/octeon/cvmx-asm.h -@@ -119,7 +119,8 @@ - asm ("pop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) - #define CVMX_DPOP(result, input) \ - asm ("dpop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) -- -+#define CVMX_CLZ(result, input) \ -+ asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) - /* some new cop0-like stuff */ - #define CVMX_RDHWR(result, regstr) \ - asm volatile ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result)) ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-helper-errata.h -@@ -0,0 +1,92 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Fixes and workaround for Octeon chip errata. This file -+ * contains functions called by cvmx-helper to workaround known -+ * chip errata. For the most part, code doesn't need to call -+ * these functions directly. -+ * -+ */ -+#ifndef __CVMX_HELPER_ERRATA_H__ -+#define __CVMX_HELPER_ERRATA_H__ -+ -+ -+#include "cvmx-wqe.h" -+ -+/** -+ * @INTERNAL -+ * Function to adjust internal IPD pointer alignments -+ * -+ * Returns 0 on success -+ * !0 on failure -+ */ -+extern int __cvmx_helper_errata_fix_ipd_ptr_alignment(void); -+ -+/** -+ * @INTERNAL -+ * Workaround ASX setup errata with CN38XX pass1 -+ * -+ * @interface: Interface to setup -+ * @port: Port to setup (0..3) -+ * @cpu_clock_hz: -+ * Chip frequency in Hertz -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_errata_asx_pass1(int interface, int port, -+ int cpu_clock_hz); -+ -+/** -+ * This function needs to be called on all Octeon chips with -+ * errata PKI-100. -+ * -+ * The Size field is 8 too large in WQE and next pointers -+ * -+ * The Size field generated by IPD is 8 larger than it should -+ * be. The Size field is <55:40> of both: -+ * - WORD3 in the work queue entry, and -+ * - the next buffer pointer (which precedes the packet data -+ * in each buffer). -+ * -+ * @work: Work queue entry to fix -+ * Returns Zero on success. Negative on failure -+ */ -+extern int cvmx_helper_fix_ipd_packet_chain(struct cvmx_wqe *work); -+ -+/** -+ * Due to errata G-720, the 2nd order CDR circuit on CN52XX pass -+ * 1 doesn't work properly. The following code disables 2nd order -+ * CDR for the specified QLM. -+ * -+ * @qlm: QLM to disable 2nd order CDR for. -+ */ -+extern void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm); -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-helper-util.h -@@ -0,0 +1,266 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Small helper utilities. -+ * -+ */ -+ -+#ifndef __CVMX_HELPER_UTIL_H__ -+#define __CVMX_HELPER_UTIL_H__ -+ -+#ifdef CVMX_ENABLE_HELPER_FUNCTIONS -+ -+/** -+ * Convert a interface mode into a human readable string -+ * -+ * @mode: Mode to convert -+ * -+ * Returns String -+ */ -+extern const char -+ *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode); -+ -+/** -+ * Debug routine to dump the packet structure to the console -+ * -+ * @work: Work queue entry containing the packet to dump -+ * Returns -+ */ -+extern int cvmx_helper_dump_packet(cvmx_wqe_t *work); -+ -+/** -+ * Setup Random Early Drop on a specific input queue -+ * -+ * @queue: Input queue to setup RED on (0-7) -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+extern int cvmx_helper_setup_red_queue(int queue, int pass_thresh, -+ int drop_thresh); -+ -+/** -+ * Setup Random Early Drop to automatically begin dropping packets. -+ * -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+extern int cvmx_helper_setup_red(int pass_thresh, int drop_thresh); -+ -+/** -+ * Get the version of the CVMX libraries. -+ * -+ * Returns Version string. Note this buffer is allocated statically -+ * and will be shared by all callers. -+ */ -+extern const char *cvmx_helper_get_version(void); -+ -+/** -+ * @INTERNAL -+ * Setup the common GMX settings that determine the number of -+ * ports. These setting apply to almost all configurations of all -+ * chips. -+ * -+ * @interface: Interface to configure -+ * @num_ports: Number of ports on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_setup_gmx(int interface, int num_ports); -+ -+/** -+ * Returns the IPD/PKO port number for a port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * @port: Port on the interface -+ * -+ * Returns IPD/PKO port number -+ */ -+extern int cvmx_helper_get_ipd_port(int interface, int port); -+ -+/** -+ * Returns the IPD/PKO port number for the first port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * -+ * Returns IPD/PKO port number -+ */ -+static inline int cvmx_helper_get_first_ipd_port(int interface) -+{ -+ return cvmx_helper_get_ipd_port(interface, 0); -+} -+ -+/** -+ * Returns the IPD/PKO port number for the last port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * -+ * Returns IPD/PKO port number -+ */ -+static inline int cvmx_helper_get_last_ipd_port(int interface) -+{ -+ extern int cvmx_helper_ports_on_interface(int interface); -+ -+ return cvmx_helper_get_first_ipd_port(interface) + -+ cvmx_helper_ports_on_interface(interface) - 1; -+} -+ -+/** -+ * Free the packet buffers contained in a work queue entry. -+ * The work queue entry is not freed. -+ * -+ * @work: Work queue entry with packet to free -+ */ -+static inline void cvmx_helper_free_packet_data(cvmx_wqe_t *work) -+{ -+ uint64_t number_buffers; -+ cvmx_buf_ptr_t buffer_ptr; -+ cvmx_buf_ptr_t next_buffer_ptr; -+ uint64_t start_of_buffer; -+ -+ number_buffers = work->word2.s.bufs; -+ if (number_buffers == 0) -+ return; -+ buffer_ptr = work->packet_ptr; -+ -+ /* -+ * Since the number of buffers is not zero, we know this is -+ * not a dynamic short packet. We need to check if it is a -+ * packet received with IPD_CTL_STATUS[NO_WPTR]. If this is -+ * true, we need to free all buffers except for the first -+ * one. The caller doesn't expect their WQE pointer to be -+ * freed. -+ */ -+ start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; -+ if (cvmx_ptr_to_phys(work) == start_of_buffer) { -+ next_buffer_ptr = -+ *(cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); -+ buffer_ptr = next_buffer_ptr; -+ number_buffers--; -+ } -+ -+ while (number_buffers--) { -+ /* -+ * Remember the back pointer is in cache lines, not -+ * 64bit words. -+ */ -+ start_of_buffer = -+ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; -+ /* -+ * Read pointer to next buffer before we free the -+ * current buffer. -+ */ -+ next_buffer_ptr = -+ *(cvmx_buf_ptr_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); -+ cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer), -+ buffer_ptr.s.pool, 0); -+ buffer_ptr = next_buffer_ptr; -+ } -+} -+ -+#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ -+ -+/** -+ * Returns the interface number for an IPD/PKO port number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface number -+ */ -+extern int cvmx_helper_get_interface_num(int ipd_port); -+ -+/** -+ * Returns the interface index number for an IPD/PKO port -+ * number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface index number -+ */ -+extern int cvmx_helper_get_interface_index_num(int ipd_port); -+ -+/** -+ * Initialize the internal QLM JTAG logic to allow programming -+ * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions. -+ * These functions should only be used at the direction of Cavium -+ * Networks. Programming incorrect values into the JTAG chain -+ * can cause chip damage. -+ */ -+extern void cvmx_helper_qlm_jtag_init(void); -+ -+/** -+ * Write up to 32bits into the QLM jtag chain. Bits are shifted -+ * into the MSB and out the LSB, so you should shift in the low -+ * order bits followed by the high order bits. The JTAG chain is -+ * 4 * 268 bits long, or 1072. -+ * -+ * @qlm: QLM to shift value into -+ * @bits: Number of bits to shift in (1-32). -+ * @data: Data to shift in. Bit 0 enters the chain first, followed by -+ * bit 1, etc. -+ * -+ * Returns The low order bits of the JTAG chain that shifted out of the -+ * circle. -+ */ -+extern uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data); -+ -+/** -+ * Shift long sequences of zeros into the QLM JTAG chain. It is -+ * common to need to shift more than 32 bits of zeros into the -+ * chain. This function is a convience wrapper around -+ * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of -+ * zeros at a time. -+ * -+ * @qlm: QLM to shift zeros into -+ * @bits: -+ */ -+extern void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits); -+ -+/** -+ * Program the QLM JTAG chain into all lanes of the QLM. You must -+ * have already shifted in 268*4, or 1072 bits into the JTAG -+ * chain. Updating invalid values can possibly cause chip damage. -+ * -+ * @qlm: QLM to program -+ */ -+extern void cvmx_helper_qlm_jtag_update(int qlm); -+ -+#endif /* __CVMX_HELPER_H__ */ ---- a/arch/mips/include/asm/octeon/cvmx-packet.h -+++ b/arch/mips/include/asm/octeon/cvmx-packet.h -@@ -25,7 +25,8 @@ - * Contact Cavium Networks for more information - ***********************license end**************************************/ - --/* -+/** -+ * - * Packet buffer defines. - */ - -@@ -39,18 +40,23 @@ union cvmx_buf_ptr { - void *ptr; - uint64_t u64; - struct { -- /* if set, invert the "free" pick of the overall -+ /* -+ * If set, invert the "free" pick of the overall - * packet. HW always sets this bit to 0 on inbound -- * packet */ -+ * packet. -+ */ - uint64_t i:1; - -- /* Indicates the amount to back up to get to the -+ /* -+ * Indicates the amount to back up to get to the - * buffer start in cache lines. In most cases this is - * less than one complete cache line, so the value is -- * zero */ -+ * zero. -+ */ - uint64_t back:4; - /* The pool that the buffer came from / goes to */ - uint64_t pool:3; -+ - /* The size of the segment pointed to by addr (in bytes) */ - uint64_t size:16; - /* Pointer to the first byte of the data, NOT buffer */ ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-pcie.h -@@ -0,0 +1,284 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Interface to PCIe as a host(RC) or target(EP) -+ * -+ */ -+ -+#ifndef __CVMX_PCIE_H__ -+#define __CVMX_PCIE_H__ -+ -+union cvmx_pcie_address { -+ uint64_t u64; -+ struct { -+ uint64_t upper:2; /* Normally 2 for XKPHYS */ -+ uint64_t reserved_49_61:13; /* Must be zero */ -+ uint64_t io:1; /* 1 for IO space access */ -+ uint64_t did:5; /* PCIe DID = 3 */ -+ uint64_t subdid:3; /* PCIe SubDID = 1 */ -+ uint64_t reserved_36_39:4; /* Must be zero */ -+ uint64_t es:2; /* Endian swap = 1 */ -+ uint64_t port:2; /* PCIe port 0,1 */ -+ uint64_t reserved_29_31:3; /* Must be zero */ -+ /* -+ * Selects the type of the configuration request (0 = type 0, -+ * 1 = type 1). -+ */ -+ uint64_t ty:1; -+ /* Target bus number sent in the ID in the request. */ -+ uint64_t bus:8; -+ /* -+ * Target device number sent in the ID in the -+ * request. Note that Dev must be zero for type 0 -+ * configuration requests. -+ */ -+ uint64_t dev:5; -+ /* Target function number sent in the ID in the request. */ -+ uint64_t func:3; -+ /* -+ * Selects a register in the configuration space of -+ * the target. -+ */ -+ uint64_t reg:12; -+ } config; -+ struct { -+ uint64_t upper:2; /* Normally 2 for XKPHYS */ -+ uint64_t reserved_49_61:13; /* Must be zero */ -+ uint64_t io:1; /* 1 for IO space access */ -+ uint64_t did:5; /* PCIe DID = 3 */ -+ uint64_t subdid:3; /* PCIe SubDID = 2 */ -+ uint64_t reserved_36_39:4; /* Must be zero */ -+ uint64_t es:2; /* Endian swap = 1 */ -+ uint64_t port:2; /* PCIe port 0,1 */ -+ uint64_t address:32; /* PCIe IO address */ -+ } io; -+ struct { -+ uint64_t upper:2; /* Normally 2 for XKPHYS */ -+ uint64_t reserved_49_61:13; /* Must be zero */ -+ uint64_t io:1; /* 1 for IO space access */ -+ uint64_t did:5; /* PCIe DID = 3 */ -+ uint64_t subdid:3; /* PCIe SubDID = 3-6 */ -+ uint64_t reserved_36_39:4; /* Must be zero */ -+ uint64_t address:36; /* PCIe Mem address */ -+ } mem; -+}; -+ -+/** -+ * Return the Core virtual base address for PCIe IO access. IOs are -+ * read/written as an offset from this address. -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns 64bit Octeon IO base address for read/write -+ */ -+uint64_t cvmx_pcie_get_io_base_address(int pcie_port); -+ -+/** -+ * Size of the IO address region returned at address -+ * cvmx_pcie_get_io_base_address() -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns Size of the IO window -+ */ -+uint64_t cvmx_pcie_get_io_size(int pcie_port); -+ -+/** -+ * Return the Core virtual base address for PCIe MEM access. Memory is -+ * read/written as an offset from this address. -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns 64bit Octeon IO base address for read/write -+ */ -+uint64_t cvmx_pcie_get_mem_base_address(int pcie_port); -+ -+/** -+ * Size of the Mem address region returned at address -+ * cvmx_pcie_get_mem_base_address() -+ * -+ * @pcie_port: PCIe port the IO is for -+ * -+ * Returns Size of the Mem window -+ */ -+uint64_t cvmx_pcie_get_mem_size(int pcie_port); -+ -+/** -+ * Initialize a PCIe port for use in host(RC) mode. It doesn't -+ * enumerate the bus. -+ * -+ * @pcie_port: PCIe port to initialize -+ * -+ * Returns Zero on success -+ */ -+int cvmx_pcie_rc_initialize(int pcie_port); -+ -+/** -+ * Shutdown a PCIe port and put it in reset -+ * -+ * @pcie_port: PCIe port to shutdown -+ * -+ * Returns Zero on success -+ */ -+int cvmx_pcie_rc_shutdown(int pcie_port); -+ -+/** -+ * Read 8bits from a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns Result of the read -+ */ -+uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, int fn, -+ int reg); -+ -+/** -+ * Read 16bits from a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns Result of the read -+ */ -+uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, -+ int reg); -+ -+/** -+ * Read 32bits from a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * -+ * Returns Result of the read -+ */ -+uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, -+ int reg); -+ -+/** -+ * Write 8bits to a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * @val: Value to write -+ */ -+void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, int reg, -+ uint8_t val); -+ -+/** -+ * Write 16bits to a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * @val: Value to write -+ */ -+void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, int reg, -+ uint16_t val); -+ -+/** -+ * Write 32bits to a Device's config space -+ * -+ * @pcie_port: PCIe port the device is on -+ * @bus: Sub bus -+ * @dev: Device ID -+ * @fn: Device sub function -+ * @reg: Register to access -+ * @val: Value to write -+ */ -+void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, int reg, -+ uint32_t val); -+ -+/** -+ * Read a PCIe config space register indirectly. This is used for -+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. -+ * -+ * @pcie_port: PCIe port to read from -+ * @cfg_offset: Address to read -+ * -+ * Returns Value read -+ */ -+uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset); -+ -+/** -+ * Write a PCIe config space register indirectly. This is used for -+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. -+ * -+ * @pcie_port: PCIe port to write to -+ * @cfg_offset: Address to write -+ * @val: Value to write -+ */ -+void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val); -+ -+/** -+ * Write a 32bit value to the Octeon NPEI register space -+ * -+ * @address: Address to write to -+ * @val: Value to write -+ */ -+static inline void cvmx_pcie_npei_write32(uint64_t address, uint32_t val) -+{ -+ cvmx_write64_uint32(address ^ 4, val); -+ cvmx_read64_uint32(address ^ 4); -+} -+ -+/** -+ * Read a 32bit value from the Octeon NPEI register space -+ * -+ * @address: Address to read -+ * Returns The result -+ */ -+static inline uint32_t cvmx_pcie_npei_read32(uint64_t address) -+{ -+ return cvmx_read64_uint32(address ^ 4); -+} -+ -+/** -+ * Initialize a PCIe port for use in target(EP) mode. -+ * -+ * Returns Zero on success -+ */ -+int cvmx_pcie_ep_initialize(void); -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-wqe.h -@@ -0,0 +1,422 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * This header file defines the work queue entry (wqe) data structure. -+ * Since this is a commonly used structure that depends on structures -+ * from several hardware blocks, those definitions have been placed -+ * in this file to create a single point of definition of the wqe -+ * format. -+ * -+ * Data structures are still named according to the block that they -+ * relate to. -+ * -+ */ -+ -+#ifndef __CVMX_WQE_H__ -+#define __CVMX_WQE_H__ -+ -+#include "cvmx-packet.h" -+ -+#define OCT_TAG_TYPE_STRING(x) ( \ -+ { \ -+ const char *r; \ -+ switch (x) { \ -+ case CVMX_POW_TAG_TYPE_ORDERED: \ -+ r = "ORDERED"; \ -+ break; \ -+ case CVMX_POW_TAG_TYPE_ATOMIC: \ -+ r = "ATOMIC"; \ -+ break; \ -+ case CVMX_POW_TAG_TYPE_NULL: \ -+ r = "NULL"; \ -+ break; \ -+ default: \ -+ r = "NULL_NULL"; \ -+ break; \ -+ } \ -+ r; \ -+ }) -+ -+/** -+ * HW decode / err_code in work queue entry -+ */ -+union cvmx_pip_wqe_word2{ -+ uint64_t u64; -+ -+ /* Use this struct if the hardware determines that the packet is IP */ -+ struct { -+ /* HW sets this to the number of buffers used by this packet */ -+ uint64_t bufs:8; -+ /* HW sets to the number of L2 bytes prior to the IP */ -+ uint64_t ip_offset:8; -+ /* Set to 1 if we found VLAN in the L2 */ -+ uint64_t vlan_valid:1; -+ uint64_t unassigned:2; -+ /* HW sets to the VLAN CFI flag (valid when vlan_valid) */ -+ uint64_t vlan_cfi:1; -+ /* HW sets to the VLAN_ID field (valid when vlan_valid) */ -+ uint64_t vlan_id:12; -+ -+ uint64_t unassigned2:12; -+ /* The packet needs to be decompressed */ -+ uint64_t dec_ipcomp:1; -+ /* The packet is either TCP or UDP */ -+ uint64_t tcp_or_udp:1; -+ /* The packet needs to be decrypted (ESP or AH) */ -+ uint64_t dec_ipsec:1; -+ /* The packet is IPv6 */ -+ uint64_t is_v6:1; -+ -+ /* -+ * rcv_error, not_IP, IP_exc, is_frag, L4_error, -+ * software, etc. -+ */ -+ -+ /* -+ * Reserved for software use, hardware will clear on -+ * packet creation. -+ */ -+ uint64_t software:1; -+ /* exceptional conditions below. */ -+ -+ /* -+ * The receive interface hardware detected an L4 error -+ * (only applies if !is_frag) (only applies if -+ * !rcv_error && !not_IP && !IP_exc && !is_frag) -+ * failure indicated in err_code below, decode: -+ * -+ * - 1 = Malformed L4 -+ * -+ * - 2 = L4 Checksum Error: the L4 checksum value is -+ * -+ * - 3 = UDP Length Error: The UDP length field would -+ * make the UDP data longer than what remains in -+ * the IP packet (as defined by the IP header -+ * length field). -+ * -+ * - 4 = Bad L4 Port: either the source or destination -+ * TCP/UDP port is 0. -+ * -+ * - 8 = TCP FIN Only: the packet is TCP and only the -+ * FIN flag set. -+ * -+ * - 9 = TCP No Flags: the packet is TCP and no flags -+ * are set. -+ * -+ * - 10 = TCP FIN RST: the packet is TCP and both FIN -+ * and RST are set. -+ * -+ * - 11 = TCP SYN URG: the packet is TCP and both SYN -+ * and URG are set. -+ * -+ * - 12 = TCP SYN RST: the packet is TCP and both SYN -+ * and RST are set. -+ * -+ * - 13 = TCP SYN FIN: the packet is TCP and both SYN -+ * and FIN are set. -+ * -+ */ -+ uint64_t L4_error:1; -+ /* Set if the packet is a fragment */ -+ uint64_t is_frag:1; -+ -+ /* -+ * The receive interface hardware detected an IP error -+ * / exception (only applies if !rcv_error && !not_IP) -+ * failure indicated in err_code below, decode: -+ * -+ * - 1 = Not IP: the IP version field is neither 4 nor -+ * 6. -+ * -+ * - 2 = IPv4 Header Checksum Error: the IPv4 header -+ * has a checksum violation. -+ * -+ * - 3 = IP Malformed Header: the packet is not long -+ * enough to contain the IP header. -+ * -+ * - 4 = IP Malformed: the packet is not long enough -+ * to contain the bytes indicated by the IP -+ * header. Pad is allowed. -+ * -+ * - 5 = IP TTL Hop: the IPv4 TTL field or the IPv6 -+ * Hop Count field are zero. -+ * -+ * - 6 = IP Options. -+ */ -+ uint64_t IP_exc:1; -+ /* -+ * Set if the hardware determined that the packet is a -+ * broadcast. -+ */ -+ uint64_t is_bcast:1; -+ /* -+ * Set if the hardware determined that the packet is a -+ * multi-cast. -+ */ -+ uint64_t is_mcast:1; -+ /* -+ * Set if the packet may not be IP (must be zero in -+ * this case). -+ */ -+ uint64_t not_IP:1; -+ /* -+ * The receive interface hardware detected a receive -+ * error (must be zero in this case) -+ * -+ * lower err_code = first-level descriptor of the work -+ * -+ * zero for packet submitted by hardware that isn't on -+ * the slow path. -+ */ -+ uint64_t rcv_error:1; -+ -+ /* Type is cvmx_pip_err_t */ -+ uint64_t err_code:8; -+ } s; -+ -+ /* Use this to get at the 16 vlan bits */ -+ struct { -+ uint64_t unused1:16; -+ uint64_t vlan:16; -+ uint64_t unused2:32; -+ } svlan; -+ -+ /* -+ * Use this struct if the hardware could not determine that -+ * the packet is ip. -+ */ -+ struct { -+ /* HW sets this to the number of buffers used by this packet. */ -+ uint64_t bufs:8; -+ uint64_t unused:8; -+ /* Set to 1 if we found VLAN in the L2. */ -+ uint64_t vlan_valid:1; -+ uint64_t unassigned:2; -+ /* HW sets to the VLAN CFI flag (valid when vlan_valid). */ -+ uint64_t vlan_cfi:1; -+ /* HW sets to the VLAN_ID field (valid when vlan_valid). */ -+ uint64_t vlan_id:12; -+ -+ uint64_t unassigned2:16; -+ /* -+ * Reserved for software use, hardware will clear on -+ * packet creation. -+ */ -+ uint64_t software:1; -+ uint64_t unassigned3:1; -+ /* Set if the hardware determined that the packet is rarp. */ -+ uint64_t is_rarp:1; -+ /* Set if the hardware determined that the packet is arp. */ -+ uint64_t is_arp:1; -+ /* -+ * Set if the hardware determined that the packet is a -+ * broadcast. -+ */ -+ uint64_t is_bcast:1; -+ /* -+ * Set if the hardware determined that the packet is a -+ * multi-cast. -+ */ -+ uint64_t is_mcast:1; -+ /* -+ * Set if the packet may not be IP (must be one in -+ * this case). -+ */ -+ uint64_t not_IP:1; -+ /* -+ * The receive interface hardware detected a receive -+ * error. Failure indicated in err_code below, decode: -+ * -+ * - 1 = partial error: a packet was partially -+ * received, but internal buffering / bandwidth -+ * was not adequate to receive the entire -+ * packet. -+ * -+ * - 2 = jabber error: the RGMII packet was too large -+ * and is truncated. -+ * -+ * - 3 = overrun error: the RGMII packet is longer -+ * than allowed and had an FCS error. -+ * -+ * - 4 = oversize error: the RGMII packet is longer -+ * than allowed. -+ * -+ * - 5 = alignment error: the RGMII packet is not an -+ * integer number of bytes and had an FCS error -+ * (100M and 10M only). -+ * -+ * - 6 = fragment error: the RGMII packet is shorter -+ * than allowed and had an FCS error. -+ * -+ * - 7 = GMX FCS error: the RGMII packet had an FCS -+ * error. -+ * -+ * - 8 = undersize error: the RGMII packet is shorter -+ * than allowed. -+ * -+ * - 9 = extend error: the RGMII packet had an extend -+ * error. -+ * -+ * - 10 = length mismatch error: the RGMII packet had -+ * a length that did not match the length field -+ * in the L2 HDR. -+ * -+ * - 11 = RGMII RX error/SPI4 DIP4 Error: the RGMII -+ * packet had one or more data reception errors -+ * (RXERR) or the SPI4 packet had one or more -+ * DIP4 errors. -+ * -+ * - 12 = RGMII skip error/SPI4 Abort Error: the RGMII -+ * packet was not large enough to cover the -+ * skipped bytes or the SPI4 packet was -+ * terminated with an About EOPS. -+ * -+ * - 13 = RGMII nibble error/SPI4 Port NXA Error: the -+ * RGMII packet had a studder error (data not -+ * repeated - 10/100M only) or the SPI4 packet -+ * was sent to an NXA. -+ * -+ * - 16 = FCS error: a SPI4.2 packet had an FCS error. -+ * -+ * - 17 = Skip error: a packet was not large enough to -+ * cover the skipped bytes. -+ * -+ * - 18 = L2 header malformed: the packet is not long -+ * enough to contain the L2 -+ */ -+ -+ /* -+ * lower err_code = first-level descriptor of the -+ * work. -+ * -+ * zero for packet submitted by hardware that isn't on -+ * the slow path. -+ */ -+ uint64_t rcv_error:1; -+ -+ /* Type is cvmx_pip_err_t (union, so can't use directly. */ -+ uint64_t err_code:8; -+ } snoip; -+ -+}; -+ -+/** -+ * Work queue entry format -+ * -+ * must be 8-byte aligned -+ */ -+struct cvmx_wqe { -+ -+ /***************************************************************** -+ * WORD 0 -+ * HW WRITE: the following 64 bits are filled by HW when a packet arrives -+ */ -+ -+ /** -+ * raw chksum result generated by the HW -+ */ -+ uint16_t hw_chksum; -+ /** -+ * Field unused by hardware - available for software -+ */ -+ uint8_t unused; -+ /** -+ * Next pointer used by hardware for list maintenance. -+ * May be written/read by HW before the work queue -+ * entry is scheduled to a PP -+ * (Only 36 bits used in Octeon 1) -+ */ -+ uint64_t next_ptr:40; -+ -+ /***************************************************************** -+ * WORD 1 -+ * HW WRITE: the following 64 bits are filled by HW when a packet arrives -+ */ -+ -+ /** -+ * HW sets to the total number of bytes in the packet -+ */ -+ uint64_t len:16; -+ /** -+ * HW sets this to input physical port -+ */ -+ uint64_t ipprt:6; -+ -+ /** -+ * HW sets this to what it thought the priority of the input packet was -+ */ -+ uint64_t qos:3; -+ -+ /** -+ * the group that the work queue entry will be scheduled to -+ */ -+ uint64_t grp:4; -+ /** -+ * the type of the tag (ORDERED, ATOMIC, NULL) -+ */ -+ uint64_t tag_type:3; -+ /** -+ * the synchronization/ordering tag -+ */ -+ uint64_t tag:32; -+ -+ /** -+ * WORD 2 HW WRITE: the following 64-bits are filled in by -+ * hardware when a packet arrives This indicates a variety of -+ * status and error conditions. -+ */ -+ union cvmx_pip_wqe_word2 word2; -+ -+ /** -+ * Pointer to the first segment of the packet. -+ */ -+ union cvmx_buf_ptr packet_ptr; -+ -+ /** -+ * HW WRITE: octeon will fill in a programmable amount from the -+ * packet, up to (at most, but perhaps less) the amount -+ * needed to fill the work queue entry to 128 bytes -+ * If the packet is recognized to be IP, the hardware starts (except that -+ * the IPv4 header is padded for appropriate alignment) writing here where -+ * the IP header starts. -+ * If the packet is not recognized to be IP, the hardware starts writing -+ * the beginning of the packet here. -+ */ -+ uint8_t packet_data[96]; -+ -+ /** -+ * If desired, SW can make the work Q entry any length. For the -+ * purposes of discussion here, Assume 128B always, as this is all that -+ * the hardware deals with. -+ * -+ */ -+ -+} CVMX_CACHE_LINE_ALIGNED; -+ -+#endif /* __CVMX_WQE_H__ */ ---- a/arch/mips/include/asm/octeon/cvmx.h -+++ b/arch/mips/include/asm/octeon/cvmx.h -@@ -376,6 +376,18 @@ static inline uint64_t cvmx_get_cycle(vo - } - - /** -+ * Wait for the specified number of cycle -+ * -+ */ -+static inline void cvmx_wait(uint64_t cycles) -+{ -+ uint64_t done = cvmx_get_cycle() + cycles; -+ -+ while (cvmx_get_cycle() < done) -+ ; /* Spin */ -+} -+ -+/** - * Reads a chip global cycle counter. This counts CPU cycles since - * chip reset. The counter is 64 bit. - * This register does not exist on CN38XX pass 1 silicion ---- a/arch/mips/include/asm/octeon/octeon.h -+++ b/arch/mips/include/asm/octeon/octeon.h -@@ -245,4 +245,6 @@ static inline uint32_t octeon_npi_read32 - return cvmx_read64_uint32(address ^ 4); - } - -+extern struct cvmx_bootinfo *octeon_bootinfo; -+ - #endif /* __ASM_OCTEON_OCTEON_H */ diff --git a/target/linux/octeon/patches/004-named_alloc_function.patch b/target/linux/octeon/patches/004-named_alloc_function.patch deleted file mode 100644 index a3135f0a8a..0000000000 --- a/target/linux/octeon/patches/004-named_alloc_function.patch +++ /dev/null @@ -1,223 +0,0 @@ -The MGMT ethernet driver uses these new functions. - -Signed-off-by: David Daney ---- - arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 101 ++++++++++++++++++++++ - arch/mips/include/asm/octeon/cvmx-bootmem.h | 85 ++++++++++++++++++ - 2 files changed, 186 insertions(+), 0 deletions(-) - ---- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c -+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c -@@ -97,6 +97,32 @@ void *cvmx_bootmem_alloc(uint64_t size, - return cvmx_bootmem_alloc_range(size, alignment, 0, 0); - } - -+void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, -+ uint64_t max_addr, uint64_t align, -+ char *name) -+{ -+ int64_t addr; -+ -+ addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, -+ align, name, 0); -+ if (addr >= 0) -+ return cvmx_phys_to_ptr(addr); -+ else -+ return NULL; -+} -+ -+void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, -+ char *name) -+{ -+ return cvmx_bootmem_alloc_named_range(size, address, address + size, -+ 0, name); -+} -+ -+void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name) -+{ -+ return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name); -+} -+ - int cvmx_bootmem_free_named(char *name) - { - return cvmx_bootmem_phy_named_block_free(name, 0); -@@ -584,3 +610,78 @@ int cvmx_bootmem_phy_named_block_free(ch - cvmx_bootmem_unlock(); - return named_block_ptr != NULL; /* 0 on failure, 1 on success */ - } -+ -+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, -+ uint64_t max_addr, -+ uint64_t alignment, -+ char *name, -+ uint32_t flags) -+{ -+ int64_t addr_allocated; -+ struct cvmx_bootmem_named_block_desc *named_block_desc_ptr; -+ -+#ifdef DEBUG -+ cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: " -+ "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n", -+ (unsigned long long)size, -+ (unsigned long long)min_addr, -+ (unsigned long long)max_addr, -+ (unsigned long long)alignment, -+ name); -+#endif -+ if (cvmx_bootmem_desc->major_version != 3) { -+ cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: " -+ "%d.%d at addr: %p\n", -+ (int)cvmx_bootmem_desc->major_version, -+ (int)cvmx_bootmem_desc->minor_version, -+ cvmx_bootmem_desc); -+ return -1; -+ } -+ -+ /* -+ * Take lock here, as name lookup/block alloc/name add need to -+ * be atomic. -+ */ -+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) -+ cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); -+ -+ /* Get pointer to first available named block descriptor */ -+ named_block_desc_ptr = -+ cvmx_bootmem_phy_named_block_find(NULL, -+ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING); -+ -+ /* -+ * Check to see if name already in use, return error if name -+ * not available or no more room for blocks. -+ */ -+ if (cvmx_bootmem_phy_named_block_find(name, -+ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) { -+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) -+ cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); -+ return -1; -+ } -+ -+ -+ /* -+ * Round size up to mult of minimum alignment bytes We need -+ * the actual size allocated to allow for blocks to be -+ * coallesced when they are freed. The alloc routine does the -+ * same rounding up on all allocations. -+ */ -+ size = __ALIGN_MASK(size, (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)); -+ -+ addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr, -+ alignment, -+ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING); -+ if (addr_allocated >= 0) { -+ named_block_desc_ptr->base_addr = addr_allocated; -+ named_block_desc_ptr->size = size; -+ strncpy(named_block_desc_ptr->name, name, -+ cvmx_bootmem_desc->named_block_name_len); -+ named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0; -+ } -+ -+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) -+ cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); -+ return addr_allocated; -+} ---- a/arch/mips/include/asm/octeon/cvmx-bootmem.h -+++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h -@@ -183,6 +183,64 @@ extern void *cvmx_bootmem_alloc_range(ui - * Returns 0 on failure, - * !0 on success - */ -+ -+ -+/** -+ * Allocate a block of memory from the free list that was passed -+ * to the application by the bootloader, and assign it a name in the -+ * global named block table. (part of the cvmx_bootmem_descriptor_t structure) -+ * Named blocks can later be freed. -+ * -+ * @size: Size in bytes of block to allocate -+ * @alignment: Alignment required - must be power of 2 -+ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes -+ * -+ * Returns a pointer to block of memory, NULL on error -+ */ -+extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, -+ char *name); -+ -+ -+ -+/** -+ * Allocate a block of memory from the free list that was passed -+ * to the application by the bootloader, and assign it a name in the -+ * global named block table. (part of the cvmx_bootmem_descriptor_t structure) -+ * Named blocks can later be freed. -+ * -+ * @size: Size in bytes of block to allocate -+ * @address: Physical address to allocate memory at. If this -+ * memory is not available, the allocation fails. -+ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN -+ * bytes -+ * -+ * Returns a pointer to block of memory, NULL on error -+ */ -+extern void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, -+ char *name); -+ -+ -+ -+/** -+ * Allocate a block of memory from a specific range of the free list -+ * that was passed to the application by the bootloader, and assign it -+ * a name in the global named block table. (part of the -+ * cvmx_bootmem_descriptor_t structure) Named blocks can later be -+ * freed. If request cannot be satisfied within the address range -+ * specified, NULL is returned -+ * -+ * @size: Size in bytes of block to allocate -+ * @min_addr: minimum address of range -+ * @max_addr: maximum address of range -+ * @align: Alignment of memory to be allocated. (must be a power of 2) -+ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes -+ * -+ * Returns a pointer to block of memory, NULL on error -+ */ -+extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, -+ uint64_t max_addr, uint64_t align, -+ char *name); -+ - extern int cvmx_bootmem_free_named(char *name); - - /** -@@ -224,6 +282,33 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t - uint32_t flags); - - /** -+ * Allocates a named block of physical memory from the free list, at -+ * (optional) requested address and alignment. -+ * -+ * @param size size of region to allocate. All requests are rounded -+ * up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE -+ * bytes size -+ * @param min_addr Minimum address that block can occupy. -+ * @param max_addr Specifies the maximum address_min (inclusive) that -+ * the allocation can use. -+ * @param alignment Requested alignment of the block. If this -+ * alignment cannot be met, the allocation fails. -+ * This must be a power of 2. (Note: Alignment of -+ * CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and -+ * internally enforced. Requested alignments of less -+ * than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to -+ * CVMX_BOOTMEM_ALIGNMENT_SIZE.) -+ * @param name name to assign to named block -+ * @param flags Flags to control options for the allocation. -+ * -+ * @return physical address of block allocated, or -1 on failure -+ */ -+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, -+ uint64_t max_addr, -+ uint64_t alignment, -+ char *name, uint32_t flags); -+ -+/** - * Finds a named memory block by name. - * Also used for finding an unused entry in the named block table. - * diff --git a/target/linux/octeon/patches/005-register_defs_octeon_mgmt.patch b/target/linux/octeon/patches/005-register_defs_octeon_mgmt.patch deleted file mode 100644 index 5169f6cf65..0000000000 --- a/target/linux/octeon/patches/005-register_defs_octeon_mgmt.patch +++ /dev/null @@ -1,1642 +0,0 @@ -The MGMT ethernet driver uses the AGL, MIXX and SMIX blocks, so we add -definitions for them. - -Signed-off-by: David Daney ---- - arch/mips/include/asm/octeon/cvmx-agl-defs.h | 1194 +++++++++++++++++++++++++ - arch/mips/include/asm/octeon/cvmx-mixx-defs.h | 248 +++++ - arch/mips/include/asm/octeon/cvmx-smix-defs.h | 178 ++++ - 3 files changed, 1620 insertions(+), 0 deletions(-) - create mode 100644 arch/mips/include/asm/octeon/cvmx-agl-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-mixx-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-smix-defs.h - ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-agl-defs.h -@@ -0,0 +1,1194 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_AGL_DEFS_H__ -+#define __CVMX_AGL_DEFS_H__ -+ -+#define CVMX_AGL_GMX_BAD_REG \ -+ CVMX_ADD_IO_SEG(0x00011800E0000518ull) -+#define CVMX_AGL_GMX_BIST \ -+ CVMX_ADD_IO_SEG(0x00011800E0000400ull) -+#define CVMX_AGL_GMX_DRV_CTL \ -+ CVMX_ADD_IO_SEG(0x00011800E00007F0ull) -+#define CVMX_AGL_GMX_INF_MODE \ -+ CVMX_ADD_IO_SEG(0x00011800E00007F8ull) -+#define CVMX_AGL_GMX_PRTX_CFG(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000010ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM0(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000180ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM1(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000188ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM2(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000190ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM3(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000198ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM4(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00001A0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM5(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00001A8ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CAM_EN(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000108ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_ADR_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000100ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_DECISION(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000040ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_FRM_CHK(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000020ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_FRM_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000018ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_FRM_MAX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000030ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_FRM_MIN(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000028ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_IFG(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000058ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_INT_EN(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000008ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_INT_REG(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000000ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_JABBER(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000038ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_PAUSE_DROP_TIME(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000068ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000050ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_OCTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000088ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_OCTS_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000098ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_OCTS_DMAC(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00000A8ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_OCTS_DRP(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00000B8ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_PKTS(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000080ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00000C0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_PKTS_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000090ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_PKTS_DMAC(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00000A0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00000B0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RXX_UDD_SKP(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000048ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_RX_BP_DROPX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000420ull + (((offset) & 1) * 8)) -+#define CVMX_AGL_GMX_RX_BP_OFFX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000460ull + (((offset) & 1) * 8)) -+#define CVMX_AGL_GMX_RX_BP_ONX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000440ull + (((offset) & 1) * 8)) -+#define CVMX_AGL_GMX_RX_PRT_INFO \ -+ CVMX_ADD_IO_SEG(0x00011800E00004E8ull) -+#define CVMX_AGL_GMX_RX_TX_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011800E00007E8ull) -+#define CVMX_AGL_GMX_SMACX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000230ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_STAT_BP \ -+ CVMX_ADD_IO_SEG(0x00011800E0000520ull) -+#define CVMX_AGL_GMX_TXX_APPEND(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000218ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000270ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_MIN_PKT(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000240ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_PAUSE_PKT_INTERVAL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000248ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_PAUSE_PKT_TIME(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000238ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_PAUSE_TOGO(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000258ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_PAUSE_ZERO(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000260ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_SOFT_PAUSE(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000250ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT0(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000280ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT1(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000288ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT2(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000290ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT3(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000298ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT4(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00002A0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT5(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00002A8ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT6(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00002B0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT7(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00002B8ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT8(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00002C0ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STAT9(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E00002C8ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_STATS_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000268ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TXX_THRESH(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800E0000210ull + (((offset) & 1) * 2048)) -+#define CVMX_AGL_GMX_TX_BP \ -+ CVMX_ADD_IO_SEG(0x00011800E00004D0ull) -+#define CVMX_AGL_GMX_TX_COL_ATTEMPT \ -+ CVMX_ADD_IO_SEG(0x00011800E0000498ull) -+#define CVMX_AGL_GMX_TX_IFG \ -+ CVMX_ADD_IO_SEG(0x00011800E0000488ull) -+#define CVMX_AGL_GMX_TX_INT_EN \ -+ CVMX_ADD_IO_SEG(0x00011800E0000508ull) -+#define CVMX_AGL_GMX_TX_INT_REG \ -+ CVMX_ADD_IO_SEG(0x00011800E0000500ull) -+#define CVMX_AGL_GMX_TX_JAM \ -+ CVMX_ADD_IO_SEG(0x00011800E0000490ull) -+#define CVMX_AGL_GMX_TX_LFSR \ -+ CVMX_ADD_IO_SEG(0x00011800E00004F8ull) -+#define CVMX_AGL_GMX_TX_OVR_BP \ -+ CVMX_ADD_IO_SEG(0x00011800E00004C8ull) -+#define CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC \ -+ CVMX_ADD_IO_SEG(0x00011800E00004A0ull) -+#define CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE \ -+ CVMX_ADD_IO_SEG(0x00011800E00004A8ull) -+ -+union cvmx_agl_gmx_bad_reg { -+ uint64_t u64; -+ struct cvmx_agl_gmx_bad_reg_s { -+ uint64_t reserved_38_63:26; -+ uint64_t txpsh1:1; -+ uint64_t txpop1:1; -+ uint64_t ovrflw1:1; -+ uint64_t txpsh:1; -+ uint64_t txpop:1; -+ uint64_t ovrflw:1; -+ uint64_t reserved_27_31:5; -+ uint64_t statovr:1; -+ uint64_t reserved_23_25:3; -+ uint64_t loststat:1; -+ uint64_t reserved_4_21:18; -+ uint64_t out_ovr:2; -+ uint64_t reserved_0_1:2; -+ } s; -+ struct cvmx_agl_gmx_bad_reg_s cn52xx; -+ struct cvmx_agl_gmx_bad_reg_s cn52xxp1; -+ struct cvmx_agl_gmx_bad_reg_cn56xx { -+ uint64_t reserved_35_63:29; -+ uint64_t txpsh:1; -+ uint64_t txpop:1; -+ uint64_t ovrflw:1; -+ uint64_t reserved_27_31:5; -+ uint64_t statovr:1; -+ uint64_t reserved_23_25:3; -+ uint64_t loststat:1; -+ uint64_t reserved_3_21:19; -+ uint64_t out_ovr:1; -+ uint64_t reserved_0_1:2; -+ } cn56xx; -+ struct cvmx_agl_gmx_bad_reg_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_bist { -+ uint64_t u64; -+ struct cvmx_agl_gmx_bist_s { -+ uint64_t reserved_10_63:54; -+ uint64_t status:10; -+ } s; -+ struct cvmx_agl_gmx_bist_s cn52xx; -+ struct cvmx_agl_gmx_bist_s cn52xxp1; -+ struct cvmx_agl_gmx_bist_s cn56xx; -+ struct cvmx_agl_gmx_bist_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_drv_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_drv_ctl_s { -+ uint64_t reserved_49_63:15; -+ uint64_t byp_en1:1; -+ uint64_t reserved_45_47:3; -+ uint64_t pctl1:5; -+ uint64_t reserved_37_39:3; -+ uint64_t nctl1:5; -+ uint64_t reserved_17_31:15; -+ uint64_t byp_en:1; -+ uint64_t reserved_13_15:3; -+ uint64_t pctl:5; -+ uint64_t reserved_5_7:3; -+ uint64_t nctl:5; -+ } s; -+ struct cvmx_agl_gmx_drv_ctl_s cn52xx; -+ struct cvmx_agl_gmx_drv_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_drv_ctl_cn56xx { -+ uint64_t reserved_17_63:47; -+ uint64_t byp_en:1; -+ uint64_t reserved_13_15:3; -+ uint64_t pctl:5; -+ uint64_t reserved_5_7:3; -+ uint64_t nctl:5; -+ } cn56xx; -+ struct cvmx_agl_gmx_drv_ctl_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_inf_mode { -+ uint64_t u64; -+ struct cvmx_agl_gmx_inf_mode_s { -+ uint64_t reserved_2_63:62; -+ uint64_t en:1; -+ uint64_t reserved_0_0:1; -+ } s; -+ struct cvmx_agl_gmx_inf_mode_s cn52xx; -+ struct cvmx_agl_gmx_inf_mode_s cn52xxp1; -+ struct cvmx_agl_gmx_inf_mode_s cn56xx; -+ struct cvmx_agl_gmx_inf_mode_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_prtx_cfg { -+ uint64_t u64; -+ struct cvmx_agl_gmx_prtx_cfg_s { -+ uint64_t reserved_6_63:58; -+ uint64_t tx_en:1; -+ uint64_t rx_en:1; -+ uint64_t slottime:1; -+ uint64_t duplex:1; -+ uint64_t speed:1; -+ uint64_t en:1; -+ } s; -+ struct cvmx_agl_gmx_prtx_cfg_s cn52xx; -+ struct cvmx_agl_gmx_prtx_cfg_s cn52xxp1; -+ struct cvmx_agl_gmx_prtx_cfg_s cn56xx; -+ struct cvmx_agl_gmx_prtx_cfg_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam0 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam0_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam1 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam1_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam2 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam2_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam3 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam3_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam4 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam4_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam5 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam5_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_cam_en { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_cam_en_s { -+ uint64_t reserved_8_63:56; -+ uint64_t en:8; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_adr_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_adr_ctl_s { -+ uint64_t reserved_4_63:60; -+ uint64_t cam_mode:1; -+ uint64_t mcst:2; -+ uint64_t bcst:1; -+ } s; -+ struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xx; -+ struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xx; -+ struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_decision { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_decision_s { -+ uint64_t reserved_5_63:59; -+ uint64_t cnt:5; -+ } s; -+ struct cvmx_agl_gmx_rxx_decision_s cn52xx; -+ struct cvmx_agl_gmx_rxx_decision_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_decision_s cn56xx; -+ struct cvmx_agl_gmx_rxx_decision_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_frm_chk { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_frm_chk_s { -+ uint64_t reserved_9_63:55; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t reserved_1_1:1; -+ uint64_t minerr:1; -+ } s; -+ struct cvmx_agl_gmx_rxx_frm_chk_s cn52xx; -+ struct cvmx_agl_gmx_rxx_frm_chk_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_frm_chk_s cn56xx; -+ struct cvmx_agl_gmx_rxx_frm_chk_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_frm_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_frm_ctl_s { -+ uint64_t reserved_10_63:54; -+ uint64_t pre_align:1; -+ uint64_t pad_len:1; -+ uint64_t vlan_len:1; -+ uint64_t pre_free:1; -+ uint64_t ctl_smac:1; -+ uint64_t ctl_mcst:1; -+ uint64_t ctl_bck:1; -+ uint64_t ctl_drp:1; -+ uint64_t pre_strp:1; -+ uint64_t pre_chk:1; -+ } s; -+ struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xx; -+ struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xx; -+ struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_frm_max { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_frm_max_s { -+ uint64_t reserved_16_63:48; -+ uint64_t len:16; -+ } s; -+ struct cvmx_agl_gmx_rxx_frm_max_s cn52xx; -+ struct cvmx_agl_gmx_rxx_frm_max_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_frm_max_s cn56xx; -+ struct cvmx_agl_gmx_rxx_frm_max_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_frm_min { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_frm_min_s { -+ uint64_t reserved_16_63:48; -+ uint64_t len:16; -+ } s; -+ struct cvmx_agl_gmx_rxx_frm_min_s cn52xx; -+ struct cvmx_agl_gmx_rxx_frm_min_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_frm_min_s cn56xx; -+ struct cvmx_agl_gmx_rxx_frm_min_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_ifg { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_ifg_s { -+ uint64_t reserved_4_63:60; -+ uint64_t ifg:4; -+ } s; -+ struct cvmx_agl_gmx_rxx_ifg_s cn52xx; -+ struct cvmx_agl_gmx_rxx_ifg_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_ifg_s cn56xx; -+ struct cvmx_agl_gmx_rxx_ifg_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_int_en { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_int_en_s { -+ uint64_t reserved_20_63:44; -+ uint64_t pause_drp:1; -+ uint64_t reserved_16_18:3; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t reserved_9_9:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t reserved_1_1:1; -+ uint64_t minerr:1; -+ } s; -+ struct cvmx_agl_gmx_rxx_int_en_s cn52xx; -+ struct cvmx_agl_gmx_rxx_int_en_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_int_en_s cn56xx; -+ struct cvmx_agl_gmx_rxx_int_en_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_int_reg { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_int_reg_s { -+ uint64_t reserved_20_63:44; -+ uint64_t pause_drp:1; -+ uint64_t reserved_16_18:3; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t reserved_9_9:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t reserved_1_1:1; -+ uint64_t minerr:1; -+ } s; -+ struct cvmx_agl_gmx_rxx_int_reg_s cn52xx; -+ struct cvmx_agl_gmx_rxx_int_reg_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_int_reg_s cn56xx; -+ struct cvmx_agl_gmx_rxx_int_reg_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_jabber { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_jabber_s { -+ uint64_t reserved_16_63:48; -+ uint64_t cnt:16; -+ } s; -+ struct cvmx_agl_gmx_rxx_jabber_s cn52xx; -+ struct cvmx_agl_gmx_rxx_jabber_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_jabber_s cn56xx; -+ struct cvmx_agl_gmx_rxx_jabber_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_pause_drop_time { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_pause_drop_time_s { -+ uint64_t reserved_16_63:48; -+ uint64_t status:16; -+ } s; -+ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xx; -+ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xx; -+ struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_ctl_s { -+ uint64_t reserved_1_63:63; -+ uint64_t rd_clr:1; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_octs { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_octs_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_octs_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_octs_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_octs_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_octs_dmac { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_octs_drp { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_octs_drp_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_pkts { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_pkts_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_pkts_bad { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_pkts_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_pkts_dmac { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_stats_pkts_drp { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xx; -+ struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rxx_udd_skp { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rxx_udd_skp_s { -+ uint64_t reserved_9_63:55; -+ uint64_t fcssel:1; -+ uint64_t reserved_7_7:1; -+ uint64_t len:7; -+ } s; -+ struct cvmx_agl_gmx_rxx_udd_skp_s cn52xx; -+ struct cvmx_agl_gmx_rxx_udd_skp_s cn52xxp1; -+ struct cvmx_agl_gmx_rxx_udd_skp_s cn56xx; -+ struct cvmx_agl_gmx_rxx_udd_skp_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rx_bp_dropx { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rx_bp_dropx_s { -+ uint64_t reserved_6_63:58; -+ uint64_t mark:6; -+ } s; -+ struct cvmx_agl_gmx_rx_bp_dropx_s cn52xx; -+ struct cvmx_agl_gmx_rx_bp_dropx_s cn52xxp1; -+ struct cvmx_agl_gmx_rx_bp_dropx_s cn56xx; -+ struct cvmx_agl_gmx_rx_bp_dropx_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rx_bp_offx { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rx_bp_offx_s { -+ uint64_t reserved_6_63:58; -+ uint64_t mark:6; -+ } s; -+ struct cvmx_agl_gmx_rx_bp_offx_s cn52xx; -+ struct cvmx_agl_gmx_rx_bp_offx_s cn52xxp1; -+ struct cvmx_agl_gmx_rx_bp_offx_s cn56xx; -+ struct cvmx_agl_gmx_rx_bp_offx_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rx_bp_onx { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rx_bp_onx_s { -+ uint64_t reserved_9_63:55; -+ uint64_t mark:9; -+ } s; -+ struct cvmx_agl_gmx_rx_bp_onx_s cn52xx; -+ struct cvmx_agl_gmx_rx_bp_onx_s cn52xxp1; -+ struct cvmx_agl_gmx_rx_bp_onx_s cn56xx; -+ struct cvmx_agl_gmx_rx_bp_onx_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rx_prt_info { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rx_prt_info_s { -+ uint64_t reserved_18_63:46; -+ uint64_t drop:2; -+ uint64_t reserved_2_15:14; -+ uint64_t commit:2; -+ } s; -+ struct cvmx_agl_gmx_rx_prt_info_s cn52xx; -+ struct cvmx_agl_gmx_rx_prt_info_s cn52xxp1; -+ struct cvmx_agl_gmx_rx_prt_info_cn56xx { -+ uint64_t reserved_17_63:47; -+ uint64_t drop:1; -+ uint64_t reserved_1_15:15; -+ uint64_t commit:1; -+ } cn56xx; -+ struct cvmx_agl_gmx_rx_prt_info_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_rx_tx_status { -+ uint64_t u64; -+ struct cvmx_agl_gmx_rx_tx_status_s { -+ uint64_t reserved_6_63:58; -+ uint64_t tx:2; -+ uint64_t reserved_2_3:2; -+ uint64_t rx:2; -+ } s; -+ struct cvmx_agl_gmx_rx_tx_status_s cn52xx; -+ struct cvmx_agl_gmx_rx_tx_status_s cn52xxp1; -+ struct cvmx_agl_gmx_rx_tx_status_cn56xx { -+ uint64_t reserved_5_63:59; -+ uint64_t tx:1; -+ uint64_t reserved_1_3:3; -+ uint64_t rx:1; -+ } cn56xx; -+ struct cvmx_agl_gmx_rx_tx_status_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_smacx { -+ uint64_t u64; -+ struct cvmx_agl_gmx_smacx_s { -+ uint64_t reserved_48_63:16; -+ uint64_t smac:48; -+ } s; -+ struct cvmx_agl_gmx_smacx_s cn52xx; -+ struct cvmx_agl_gmx_smacx_s cn52xxp1; -+ struct cvmx_agl_gmx_smacx_s cn56xx; -+ struct cvmx_agl_gmx_smacx_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_stat_bp { -+ uint64_t u64; -+ struct cvmx_agl_gmx_stat_bp_s { -+ uint64_t reserved_17_63:47; -+ uint64_t bp:1; -+ uint64_t cnt:16; -+ } s; -+ struct cvmx_agl_gmx_stat_bp_s cn52xx; -+ struct cvmx_agl_gmx_stat_bp_s cn52xxp1; -+ struct cvmx_agl_gmx_stat_bp_s cn56xx; -+ struct cvmx_agl_gmx_stat_bp_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_append { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_append_s { -+ uint64_t reserved_4_63:60; -+ uint64_t force_fcs:1; -+ uint64_t fcs:1; -+ uint64_t pad:1; -+ uint64_t preamble:1; -+ } s; -+ struct cvmx_agl_gmx_txx_append_s cn52xx; -+ struct cvmx_agl_gmx_txx_append_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_append_s cn56xx; -+ struct cvmx_agl_gmx_txx_append_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_ctl_s { -+ uint64_t reserved_2_63:62; -+ uint64_t xsdef_en:1; -+ uint64_t xscol_en:1; -+ } s; -+ struct cvmx_agl_gmx_txx_ctl_s cn52xx; -+ struct cvmx_agl_gmx_txx_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_ctl_s cn56xx; -+ struct cvmx_agl_gmx_txx_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_min_pkt { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_min_pkt_s { -+ uint64_t reserved_8_63:56; -+ uint64_t min_size:8; -+ } s; -+ struct cvmx_agl_gmx_txx_min_pkt_s cn52xx; -+ struct cvmx_agl_gmx_txx_min_pkt_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_min_pkt_s cn56xx; -+ struct cvmx_agl_gmx_txx_min_pkt_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_pause_pkt_interval { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_pause_pkt_interval_s { -+ uint64_t reserved_16_63:48; -+ uint64_t interval:16; -+ } s; -+ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xx; -+ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xx; -+ struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_pause_pkt_time { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_pause_pkt_time_s { -+ uint64_t reserved_16_63:48; -+ uint64_t time:16; -+ } s; -+ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xx; -+ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xx; -+ struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_pause_togo { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_pause_togo_s { -+ uint64_t reserved_16_63:48; -+ uint64_t time:16; -+ } s; -+ struct cvmx_agl_gmx_txx_pause_togo_s cn52xx; -+ struct cvmx_agl_gmx_txx_pause_togo_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_pause_togo_s cn56xx; -+ struct cvmx_agl_gmx_txx_pause_togo_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_pause_zero { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_pause_zero_s { -+ uint64_t reserved_1_63:63; -+ uint64_t send:1; -+ } s; -+ struct cvmx_agl_gmx_txx_pause_zero_s cn52xx; -+ struct cvmx_agl_gmx_txx_pause_zero_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_pause_zero_s cn56xx; -+ struct cvmx_agl_gmx_txx_pause_zero_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_soft_pause { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_soft_pause_s { -+ uint64_t reserved_16_63:48; -+ uint64_t time:16; -+ } s; -+ struct cvmx_agl_gmx_txx_soft_pause_s cn52xx; -+ struct cvmx_agl_gmx_txx_soft_pause_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_soft_pause_s cn56xx; -+ struct cvmx_agl_gmx_txx_soft_pause_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat0 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat0_s { -+ uint64_t xsdef:32; -+ uint64_t xscol:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat0_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat0_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat0_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat0_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat1 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat1_s { -+ uint64_t scol:32; -+ uint64_t mcol:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat1_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat1_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat1_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat1_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat2 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat2_s { -+ uint64_t reserved_48_63:16; -+ uint64_t octs:48; -+ } s; -+ struct cvmx_agl_gmx_txx_stat2_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat2_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat2_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat2_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat3 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat3_s { -+ uint64_t reserved_32_63:32; -+ uint64_t pkts:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat3_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat3_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat3_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat3_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat4 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat4_s { -+ uint64_t hist1:32; -+ uint64_t hist0:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat4_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat4_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat4_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat4_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat5 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat5_s { -+ uint64_t hist3:32; -+ uint64_t hist2:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat5_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat5_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat5_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat5_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat6 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat6_s { -+ uint64_t hist5:32; -+ uint64_t hist4:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat6_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat6_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat6_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat6_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat7 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat7_s { -+ uint64_t hist7:32; -+ uint64_t hist6:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat7_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat7_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat7_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat7_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat8 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat8_s { -+ uint64_t mcst:32; -+ uint64_t bcst:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat8_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat8_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat8_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat8_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stat9 { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stat9_s { -+ uint64_t undflw:32; -+ uint64_t ctl:32; -+ } s; -+ struct cvmx_agl_gmx_txx_stat9_s cn52xx; -+ struct cvmx_agl_gmx_txx_stat9_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stat9_s cn56xx; -+ struct cvmx_agl_gmx_txx_stat9_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_stats_ctl { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_stats_ctl_s { -+ uint64_t reserved_1_63:63; -+ uint64_t rd_clr:1; -+ } s; -+ struct cvmx_agl_gmx_txx_stats_ctl_s cn52xx; -+ struct cvmx_agl_gmx_txx_stats_ctl_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_stats_ctl_s cn56xx; -+ struct cvmx_agl_gmx_txx_stats_ctl_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_txx_thresh { -+ uint64_t u64; -+ struct cvmx_agl_gmx_txx_thresh_s { -+ uint64_t reserved_6_63:58; -+ uint64_t cnt:6; -+ } s; -+ struct cvmx_agl_gmx_txx_thresh_s cn52xx; -+ struct cvmx_agl_gmx_txx_thresh_s cn52xxp1; -+ struct cvmx_agl_gmx_txx_thresh_s cn56xx; -+ struct cvmx_agl_gmx_txx_thresh_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_bp { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_bp_s { -+ uint64_t reserved_2_63:62; -+ uint64_t bp:2; -+ } s; -+ struct cvmx_agl_gmx_tx_bp_s cn52xx; -+ struct cvmx_agl_gmx_tx_bp_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_bp_cn56xx { -+ uint64_t reserved_1_63:63; -+ uint64_t bp:1; -+ } cn56xx; -+ struct cvmx_agl_gmx_tx_bp_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_col_attempt { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_col_attempt_s { -+ uint64_t reserved_5_63:59; -+ uint64_t limit:5; -+ } s; -+ struct cvmx_agl_gmx_tx_col_attempt_s cn52xx; -+ struct cvmx_agl_gmx_tx_col_attempt_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_col_attempt_s cn56xx; -+ struct cvmx_agl_gmx_tx_col_attempt_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_ifg { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_ifg_s { -+ uint64_t reserved_8_63:56; -+ uint64_t ifg2:4; -+ uint64_t ifg1:4; -+ } s; -+ struct cvmx_agl_gmx_tx_ifg_s cn52xx; -+ struct cvmx_agl_gmx_tx_ifg_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_ifg_s cn56xx; -+ struct cvmx_agl_gmx_tx_ifg_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_int_en { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_int_en_s { -+ uint64_t reserved_18_63:46; -+ uint64_t late_col:2; -+ uint64_t reserved_14_15:2; -+ uint64_t xsdef:2; -+ uint64_t reserved_10_11:2; -+ uint64_t xscol:2; -+ uint64_t reserved_4_7:4; -+ uint64_t undflw:2; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } s; -+ struct cvmx_agl_gmx_tx_int_en_s cn52xx; -+ struct cvmx_agl_gmx_tx_int_en_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_int_en_cn56xx { -+ uint64_t reserved_17_63:47; -+ uint64_t late_col:1; -+ uint64_t reserved_13_15:3; -+ uint64_t xsdef:1; -+ uint64_t reserved_9_11:3; -+ uint64_t xscol:1; -+ uint64_t reserved_3_7:5; -+ uint64_t undflw:1; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn56xx; -+ struct cvmx_agl_gmx_tx_int_en_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_int_reg { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_int_reg_s { -+ uint64_t reserved_18_63:46; -+ uint64_t late_col:2; -+ uint64_t reserved_14_15:2; -+ uint64_t xsdef:2; -+ uint64_t reserved_10_11:2; -+ uint64_t xscol:2; -+ uint64_t reserved_4_7:4; -+ uint64_t undflw:2; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } s; -+ struct cvmx_agl_gmx_tx_int_reg_s cn52xx; -+ struct cvmx_agl_gmx_tx_int_reg_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_int_reg_cn56xx { -+ uint64_t reserved_17_63:47; -+ uint64_t late_col:1; -+ uint64_t reserved_13_15:3; -+ uint64_t xsdef:1; -+ uint64_t reserved_9_11:3; -+ uint64_t xscol:1; -+ uint64_t reserved_3_7:5; -+ uint64_t undflw:1; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn56xx; -+ struct cvmx_agl_gmx_tx_int_reg_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_jam { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_jam_s { -+ uint64_t reserved_8_63:56; -+ uint64_t jam:8; -+ } s; -+ struct cvmx_agl_gmx_tx_jam_s cn52xx; -+ struct cvmx_agl_gmx_tx_jam_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_jam_s cn56xx; -+ struct cvmx_agl_gmx_tx_jam_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_lfsr { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_lfsr_s { -+ uint64_t reserved_16_63:48; -+ uint64_t lfsr:16; -+ } s; -+ struct cvmx_agl_gmx_tx_lfsr_s cn52xx; -+ struct cvmx_agl_gmx_tx_lfsr_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_lfsr_s cn56xx; -+ struct cvmx_agl_gmx_tx_lfsr_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_ovr_bp { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_ovr_bp_s { -+ uint64_t reserved_10_63:54; -+ uint64_t en:2; -+ uint64_t reserved_6_7:2; -+ uint64_t bp:2; -+ uint64_t reserved_2_3:2; -+ uint64_t ign_full:2; -+ } s; -+ struct cvmx_agl_gmx_tx_ovr_bp_s cn52xx; -+ struct cvmx_agl_gmx_tx_ovr_bp_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_ovr_bp_cn56xx { -+ uint64_t reserved_9_63:55; -+ uint64_t en:1; -+ uint64_t reserved_5_7:3; -+ uint64_t bp:1; -+ uint64_t reserved_1_3:3; -+ uint64_t ign_full:1; -+ } cn56xx; -+ struct cvmx_agl_gmx_tx_ovr_bp_cn56xx cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_pause_pkt_dmac { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s { -+ uint64_t reserved_48_63:16; -+ uint64_t dmac:48; -+ } s; -+ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xx; -+ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xx; -+ struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xxp1; -+}; -+ -+union cvmx_agl_gmx_tx_pause_pkt_type { -+ uint64_t u64; -+ struct cvmx_agl_gmx_tx_pause_pkt_type_s { -+ uint64_t reserved_16_63:48; -+ uint64_t type:16; -+ } s; -+ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xx; -+ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xxp1; -+ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xx; -+ struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-mixx-defs.h -@@ -0,0 +1,248 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_MIXX_DEFS_H__ -+#define __CVMX_MIXX_DEFS_H__ -+ -+#define CVMX_MIXX_BIST(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100078ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_CTL(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100020ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_INTENA(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100050ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_IRCNT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100030ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_IRHWM(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100028ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_IRING1(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100010ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_IRING2(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100018ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_ISR(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100048ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_ORCNT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100040ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_ORHWM(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100038ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_ORING1(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100000ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_ORING2(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100008ull + (((offset) & 1) * 2048)) -+#define CVMX_MIXX_REMCNT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001070000100058ull + (((offset) & 1) * 2048)) -+ -+union cvmx_mixx_bist { -+ uint64_t u64; -+ struct cvmx_mixx_bist_s { -+ uint64_t reserved_4_63:60; -+ uint64_t mrqdat:1; -+ uint64_t ipfdat:1; -+ uint64_t irfdat:1; -+ uint64_t orfdat:1; -+ } s; -+ struct cvmx_mixx_bist_s cn52xx; -+ struct cvmx_mixx_bist_s cn52xxp1; -+ struct cvmx_mixx_bist_s cn56xx; -+ struct cvmx_mixx_bist_s cn56xxp1; -+}; -+ -+union cvmx_mixx_ctl { -+ uint64_t u64; -+ struct cvmx_mixx_ctl_s { -+ uint64_t reserved_8_63:56; -+ uint64_t crc_strip:1; -+ uint64_t busy:1; -+ uint64_t en:1; -+ uint64_t reset:1; -+ uint64_t lendian:1; -+ uint64_t nbtarb:1; -+ uint64_t mrq_hwm:2; -+ } s; -+ struct cvmx_mixx_ctl_s cn52xx; -+ struct cvmx_mixx_ctl_s cn52xxp1; -+ struct cvmx_mixx_ctl_s cn56xx; -+ struct cvmx_mixx_ctl_s cn56xxp1; -+}; -+ -+union cvmx_mixx_intena { -+ uint64_t u64; -+ struct cvmx_mixx_intena_s { -+ uint64_t reserved_7_63:57; -+ uint64_t orunena:1; -+ uint64_t irunena:1; -+ uint64_t data_drpena:1; -+ uint64_t ithena:1; -+ uint64_t othena:1; -+ uint64_t ivfena:1; -+ uint64_t ovfena:1; -+ } s; -+ struct cvmx_mixx_intena_s cn52xx; -+ struct cvmx_mixx_intena_s cn52xxp1; -+ struct cvmx_mixx_intena_s cn56xx; -+ struct cvmx_mixx_intena_s cn56xxp1; -+}; -+ -+union cvmx_mixx_ircnt { -+ uint64_t u64; -+ struct cvmx_mixx_ircnt_s { -+ uint64_t reserved_20_63:44; -+ uint64_t ircnt:20; -+ } s; -+ struct cvmx_mixx_ircnt_s cn52xx; -+ struct cvmx_mixx_ircnt_s cn52xxp1; -+ struct cvmx_mixx_ircnt_s cn56xx; -+ struct cvmx_mixx_ircnt_s cn56xxp1; -+}; -+ -+union cvmx_mixx_irhwm { -+ uint64_t u64; -+ struct cvmx_mixx_irhwm_s { -+ uint64_t reserved_40_63:24; -+ uint64_t ibplwm:20; -+ uint64_t irhwm:20; -+ } s; -+ struct cvmx_mixx_irhwm_s cn52xx; -+ struct cvmx_mixx_irhwm_s cn52xxp1; -+ struct cvmx_mixx_irhwm_s cn56xx; -+ struct cvmx_mixx_irhwm_s cn56xxp1; -+}; -+ -+union cvmx_mixx_iring1 { -+ uint64_t u64; -+ struct cvmx_mixx_iring1_s { -+ uint64_t reserved_60_63:4; -+ uint64_t isize:20; -+ uint64_t reserved_36_39:4; -+ uint64_t ibase:33; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_mixx_iring1_s cn52xx; -+ struct cvmx_mixx_iring1_s cn52xxp1; -+ struct cvmx_mixx_iring1_s cn56xx; -+ struct cvmx_mixx_iring1_s cn56xxp1; -+}; -+ -+union cvmx_mixx_iring2 { -+ uint64_t u64; -+ struct cvmx_mixx_iring2_s { -+ uint64_t reserved_52_63:12; -+ uint64_t itlptr:20; -+ uint64_t reserved_20_31:12; -+ uint64_t idbell:20; -+ } s; -+ struct cvmx_mixx_iring2_s cn52xx; -+ struct cvmx_mixx_iring2_s cn52xxp1; -+ struct cvmx_mixx_iring2_s cn56xx; -+ struct cvmx_mixx_iring2_s cn56xxp1; -+}; -+ -+union cvmx_mixx_isr { -+ uint64_t u64; -+ struct cvmx_mixx_isr_s { -+ uint64_t reserved_7_63:57; -+ uint64_t orun:1; -+ uint64_t irun:1; -+ uint64_t data_drp:1; -+ uint64_t irthresh:1; -+ uint64_t orthresh:1; -+ uint64_t idblovf:1; -+ uint64_t odblovf:1; -+ } s; -+ struct cvmx_mixx_isr_s cn52xx; -+ struct cvmx_mixx_isr_s cn52xxp1; -+ struct cvmx_mixx_isr_s cn56xx; -+ struct cvmx_mixx_isr_s cn56xxp1; -+}; -+ -+union cvmx_mixx_orcnt { -+ uint64_t u64; -+ struct cvmx_mixx_orcnt_s { -+ uint64_t reserved_20_63:44; -+ uint64_t orcnt:20; -+ } s; -+ struct cvmx_mixx_orcnt_s cn52xx; -+ struct cvmx_mixx_orcnt_s cn52xxp1; -+ struct cvmx_mixx_orcnt_s cn56xx; -+ struct cvmx_mixx_orcnt_s cn56xxp1; -+}; -+ -+union cvmx_mixx_orhwm { -+ uint64_t u64; -+ struct cvmx_mixx_orhwm_s { -+ uint64_t reserved_20_63:44; -+ uint64_t orhwm:20; -+ } s; -+ struct cvmx_mixx_orhwm_s cn52xx; -+ struct cvmx_mixx_orhwm_s cn52xxp1; -+ struct cvmx_mixx_orhwm_s cn56xx; -+ struct cvmx_mixx_orhwm_s cn56xxp1; -+}; -+ -+union cvmx_mixx_oring1 { -+ uint64_t u64; -+ struct cvmx_mixx_oring1_s { -+ uint64_t reserved_60_63:4; -+ uint64_t osize:20; -+ uint64_t reserved_36_39:4; -+ uint64_t obase:33; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_mixx_oring1_s cn52xx; -+ struct cvmx_mixx_oring1_s cn52xxp1; -+ struct cvmx_mixx_oring1_s cn56xx; -+ struct cvmx_mixx_oring1_s cn56xxp1; -+}; -+ -+union cvmx_mixx_oring2 { -+ uint64_t u64; -+ struct cvmx_mixx_oring2_s { -+ uint64_t reserved_52_63:12; -+ uint64_t otlptr:20; -+ uint64_t reserved_20_31:12; -+ uint64_t odbell:20; -+ } s; -+ struct cvmx_mixx_oring2_s cn52xx; -+ struct cvmx_mixx_oring2_s cn52xxp1; -+ struct cvmx_mixx_oring2_s cn56xx; -+ struct cvmx_mixx_oring2_s cn56xxp1; -+}; -+ -+union cvmx_mixx_remcnt { -+ uint64_t u64; -+ struct cvmx_mixx_remcnt_s { -+ uint64_t reserved_52_63:12; -+ uint64_t iremcnt:20; -+ uint64_t reserved_20_31:12; -+ uint64_t oremcnt:20; -+ } s; -+ struct cvmx_mixx_remcnt_s cn52xx; -+ struct cvmx_mixx_remcnt_s cn52xxp1; -+ struct cvmx_mixx_remcnt_s cn56xx; -+ struct cvmx_mixx_remcnt_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-smix-defs.h -@@ -0,0 +1,178 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_SMIX_DEFS_H__ -+#define __CVMX_SMIX_DEFS_H__ -+ -+#define CVMX_SMIX_CLK(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_CMD(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_EN(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_RD_DAT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_WR_DAT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256)) -+ -+union cvmx_smix_clk { -+ uint64_t u64; -+ struct cvmx_smix_clk_s { -+ uint64_t reserved_25_63:39; -+ uint64_t mode:1; -+ uint64_t reserved_21_23:3; -+ uint64_t sample_hi:5; -+ uint64_t sample_mode:1; -+ uint64_t reserved_14_14:1; -+ uint64_t clk_idle:1; -+ uint64_t preamble:1; -+ uint64_t sample:4; -+ uint64_t phase:8; -+ } s; -+ struct cvmx_smix_clk_cn30xx { -+ uint64_t reserved_21_63:43; -+ uint64_t sample_hi:5; -+ uint64_t reserved_14_15:2; -+ uint64_t clk_idle:1; -+ uint64_t preamble:1; -+ uint64_t sample:4; -+ uint64_t phase:8; -+ } cn30xx; -+ struct cvmx_smix_clk_cn30xx cn31xx; -+ struct cvmx_smix_clk_cn30xx cn38xx; -+ struct cvmx_smix_clk_cn30xx cn38xxp2; -+ struct cvmx_smix_clk_cn50xx { -+ uint64_t reserved_25_63:39; -+ uint64_t mode:1; -+ uint64_t reserved_21_23:3; -+ uint64_t sample_hi:5; -+ uint64_t reserved_14_15:2; -+ uint64_t clk_idle:1; -+ uint64_t preamble:1; -+ uint64_t sample:4; -+ uint64_t phase:8; -+ } cn50xx; -+ struct cvmx_smix_clk_s cn52xx; -+ struct cvmx_smix_clk_cn50xx cn52xxp1; -+ struct cvmx_smix_clk_s cn56xx; -+ struct cvmx_smix_clk_cn50xx cn56xxp1; -+ struct cvmx_smix_clk_cn30xx cn58xx; -+ struct cvmx_smix_clk_cn30xx cn58xxp1; -+}; -+ -+union cvmx_smix_cmd { -+ uint64_t u64; -+ struct cvmx_smix_cmd_s { -+ uint64_t reserved_18_63:46; -+ uint64_t phy_op:2; -+ uint64_t reserved_13_15:3; -+ uint64_t phy_adr:5; -+ uint64_t reserved_5_7:3; -+ uint64_t reg_adr:5; -+ } s; -+ struct cvmx_smix_cmd_cn30xx { -+ uint64_t reserved_17_63:47; -+ uint64_t phy_op:1; -+ uint64_t reserved_13_15:3; -+ uint64_t phy_adr:5; -+ uint64_t reserved_5_7:3; -+ uint64_t reg_adr:5; -+ } cn30xx; -+ struct cvmx_smix_cmd_cn30xx cn31xx; -+ struct cvmx_smix_cmd_cn30xx cn38xx; -+ struct cvmx_smix_cmd_cn30xx cn38xxp2; -+ struct cvmx_smix_cmd_s cn50xx; -+ struct cvmx_smix_cmd_s cn52xx; -+ struct cvmx_smix_cmd_s cn52xxp1; -+ struct cvmx_smix_cmd_s cn56xx; -+ struct cvmx_smix_cmd_s cn56xxp1; -+ struct cvmx_smix_cmd_cn30xx cn58xx; -+ struct cvmx_smix_cmd_cn30xx cn58xxp1; -+}; -+ -+union cvmx_smix_en { -+ uint64_t u64; -+ struct cvmx_smix_en_s { -+ uint64_t reserved_1_63:63; -+ uint64_t en:1; -+ } s; -+ struct cvmx_smix_en_s cn30xx; -+ struct cvmx_smix_en_s cn31xx; -+ struct cvmx_smix_en_s cn38xx; -+ struct cvmx_smix_en_s cn38xxp2; -+ struct cvmx_smix_en_s cn50xx; -+ struct cvmx_smix_en_s cn52xx; -+ struct cvmx_smix_en_s cn52xxp1; -+ struct cvmx_smix_en_s cn56xx; -+ struct cvmx_smix_en_s cn56xxp1; -+ struct cvmx_smix_en_s cn58xx; -+ struct cvmx_smix_en_s cn58xxp1; -+}; -+ -+union cvmx_smix_rd_dat { -+ uint64_t u64; -+ struct cvmx_smix_rd_dat_s { -+ uint64_t reserved_18_63:46; -+ uint64_t pending:1; -+ uint64_t val:1; -+ uint64_t dat:16; -+ } s; -+ struct cvmx_smix_rd_dat_s cn30xx; -+ struct cvmx_smix_rd_dat_s cn31xx; -+ struct cvmx_smix_rd_dat_s cn38xx; -+ struct cvmx_smix_rd_dat_s cn38xxp2; -+ struct cvmx_smix_rd_dat_s cn50xx; -+ struct cvmx_smix_rd_dat_s cn52xx; -+ struct cvmx_smix_rd_dat_s cn52xxp1; -+ struct cvmx_smix_rd_dat_s cn56xx; -+ struct cvmx_smix_rd_dat_s cn56xxp1; -+ struct cvmx_smix_rd_dat_s cn58xx; -+ struct cvmx_smix_rd_dat_s cn58xxp1; -+}; -+ -+union cvmx_smix_wr_dat { -+ uint64_t u64; -+ struct cvmx_smix_wr_dat_s { -+ uint64_t reserved_18_63:46; -+ uint64_t pending:1; -+ uint64_t val:1; -+ uint64_t dat:16; -+ } s; -+ struct cvmx_smix_wr_dat_s cn30xx; -+ struct cvmx_smix_wr_dat_s cn31xx; -+ struct cvmx_smix_wr_dat_s cn38xx; -+ struct cvmx_smix_wr_dat_s cn38xxp2; -+ struct cvmx_smix_wr_dat_s cn50xx; -+ struct cvmx_smix_wr_dat_s cn52xx; -+ struct cvmx_smix_wr_dat_s cn52xxp1; -+ struct cvmx_smix_wr_dat_s cn56xx; -+ struct cvmx_smix_wr_dat_s cn56xxp1; -+ struct cvmx_smix_wr_dat_s cn58xx; -+ struct cvmx_smix_wr_dat_s cn58xxp1; -+}; -+ -+#endif diff --git a/target/linux/octeon/patches/006-octeon_mgmt_driver.patch b/target/linux/octeon/patches/006-octeon_mgmt_driver.patch deleted file mode 100644 index 7ea094519e..0000000000 --- a/target/linux/octeon/patches/006-octeon_mgmt_driver.patch +++ /dev/null @@ -1,2022 +0,0 @@ -Signed-off-by: David Daney ---- - arch/mips/include/asm/octeon/cvmx-mdio.h | 577 +++++++++++++++++++++ - drivers/net/Kconfig | 8 + - drivers/net/Makefile | 1 + - drivers/net/octeon/Makefile | 11 + - drivers/net/octeon/cvmx-mgmt-port.c | 818 ++++++++++++++++++++++++++++++ - drivers/net/octeon/cvmx-mgmt-port.h | 168 ++++++ - drivers/net/octeon/octeon-mgmt-port.c | 389 ++++++++++++++ - 7 files changed, 1972 insertions(+), 0 deletions(-) - create mode 100644 arch/mips/include/asm/octeon/cvmx-mdio.h - create mode 100644 drivers/net/octeon/Makefile - create mode 100644 drivers/net/octeon/cvmx-mgmt-port.c - create mode 100644 drivers/net/octeon/cvmx-mgmt-port.h - create mode 100644 drivers/net/octeon/octeon-mgmt-port.c - ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-mdio.h -@@ -0,0 +1,577 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3 -+ * clause 22 and clause 45 operations. -+ * -+ */ -+ -+#ifndef __CVMX_MIO_H__ -+#define __CVMX_MIO_H__ -+ -+#include "cvmx-smix-defs.h" -+ -+/** -+ * PHY register 0 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_CONTROL 0 -+union cvmx_mdio_phy_reg_control { -+ uint16_t u16; -+ struct { -+ uint16_t reset:1; -+ uint16_t loopback:1; -+ uint16_t speed_lsb:1; -+ uint16_t autoneg_enable:1; -+ uint16_t power_down:1; -+ uint16_t isolate:1; -+ uint16_t restart_autoneg:1; -+ uint16_t duplex:1; -+ uint16_t collision_test:1; -+ uint16_t speed_msb:1; -+ uint16_t unidirectional_enable:1; -+ uint16_t reserved_0_4:5; -+ } s; -+}; -+ -+/** -+ * PHY register 1 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_STATUS 1 -+union cvmx_mdio_phy_reg_status { -+ uint16_t u16; -+ struct { -+ uint16_t capable_100base_t4:1; -+ uint16_t capable_100base_x_full:1; -+ uint16_t capable_100base_x_half:1; -+ uint16_t capable_10_full:1; -+ uint16_t capable_10_half:1; -+ uint16_t capable_100base_t2_full:1; -+ uint16_t capable_100base_t2_half:1; -+ uint16_t capable_extended_status:1; -+ uint16_t capable_unidirectional:1; -+ uint16_t capable_mf_preamble_suppression:1; -+ uint16_t autoneg_complete:1; -+ uint16_t remote_fault:1; -+ uint16_t capable_autoneg:1; -+ uint16_t link_status:1; -+ uint16_t jabber_detect:1; -+ uint16_t capable_extended_registers:1; -+ -+ } s; -+}; -+ -+/** -+ * PHY register 2 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_ID1 2 -+union cvmx_mdio_phy_reg_id1 { -+ uint16_t u16; -+ struct { -+ uint16_t oui_bits_3_18; -+ } s; -+}; -+ -+/** -+ * PHY register 3 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_ID2 3 -+union cvmx_mdio_phy_reg_id2 { -+ uint16_t u16; -+ struct { -+ uint16_t oui_bits_19_24:6; -+ uint16_t model:6; -+ uint16_t revision:4; -+ } s; -+}; -+ -+/** -+ * PHY register 4 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4 -+union cvmx_mdio_phy_reg_autoneg_adver { -+ uint16_t u16; -+ struct { -+ uint16_t next_page:1; -+ uint16_t reserved_14:1; -+ uint16_t remote_fault:1; -+ uint16_t reserved_12:1; -+ uint16_t asymmetric_pause:1; -+ uint16_t pause:1; -+ uint16_t advert_100base_t4:1; -+ uint16_t advert_100base_tx_full:1; -+ uint16_t advert_100base_tx_half:1; -+ uint16_t advert_10base_tx_full:1; -+ uint16_t advert_10base_tx_half:1; -+ uint16_t selector:5; -+ } s; -+}; -+ -+/** -+ * PHY register 5 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5 -+union cvmx_mdio_phy_reg_link_partner_ability { -+ uint16_t u16; -+ struct { -+ uint16_t next_page:1; -+ uint16_t ack:1; -+ uint16_t remote_fault:1; -+ uint16_t reserved_12:1; -+ uint16_t asymmetric_pause:1; -+ uint16_t pause:1; -+ uint16_t advert_100base_t4:1; -+ uint16_t advert_100base_tx_full:1; -+ uint16_t advert_100base_tx_half:1; -+ uint16_t advert_10base_tx_full:1; -+ uint16_t advert_10base_tx_half:1; -+ uint16_t selector:5; -+ } s; -+}; -+ -+/** -+ * PHY register 6 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6 -+union cvmx_mdio_phy_reg_autoneg_expansion { -+ uint16_t u16; -+ struct { -+ uint16_t reserved_5_15:11; -+ uint16_t parallel_detection_fault:1; -+ uint16_t link_partner_next_page_capable:1; -+ uint16_t local_next_page_capable:1; -+ uint16_t page_received:1; -+ uint16_t link_partner_autoneg_capable:1; -+ -+ } s; -+}; -+ -+/** -+ * PHY register 9 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_CONTROL_1000 9 -+union cvmx_mdio_phy_reg_control_1000 { -+ uint16_t u16; -+ struct { -+ uint16_t test_mode:3; -+ uint16_t manual_master_slave:1; -+ uint16_t master:1; -+ uint16_t port_type:1; -+ uint16_t advert_1000base_t_full:1; -+ uint16_t advert_1000base_t_half:1; -+ uint16_t reserved_0_7:8; -+ } s; -+}; -+ -+/** -+ * PHY register 10 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_STATUS_1000 10 -+union cvmx_mdio_phy_reg_status_1000 { -+ uint16_t u16; -+ struct { -+ uint16_t master_slave_fault:1; -+ uint16_t is_master:1; -+ uint16_t local_receiver_ok:1; -+ uint16_t remote_receiver_ok:1; -+ uint16_t remote_capable_1000base_t_full:1; -+ uint16_t remote_capable_1000base_t_half:1; -+ uint16_t reserved_8_9:2; -+ uint16_t idle_error_count:8; -+ } s; -+}; -+ -+/** -+ * PHY register 15 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15 -+union cvmx_mdio_phy_reg_extended_status { -+ uint16_t u16; -+ struct { -+ uint16_t capable_1000base_x_full:1; -+ uint16_t capable_1000base_x_half:1; -+ uint16_t capable_1000base_t_full:1; -+ uint16_t capable_1000base_t_half:1; -+ uint16_t reserved_0_11:12; -+ } s; -+}; -+ -+/** -+ * PHY register 13 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13 -+union cvmx_mdio_phy_reg_mmd_control { -+ uint16_t u16; -+ struct { -+ uint16_t function:2; -+ uint16_t reserved_5_13:9; -+ uint16_t devad:5; -+ } s; -+}; -+ -+/** -+ * PHY register 14 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14 -+union cvmx_mdio_phy_reg_mmd_address_data { -+ uint16_t u16; -+ struct { -+ uint16_t address_data:16; -+ } s; -+}; -+ -+/* Operating request encodings. */ -+#define MDIO_CLAUSE_22_WRITE 0 -+#define MDIO_CLAUSE_22_READ 1 -+ -+#define MDIO_CLAUSE_45_ADDRESS 0 -+#define MDIO_CLAUSE_45_WRITE 1 -+#define MDIO_CLAUSE_45_READ_INC 2 -+#define MDIO_CLAUSE_45_READ 3 -+ -+/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */ -+#define CVMX_MMD_DEVICE_PMA_PMD 1 -+#define CVMX_MMD_DEVICE_WIS 2 -+#define CVMX_MMD_DEVICE_PCS 3 -+#define CVMX_MMD_DEVICE_PHY_XS 4 -+#define CVMX_MMD_DEVICE_DTS_XS 5 -+#define CVMX_MMD_DEVICE_TC 6 -+#define CVMX_MMD_DEVICE_CL22_EXT 29 -+#define CVMX_MMD_DEVICE_VENDOR_1 30 -+#define CVMX_MMD_DEVICE_VENDOR_2 31 -+ -+/** -+ * Perform an MII read. This function is used to read PHY -+ * registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @location: Register location to read -+ * -+ * Returns Result from the read or -1 on failure -+ */ -+static inline int cvmx_mdio_read(int bus_id, int phy_id, int location) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_rd_dat smi_rd; -+ int timeout = 1000; -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = location; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); -+ } while (smi_rd.s.pending && timeout--); -+ -+ if (smi_rd.s.val) -+ return smi_rd.s.dat; -+ else -+ return -1; -+} -+ -+/** -+ * Perform an MII write. This function is used to write PHY -+ * registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @location: Register location to write -+ * @val: Value to write -+ * -+ * Returns -1 on error -+ * 0 on success -+ */ -+static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_wr_dat smi_wr; -+ int timeout = 1000; -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = val; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = location; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ return 0; -+} -+ -+/** -+ * Perform an IEEE 802.3 clause 45 MII read using clause 22 operations. This -+ * function is used to read PHY registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @device: MDIO Managable Device (MMD) id -+ * @location: Register location to read -+ * -+ * Returns Result from the read or -1 on failure -+ */ -+ -+static inline int cvmx_mdio_45_via_22_read(int bus_id, int phy_id, int device, -+ int location) -+{ -+ union cvmx_mdio_phy_reg_mmd_control mmd_control; -+ -+ /* -+ * a) To Register 13, write the Function field to 00 (address) -+ * and DEVAD field to the device address value for the -+ * desired MMD; -+ */ -+ mmd_control.u16 = 0; -+ mmd_control.s.function = MDIO_CLAUSE_45_ADDRESS; -+ mmd_control.s.devad = device; -+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, -+ mmd_control.u16); -+ -+ /* -+ * b) To Register 14, write the desired address value to the -+ * MMD's address register; -+ */ -+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, -+ location); -+ -+ /* -+ * c) To Register 13, write the Function field to 01 (Data, no -+ * post increment) and DEVAD field to the same device -+ * address value for the desired MMD; -+ */ -+ mmd_control.u16 = 0; -+ mmd_control.s.function = MDIO_CLAUSE_45_READ; -+ mmd_control.s.devad = device; -+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, -+ mmd_control.u16); -+ -+ /* -+ * d) From Register 14, read the content of the MMD's selected -+ * register. -+ */ -+ return cvmx_mdio_read(bus_id, phy_id, -+ CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA); -+} -+ -+/** -+ * Perform an IEEE 802.3 clause 45 MII write using clause 22 -+ * operations. This function is used to write PHY registers -+ * controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @device: MDIO Managable Device (MMD) id -+ * @location: Register location to write -+ * @val: Value to write -+ * -+ * Returns -1 on error -+ * 0 on success -+ */ -+static inline int cvmx_mdio_45_via_22_write(int bus_id, int phy_id, int device, -+ int location, int val) -+{ -+ union cvmx_mdio_phy_reg_mmd_control mmd_control; -+ -+ /* -+ * a) To Register 13, write the Function field to 00 (address) -+ * and DEVAD field to the device address value for the -+ * desired MMD; -+ */ -+ mmd_control.u16 = 0; -+ mmd_control.s.function = MDIO_CLAUSE_45_ADDRESS; -+ mmd_control.s.devad = device; -+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, -+ mmd_control.u16); -+ -+ /* -+ * b) To Register 14, write the desired address value to the -+ * MMD's address register; -+ */ -+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, -+ location); -+ -+ /* -+ * c) To Register 13, write the Function field to 01 (Data, no -+ * post increment) and DEVAD field to the same device -+ * address value for the desired MMD; -+ */ -+ mmd_control.u16 = 0; -+ mmd_control.s.function = MDIO_CLAUSE_45_READ; -+ mmd_control.s.devad = device; -+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL, -+ mmd_control.u16); -+ -+ /* -+ * d) To Register 14, write the content of the MMD's selected -+ * register. -+ */ -+ return cvmx_mdio_write(bus_id, phy_id, -+ CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, val); -+ -+ return 0; -+} -+ -+/** -+ * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY -+ * registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @device: MDIO Managable Device (MMD) id -+ * @location: Register location to read -+ * -+ * Returns Result from the read or -1 on failure -+ */ -+ -+static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, -+ int location) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_rd_dat smi_rd; -+ union cvmx_smix_wr_dat smi_wr; -+ int timeout = 1000; -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = location; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); -+ } while (smi_rd.s.pending && timeout--); -+ -+ if (0 == timeout) -+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " -+ "device %2d register %2d TIME OUT\n", -+ bus_id, phy_id, device, location); -+ -+ if (smi_rd.s.val) -+ return smi_rd.s.dat; -+ else { -+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " -+ "device %2d register %2d INVALID READ\n", -+ bus_id, phy_id, device, location); -+ return -1; -+ } -+} -+ -+/** -+ * Perform an IEEE 802.3 clause 45 MII write. This function is used to -+ * write PHY registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @device: MDIO Managable Device (MMD) id -+ * @location: Register location to write -+ * @val: Value to write -+ * -+ * Returns -1 on error -+ * 0 on success -+ */ -+static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, -+ int location, int val) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_wr_dat smi_wr; -+ int timeout = 1000; -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = location; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = val; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ return 0; -+} -+ -+#endif ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -2035,6 +2035,14 @@ config ATL2 - To compile this driver as a module, choose M here. The module - will be called atl2. - -+config OCTEON_MGMT -+ tristate "OCTEON Management port ethernet driver (CN5XXX)" -+ depends on CPU_CAVIUM_OCTEON -+ default y -+ help -+ This option enables the ethernet driver for the management port on -+ CN52XX, CN57XX, CN56XX, CN55XX, and CN54XX chips. -+ - source "drivers/net/fs_enet/Kconfig" - - endif # NET_ETHERNET ---- a/drivers/net/Makefile -+++ b/drivers/net/Makefile -@@ -234,6 +234,7 @@ pasemi_mac_driver-objs := pasemi_mac.o p - obj-$(CONFIG_MLX4_CORE) += mlx4/ - obj-$(CONFIG_ENC28J60) += enc28j60.o - obj-$(CONFIG_ETHOC) += ethoc.o -+obj-$(CONFIG_OCTEON_MGMT) += octeon/ - - obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o - ---- /dev/null -+++ b/drivers/net/octeon/Makefile -@@ -0,0 +1,11 @@ -+# Makefile for the Cavium OCTEON Ethernet drivers. -+# -+# This file is subject to the terms and conditions of the GNU General Public -+# License. See the file "COPYING" in the main directory of this archive -+# for more details. -+# -+# Copyright (C) 2008 Cavium Networks -+ -+obj-$(CONFIG_OCTEON_MGMT) += octeon_mgmt.o -+ -+octeon_mgmt-objs := octeon-mgmt-port.o cvmx-mgmt-port.o -\ No newline at end of file ---- /dev/null -+++ b/drivers/net/octeon/cvmx-mgmt-port.c -@@ -0,0 +1,818 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Support functions for managing the MII management port -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "cvmx-mgmt-port.h" -+ -+#define CVMX_MGMT_PORT_NUM_PORTS 2 -+/* Number of TX ring buffer entries and buffers */ -+#define CVMX_MGMT_PORT_NUM_TX_BUFFERS 16 -+/* Number of RX ring buffer entries and buffers */ -+#define CVMX_MGMT_PORT_NUM_RX_BUFFERS 128 -+ -+#define CVMX_MGMT_PORT_TX_BUFFER_SIZE 12288 -+#define CVMX_MGMT_PORT_RX_BUFFER_SIZE 1536 -+ -+/** -+ * Format of the TX/RX ring buffer entries -+ */ -+union cvmx_mgmt_port_ring_entry { -+ uint64_t u64; -+ struct { -+ uint64_t reserved_62_63:2; -+ /* Length of the buffer/packet in bytes */ -+ uint64_t len:14; -+ /* The RX error code */ -+ uint64_t code:8; -+ /* Physical address of the buffer */ -+ uint64_t addr:40; -+ } s; -+}; -+ -+/** -+ * Per port state required for each mgmt port -+ */ -+struct cvmx_mgmt_port_state { -+ /* Used for exclusive access to this structure */ -+ cvmx_spinlock_t lock; -+ /* Where the next TX will write in the tx_ring and tx_buffers */ -+ int tx_write_index; -+ /* Where the next RX will be in the rx_ring and rx_buffers */ -+ int rx_read_index; -+ /* The SMI/MDIO PHY address */ -+ int phy_id; -+ /* Our MAC address */ -+ uint64_t mac; -+ union cvmx_mgmt_port_ring_entry tx_ring[CVMX_MGMT_PORT_NUM_TX_BUFFERS]; -+ union cvmx_mgmt_port_ring_entry rx_ring[CVMX_MGMT_PORT_NUM_RX_BUFFERS]; -+ char tx_buffers[CVMX_MGMT_PORT_NUM_TX_BUFFERS] -+ [CVMX_MGMT_PORT_TX_BUFFER_SIZE]; -+ char rx_buffers[CVMX_MGMT_PORT_NUM_RX_BUFFERS] -+ [CVMX_MGMT_PORT_RX_BUFFER_SIZE]; -+}; -+ -+/** -+ * Pointers to each mgmt port's state -+ */ -+struct cvmx_mgmt_port_state *cvmx_mgmt_port_state_ptr; -+ -+/** -+ * Return the number of management ports supported by this chip -+ * -+ * Returns Number of ports -+ */ -+int __cvmx_mgmt_port_num_ports(void) -+{ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) -+ return 1; -+ else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ return 2; -+ else -+ return 0; -+} -+ -+/** -+ * Called to initialize a management port for use. Multiple calls -+ * to this function accross applications is safe. -+ * -+ * @port: Port to initialize -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+enum cvmx_mgmt_port_result cvmx_mgmt_port_initialize(int port) -+{ -+ char *alloc_name = "cvmx_mgmt_port"; -+ union cvmx_mixx_oring1 oring1; -+ union cvmx_mixx_ctl mix_ctl; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ cvmx_mgmt_port_state_ptr = -+ cvmx_bootmem_alloc_named(CVMX_MGMT_PORT_NUM_PORTS * -+ sizeof(struct cvmx_mgmt_port_state), 128, -+ alloc_name); -+ if (cvmx_mgmt_port_state_ptr) { -+ memset(cvmx_mgmt_port_state_ptr, 0, -+ CVMX_MGMT_PORT_NUM_PORTS * -+ sizeof(struct cvmx_mgmt_port_state)); -+ } else { -+ struct cvmx_bootmem_named_block_desc *block_desc = -+ cvmx_bootmem_find_named_block(alloc_name); -+ if (block_desc) -+ cvmx_mgmt_port_state_ptr = -+ cvmx_phys_to_ptr(block_desc->base_addr); -+ else { -+ cvmx_dprintf("ERROR: cvmx_mgmt_port_initialize: " -+ "Unable to get named block %s.\n", -+ alloc_name); -+ return CVMX_MGMT_PORT_NO_MEMORY; -+ } -+ } -+ -+ /* -+ * Reset the MIX block if the previous user had a different TX -+ * ring size. -+ */ -+ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); -+ if (!mix_ctl.s.reset) { -+ oring1.u64 = cvmx_read_csr(CVMX_MIXX_ORING1(port)); -+ if (oring1.s.osize != CVMX_MGMT_PORT_NUM_TX_BUFFERS) { -+ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); -+ mix_ctl.s.en = 0; -+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); -+ do { -+ mix_ctl.u64 = -+ cvmx_read_csr(CVMX_MIXX_CTL(port)); -+ } while (mix_ctl.s.busy); -+ mix_ctl.s.reset = 1; -+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); -+ cvmx_read_csr(CVMX_MIXX_CTL(port)); -+ memset(cvmx_mgmt_port_state_ptr + port, 0, -+ sizeof(struct cvmx_mgmt_port_state)); -+ } -+ } -+ -+ if (cvmx_mgmt_port_state_ptr[port].tx_ring[0].u64 == 0) { -+ struct cvmx_mgmt_port_state *state = -+ cvmx_mgmt_port_state_ptr + port; -+ int i; -+ union cvmx_mixx_bist mix_bist; -+ union cvmx_agl_gmx_bist agl_gmx_bist; -+ union cvmx_mixx_oring1 oring1; -+ union cvmx_mixx_iring1 iring1; -+ union cvmx_mixx_ctl mix_ctl; -+ -+ /* Make sure BIST passed */ -+ mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(port)); -+ if (mix_bist.u64) -+ cvmx_dprintf("WARNING: cvmx_mgmt_port_initialize: " -+ "Managment port MIX failed BIST " -+ "(0x%016llx)\n", -+ (unsigned long long)mix_bist.u64); -+ -+ agl_gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST); -+ if (agl_gmx_bist.u64) -+ cvmx_dprintf("WARNING: cvmx_mgmt_port_initialize: " -+ "Managment port AGL failed BIST " -+ "(0x%016llx)\n", -+ (unsigned long long)agl_gmx_bist.u64); -+ -+ /* Clear all state information */ -+ memset(state, 0, sizeof(*state)); -+ -+ /* Take the control logic out of reset */ -+ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); -+ mix_ctl.s.reset = 0; -+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); -+ -+ /* Set the PHY address */ -+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) -+ state->phy_id = -1; -+ else -+ /* Will need to be change to match the board */ -+ state->phy_id = port; -+ -+ /* Create a default MAC address */ -+ state->mac = 0x000000dead000000ull; -+ state->mac += 0xffffff & CAST64(state); -+ -+ /* Setup the TX ring */ -+ for (i = 0; i < CVMX_MGMT_PORT_NUM_TX_BUFFERS; i++) { -+ state->tx_ring[i].s.len = CVMX_MGMT_PORT_TX_BUFFER_SIZE; -+ state->tx_ring[i].s.addr = -+ cvmx_ptr_to_phys(state->tx_buffers[i]); -+ } -+ -+ /* Tell the HW where the TX ring is */ -+ oring1.u64 = 0; -+ oring1.s.obase = cvmx_ptr_to_phys(state->tx_ring) >> 3; -+ oring1.s.osize = CVMX_MGMT_PORT_NUM_TX_BUFFERS; -+ CVMX_SYNCWS; -+ cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64); -+ -+ /* Setup the RX ring */ -+ for (i = 0; i < CVMX_MGMT_PORT_NUM_RX_BUFFERS; i++) { -+ /* This size is -8 due to an errata for CN56XX pass 1 */ -+ state->rx_ring[i].s.len = -+ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8; -+ state->rx_ring[i].s.addr = -+ cvmx_ptr_to_phys(state->rx_buffers[i]); -+ } -+ -+ /* Tell the HW where the RX ring is */ -+ iring1.u64 = 0; -+ iring1.s.ibase = cvmx_ptr_to_phys(state->rx_ring) >> 3; -+ iring1.s.isize = CVMX_MGMT_PORT_NUM_RX_BUFFERS; -+ CVMX_SYNCWS; -+ cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64); -+ cvmx_write_csr(CVMX_MIXX_IRING2(port), -+ CVMX_MGMT_PORT_NUM_RX_BUFFERS); -+ -+ /* Disable the external input/output */ -+ cvmx_mgmt_port_disable(port); -+ -+ /* Set the MAC address filtering up */ -+ cvmx_mgmt_port_set_mac(port, state->mac); -+ -+ /* -+ * Set the default max size to an MTU of 1500 with L2 -+ * and VLAN. -+ */ -+ cvmx_mgmt_port_set_max_packet_size(port, 1518); -+ -+ /* -+ * Enable the port HW. Packets are not allowed until -+ * cvmx_mgmt_port_enable() is called. -+ */ -+ mix_ctl.u64 = 0; -+ /* Strip the ending CRC */ -+ mix_ctl.s.crc_strip = 1; -+ /* Enable the port */ -+ mix_ctl.s.en = 1; -+ /* Arbitration mode */ -+ mix_ctl.s.nbtarb = 0; -+ /* MII CB-request FIFO programmable high watermark */ -+ mix_ctl.s.mrq_hwm = 1; -+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) -+ || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { -+ /* -+ * Force compensation values, as they are not -+ * determined properly by HW. -+ */ -+ union cvmx_agl_gmx_drv_ctl drv_ctl; -+ -+ drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL); -+ if (port) { -+ drv_ctl.s.byp_en1 = 1; -+ drv_ctl.s.nctl1 = 6; -+ drv_ctl.s.pctl1 = 6; -+ } else { -+ drv_ctl.s.byp_en = 1; -+ drv_ctl.s.nctl = 6; -+ drv_ctl.s.pctl = 6; -+ } -+ cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64); -+ } -+ } -+ return CVMX_MGMT_PORT_SUCCESS; -+} -+ -+/** -+ * Shutdown a management port. This currently disables packet IO -+ * but leaves all hardware and buffers. Another application can then -+ * call initialize() without redoing the hardware setup. -+ * -+ * @port: Management port -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+enum cvmx_mgmt_port_result cvmx_mgmt_port_shutdown(int port) -+{ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ /* Stop packets from comming in */ -+ cvmx_mgmt_port_disable(port); -+ -+ /* -+ * We don't free any memory so the next intialize can reuse -+ * the HW setup. -+ */ -+ return CVMX_MGMT_PORT_SUCCESS; -+} -+ -+/** -+ * Enable packet IO on a management port -+ * -+ * @port: Management port -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+enum cvmx_mgmt_port_result cvmx_mgmt_port_enable(int port) -+{ -+ struct cvmx_mgmt_port_state *state; -+ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; -+ union cvmx_agl_gmx_inf_mode agl_gmx_inf_mode; -+ union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ -+ rxx_frm_ctl.u64 = 0; -+ rxx_frm_ctl.s.pre_align = 1; -+ /* -+ * When set, disables the length check for non-min sized pkts -+ * with padding in the client data. -+ */ -+ rxx_frm_ctl.s.pad_len = 1; -+ /* When set, disables the length check for VLAN pkts */ -+ rxx_frm_ctl.s.vlan_len = 1; -+ /* When set, PREAMBLE checking is less strict */ -+ rxx_frm_ctl.s.pre_free = 1; -+ /* Control Pause Frames can match station SMAC */ -+ rxx_frm_ctl.s.ctl_smac = 0; -+ /* Control Pause Frames can match globally assign Multicast address */ -+ rxx_frm_ctl.s.ctl_mcst = 1; -+ /* Forward pause information to TX block */ -+ rxx_frm_ctl.s.ctl_bck = 1; -+ /* Drop Control Pause Frames */ -+ rxx_frm_ctl.s.ctl_drp = 1; -+ /* Strip off the preamble */ -+ rxx_frm_ctl.s.pre_strp = 1; -+ /* -+ * This port is configured to send PREAMBLE+SFD to begin every -+ * frame. GMX checks that the PREAMBLE is sent correctly. -+ */ -+ rxx_frm_ctl.s.pre_chk = 1; -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64); -+ -+ /* Enable the AGL block */ -+ agl_gmx_inf_mode.u64 = 0; -+ agl_gmx_inf_mode.s.en = 1; -+ cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64); -+ -+ /* Configure the port duplex and enables */ -+ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); -+ agl_gmx_prtx.s.tx_en = 1; -+ agl_gmx_prtx.s.rx_en = 1; -+ if (cvmx_mgmt_port_get_link(port) < 0) -+ agl_gmx_prtx.s.duplex = 0; -+ else -+ agl_gmx_prtx.s.duplex = 1; -+ agl_gmx_prtx.s.en = 1; -+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); -+ -+ cvmx_spinlock_unlock(&state->lock); -+ return CVMX_MGMT_PORT_SUCCESS; -+} -+ -+/** -+ * Disable packet IO on a management port -+ * -+ * @port: Management port -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+enum cvmx_mgmt_port_result cvmx_mgmt_port_disable(int port) -+{ -+ struct cvmx_mgmt_port_state *state; -+ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ -+ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); -+ agl_gmx_prtx.s.en = 0; -+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); -+ -+ cvmx_spinlock_unlock(&state->lock); -+ return CVMX_MGMT_PORT_SUCCESS; -+} -+ -+/** -+ * Send a packet out the management port. The packet is copied so -+ * the input buffer isn't used after this call. -+ * -+ * @port: Management port -+ * @packet_len: Length of the packet to send. It does not include the final CRC -+ * @buffer: Packet data -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+enum cvmx_mgmt_port_result cvmx_mgmt_port_send(int port, int packet_len, -+ void *buffer) -+{ -+ struct cvmx_mgmt_port_state *state; -+ union cvmx_mixx_oring2 mix_oring2; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ /* Max sure the packet size is valid */ -+ if ((packet_len < 1) || (packet_len > CVMX_MGMT_PORT_TX_BUFFER_SIZE)) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ if (buffer == NULL) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ -+ mix_oring2.u64 = cvmx_read_csr(CVMX_MIXX_ORING2(port)); -+ if (mix_oring2.s.odbell >= CVMX_MGMT_PORT_NUM_TX_BUFFERS - 1) { -+ /* No room for another packet */ -+ cvmx_spinlock_unlock(&state->lock); -+ return CVMX_MGMT_PORT_NO_MEMORY; -+ } else { -+ /* Copy the packet into the output buffer */ -+ memcpy(state->tx_buffers[state->tx_write_index], buffer, -+ packet_len); -+ /* Insert the source MAC */ -+ memcpy(state->tx_buffers[state->tx_write_index] + 6, -+ ((char *)&state->mac) + 2, 6); -+ /* Update the TX ring buffer entry size */ -+ state->tx_ring[state->tx_write_index].s.len = packet_len; -+ /* Increment our TX index */ -+ state->tx_write_index = -+ (state->tx_write_index + 1) % CVMX_MGMT_PORT_NUM_TX_BUFFERS; -+ /* Ring the doorbell, send ing the packet */ -+ CVMX_SYNCWS; -+ cvmx_write_csr(CVMX_MIXX_ORING2(port), 1); -+ if (cvmx_read_csr(CVMX_MIXX_ORCNT(port))) -+ cvmx_write_csr(CVMX_MIXX_ORCNT(port), -+ cvmx_read_csr(CVMX_MIXX_ORCNT(port))); -+ -+ cvmx_spinlock_unlock(&state->lock); -+ return CVMX_MGMT_PORT_SUCCESS; -+ } -+} -+ -+/** -+ * Receive a packet from the management port. -+ * -+ * @port: Management port -+ * @buffer_len: Size of the buffer to receive the packet into -+ * @buffer: Buffer to receive the packet into -+ * -+ * Returns The size of the packet, or a negative erorr code on failure. Zero -+ * means that no packets were available. -+ */ -+int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer) -+{ -+ union cvmx_mixx_ircnt mix_ircnt; -+ struct cvmx_mgmt_port_state *state; -+ int result; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ /* Max sure the buffer size is valid */ -+ if (buffer_len < 1) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ if (buffer == NULL) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ -+ /* Find out how many RX packets are pending */ -+ mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port)); -+ if (mix_ircnt.s.ircnt) { -+ void *source = state->rx_buffers[state->rx_read_index]; -+ uint64_t *zero_check = source; -+ /* -+ * CN56XX pass 1 has an errata where packets might -+ * start 8 bytes into the buffer instead of at their -+ * correct location. If the first 8 bytes is zero we -+ * assume this has happened. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) -+ && (*zero_check == 0)) -+ source += 8; -+ /* Start off with zero bytes received */ -+ result = 0; -+ /* -+ * While the completion code signals more data, copy -+ * the buffers into the user's data. -+ */ -+ while (state->rx_ring[state->rx_read_index].s.code == 16) { -+ /* Only copy what will fit in the user's buffer */ -+ int length = state->rx_ring[state->rx_read_index].s.len; -+ if (length > buffer_len) -+ length = buffer_len; -+ memcpy(buffer, source, length); -+ /* -+ * Reduce the size of the buffer to the -+ * remaining space. If we run out we will -+ * signal an error when the code 15 buffer -+ * doesn't fit. -+ */ -+ buffer += length; -+ buffer_len -= length; -+ result += length; -+ /* -+ * Update this buffer for reuse in future -+ * receives. This size is -8 due to an errata -+ * for CN56XX pass 1. -+ */ -+ state->rx_ring[state->rx_read_index].s.code = 0; -+ state->rx_ring[state->rx_read_index].s.len = -+ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8; -+ state->rx_read_index = -+ (state->rx_read_index + -+ 1) % CVMX_MGMT_PORT_NUM_RX_BUFFERS; -+ /* -+ * Zero the beginning of the buffer for use by -+ * the errata check. -+ */ -+ *zero_check = 0; -+ CVMX_SYNCWS; -+ /* Increment the number of RX buffers */ -+ cvmx_write_csr(CVMX_MIXX_IRING2(port), 1); -+ source = state->rx_buffers[state->rx_read_index]; -+ zero_check = source; -+ } -+ -+ /* Check for the final good completion code */ -+ if (state->rx_ring[state->rx_read_index].s.code == 15) { -+ if (buffer_len >= -+ state->rx_ring[state->rx_read_index].s.len) { -+ int length = -+ state->rx_ring[state->rx_read_index].s.len; -+ memcpy(buffer, source, length); -+ result += length; -+ } else { -+ /* Not enough room for the packet */ -+ cvmx_dprintf("ERROR: cvmx_mgmt_port_receive: " -+ "Packet (%d) larger than " -+ "supplied buffer (%d)\n", -+ state->rx_ring[state->rx_read_index].s.len, -+ buffer_len); -+ result = CVMX_MGMT_PORT_NO_MEMORY; -+ } -+ } else { -+ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; -+ cvmx_dprintf("ERROR: cvmx_mgmt_port_receive: Receive " -+ "error code %d. Packet dropped(Len %d)\n", -+ state->rx_ring[state->rx_read_index].s.code, -+ state->rx_ring[state->rx_read_index].s.len + -+ result); -+ result = -state->rx_ring[state->rx_read_index].s.code; -+ -+ /* Check to see if we need to change the duplex. */ -+ agl_gmx_prtx.u64 = -+ cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); -+ if (cvmx_mgmt_port_get_link(port) < 0) -+ agl_gmx_prtx.s.duplex = 0; -+ else -+ agl_gmx_prtx.s.duplex = 1; -+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), -+ agl_gmx_prtx.u64); -+ } -+ -+ /* -+ * Clean out the ring buffer entry. This size is -8 -+ * due to an errata for CN56XX pass 1. -+ */ -+ state->rx_ring[state->rx_read_index].s.code = 0; -+ state->rx_ring[state->rx_read_index].s.len = -+ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8; -+ state->rx_read_index = -+ (state->rx_read_index + 1) % CVMX_MGMT_PORT_NUM_RX_BUFFERS; -+ /* -+ * Zero the beginning of the buffer for use by the -+ * errata check. -+ */ -+ *zero_check = 0; -+ CVMX_SYNCWS; -+ /* Increment the number of RX buffers */ -+ cvmx_write_csr(CVMX_MIXX_IRING2(port), 1); -+ /* Decrement the pending RX count */ -+ cvmx_write_csr(CVMX_MIXX_IRCNT(port), 1); -+ } else { -+ /* No packets available */ -+ result = 0; -+ } -+ cvmx_spinlock_unlock(&state->lock); -+ return result; -+} -+ -+/** -+ * Get the management port link status: -+ * 100 = 100Mbps, full duplex -+ * 10 = 10Mbps, full duplex -+ * 0 = Link down -+ * -10 = 10Mpbs, half duplex -+ * -100 = 100Mbps, half duplex -+ * -+ * @port: Management port -+ * -+ * Returns -+ */ -+int cvmx_mgmt_port_get_link(int port) -+{ -+ struct cvmx_mgmt_port_state *state; -+ int phy_status; -+ int duplex; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ /* Assume 100Mbps if we don't know the PHY address */ -+ if (state->phy_id == -1) -+ return 100; -+ -+ /* Read the PHY state */ -+ phy_status = -+ cvmx_mdio_read(state->phy_id >> 8, state->phy_id & 0xff, 17); -+ -+ /* Only return a link if the PHY has finished auto negotiation -+ and set the resolved bit (bit 11) */ -+ if (!(phy_status & (1 << 11))) -+ return 0; -+ -+ /* Create multiple factor to represent duplex */ -+ if ((phy_status >> 13) & 1) -+ duplex = 1; -+ else -+ duplex = -1; -+ -+ /* Speed is encoded on bits 15-14 */ -+ switch ((phy_status >> 14) & 3) { -+ case 0: /* 10 Mbps */ -+ return 10 * duplex; -+ case 1: /* 100 Mbps */ -+ return 100 * duplex; -+ default: -+ return 0; -+ } -+} -+ -+/** -+ * Set the MAC address for a management port -+ * -+ * @port: Management port -+ * @mac: New MAC address. The lower 6 bytes are used. -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+enum cvmx_mgmt_port_result cvmx_mgmt_port_set_mac(int port, uint64_t mac) -+{ -+ struct cvmx_mgmt_port_state *state; -+ union cvmx_agl_gmx_rxx_adr_ctl agl_gmx_rxx_adr_ctl; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ -+ agl_gmx_rxx_adr_ctl.u64 = 0; -+ /* Only accept matching MAC addresses */ -+ agl_gmx_rxx_adr_ctl.s.cam_mode = 1; -+ /* Drop multicast */ -+ agl_gmx_rxx_adr_ctl.s.mcst = 0; -+ /* Allow broadcast */ -+ agl_gmx_rxx_adr_ctl.s.bcst = 1; -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), agl_gmx_rxx_adr_ctl.u64); -+ -+ /* Only using one of the CAMs */ -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), (mac >> 40) & 0xff); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), (mac >> 32) & 0xff); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), (mac >> 24) & 0xff); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), (mac >> 16) & 0xff); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), (mac >> 8) & 0xff); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), (mac >> 0) & 0xff); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 1); -+ state->mac = mac; -+ -+ cvmx_spinlock_unlock(&state->lock); -+ return CVMX_MGMT_PORT_SUCCESS; -+} -+ -+/** -+ * Get the MAC address for a management port -+ * -+ * @port: Management port -+ * -+ * Returns MAC address -+ */ -+uint64_t cvmx_mgmt_port_get_mac(int port) -+{ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return CVMX_MGMT_PORT_INVALID_PARAM; -+ -+ return cvmx_mgmt_port_state_ptr[port].mac; -+} -+ -+/** -+ * Set the multicast list. -+ * -+ * @port: Management port -+ * @flags: Interface flags -+ * -+ * Returns -+ */ -+void cvmx_mgmt_port_set_multicast_list(int port, int flags) -+{ -+ struct cvmx_mgmt_port_state *state; -+ union cvmx_agl_gmx_rxx_adr_ctl agl_gmx_rxx_adr_ctl; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ -+ agl_gmx_rxx_adr_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port)); -+ -+ /* Allow broadcast MAC addresses */ -+ if (!agl_gmx_rxx_adr_ctl.s.bcst) -+ agl_gmx_rxx_adr_ctl.s.bcst = 1; -+ -+ if ((flags & CVMX_IFF_ALLMULTI) || (flags & CVMX_IFF_PROMISC)) -+ /* Force accept multicast packets */ -+ agl_gmx_rxx_adr_ctl.s.mcst = 2; -+ else -+ /* Force reject multicast packets */ -+ agl_gmx_rxx_adr_ctl.s.mcst = 1; -+ -+ if (flags & CVMX_IFF_PROMISC) -+ /* -+ * Reject matches if promisc. Since CAM is shut off, -+ * should accept everything. -+ */ -+ agl_gmx_rxx_adr_ctl.s.cam_mode = 0; -+ else -+ /* Filter packets based on the CAM */ -+ agl_gmx_rxx_adr_ctl.s.cam_mode = 1; -+ -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), agl_gmx_rxx_adr_ctl.u64); -+ -+ if (flags & CVMX_IFF_PROMISC) -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 0); -+ else -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 1); -+ -+ cvmx_spinlock_unlock(&state->lock); -+} -+ -+/** -+ * Set the maximum packet allowed in. Size is specified -+ * including L2 but without FCS. A normal MTU would corespond -+ * to 1514 assuming the standard 14 byte L2 header. -+ * -+ * @port: Management port -+ * @size_without_fcs: -+ * Size in bytes without FCS -+ */ -+void cvmx_mgmt_port_set_max_packet_size(int port, int size_without_fcs) -+{ -+ struct cvmx_mgmt_port_state *state; -+ -+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports())) -+ return; -+ -+ state = cvmx_mgmt_port_state_ptr + port; -+ -+ cvmx_spinlock_lock(&state->lock); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs); -+ cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port), -+ (size_without_fcs + 7) & 0xfff8); -+ cvmx_spinlock_unlock(&state->lock); -+} ---- /dev/null -+++ b/drivers/net/octeon/cvmx-mgmt-port.h -@@ -0,0 +1,168 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Support functions for managing the MII management port -+ * -+ */ -+ -+#ifndef __CVMX_MGMT_PORT_H__ -+#define __CVMX_MGMT_PORT_H__ -+ -+enum cvmx_mgmt_port_result { -+ CVMX_MGMT_PORT_SUCCESS = 0, -+ CVMX_MGMT_PORT_NO_MEMORY = -1, -+ CVMX_MGMT_PORT_INVALID_PARAM = -2, -+}; -+ -+/* Enumeration of Net Device interface flags. */ -+enum cvmx_mgmt_port_netdevice_flags { -+ CVMX_IFF_PROMISC = 0x100, /* receive all packets */ -+ CVMX_IFF_ALLMULTI = 0x200, /* receive all multicast packets */ -+}; -+ -+/** -+ * Called to initialize a management port for use. Multiple calls -+ * to this function accross applications is safe. -+ * -+ * @port: Port to initialize -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_initialize(int port); -+ -+/** -+ * Shutdown a management port. This currently disables packet IO -+ * but leaves all hardware and buffers. Another application can then -+ * call initialize() without redoing the hardware setup. -+ * -+ * @port: Management port -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_shutdown(int port); -+ -+/** -+ * Enable packet IO on a management port -+ * -+ * @port: Management port -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_enable(int port); -+ -+/** -+ * Disable packet IO on a management port -+ * -+ * @port: Management port -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_disable(int port); -+ -+/** -+ * Send a packet out the management port. The packet is copied so -+ * the input buffer isn't used after this call. -+ * -+ * @port: Management port -+ * @packet_len: Length of the packet to send. It does not include the final CRC -+ * @buffer: Packet data -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_send(int port, int packet_len, -+ void *buffer); -+ -+/** -+ * Receive a packet from the management port. -+ * -+ * @port: Management port -+ * @buffer_len: Size of the buffer to receive the packet into -+ * @buffer: Buffer to receive the packet into -+ * -+ * Returns The size of the packet, or a negative erorr code on failure. Zero -+ * means that no packets were available. -+ */ -+extern int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer); -+ -+/** -+ * Get the management port link status: -+ * 100 = 100Mbps, full duplex -+ * 10 = 10Mbps, full duplex -+ * 0 = Link down -+ * -10 = 10Mpbs, half duplex -+ * -100 = 100Mbps, half duplex -+ * -+ * @port: Management port -+ * -+ * Returns -+ */ -+extern int cvmx_mgmt_port_get_link(int port); -+ -+/** -+ * Set the MAC address for a management port -+ * -+ * @port: Management port -+ * @mac: New MAC address. The lower 6 bytes are used. -+ * -+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code -+ */ -+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_set_mac(int port, -+ uint64_t mac); -+ -+/** -+ * Get the MAC address for a management port -+ * -+ * @port: Management port -+ * -+ * Returns MAC address -+ */ -+extern uint64_t cvmx_mgmt_port_get_mac(int port); -+ -+/** -+ * Set the multicast list. -+ * -+ * @port: Management port -+ * @flags: Interface flags -+ * -+ * Returns -+ */ -+extern void cvmx_mgmt_port_set_multicast_list(int port, int flags); -+ -+/** -+ * Set the maximum packet allowed in. Size is specified -+ * including L2 but without FCS. A normal MTU would corespond -+ * to 1514 assuming the standard 14 byte L2 header. -+ * -+ * @port: Management port -+ * @size_without_crc: -+ * Size in bytes without FCS -+ */ -+extern void cvmx_mgmt_port_set_max_packet_size(int port, int size_without_fcs); -+ -+#endif /* __CVMX_MGMT_PORT_H__ */ ---- /dev/null -+++ b/drivers/net/octeon/octeon-mgmt-port.c -@@ -0,0 +1,389 @@ -+/* -+ * Octeon Management Port Ethernet Driver -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2007, 2008 Cavium Networks -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "cvmx-mgmt-port.h" -+ -+static struct net_device *global_dev[2] = { NULL, NULL }; -+ -+#define DEBUGPRINT(format, ...) do {if (printk_ratelimit()) \ -+ printk(format, ##__VA_ARGS__); \ -+ } while (0) -+ -+/** -+ * This is the definition of the Ethernet driver's private -+ * driver state stored in dev->priv. -+ */ -+struct device_private { -+ int port; -+ struct net_device_stats stats; /* Device statistics */ -+}; -+ -+ -+/** -+ * Packet transmit -+ * -+ * @param skb Packet to send -+ * @param dev Device info structure -+ * @return Always returns zero -+ */ -+static int packet_transmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ uint64_t flags; -+ struct device_private *priv = netdev_priv(dev); -+ enum cvmx_mgmt_port_result result; -+ local_irq_save(flags); -+ result = cvmx_mgmt_port_send(priv->port, skb->len, skb->data); -+ local_irq_restore(flags); -+ if (result == CVMX_MGMT_PORT_SUCCESS) { -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += skb->len; -+ } else { -+ /* DEBUGPRINT("ERROR: cvmx_mgmt_port_send() failed with %d\n", -+ result); -+ */ -+ priv->stats.tx_dropped++; -+ } -+ dev_kfree_skb(skb); -+ return 0; -+} -+ -+ -+/** -+ * Interrupt handler. The interrupt occurs whenever the POW -+ * transitions from 0->1 packets in our group. -+ * -+ * @param cpl -+ * @param dev_id -+ * @param regs -+ * @return -+ */ -+static irqreturn_t do_interrupt(int cpl, void *dev_id) -+{ -+ uint64_t flags; -+ struct sk_buff *skb; -+ int result; -+ char packet[2048]; -+ struct net_device *dev = (struct net_device *) dev_id; -+ struct device_private *priv = netdev_priv(dev); -+ -+ do { -+ local_irq_save(flags); -+ result = cvmx_mgmt_port_receive(priv->port, sizeof(packet), -+ packet); -+ local_irq_restore(flags); -+ -+ /* Silently drop packets if we aren't up */ -+ if ((dev->flags & IFF_UP) == 0) -+ continue; -+ -+ if (result > 0) { -+ skb = dev_alloc_skb(result); -+ if (skb) { -+ memcpy(skb_put(skb, result), packet, result); -+ skb->protocol = eth_type_trans(skb, dev); -+ skb->dev = dev; -+ skb->ip_summed = CHECKSUM_NONE; -+ priv->stats.rx_bytes += skb->len; -+ priv->stats.rx_packets++; -+ netif_rx(skb); -+ } else { -+ DEBUGPRINT("%s: Failed to allocate skbuff, " -+ "packet dropped\n", -+ dev->name); -+ priv->stats.rx_dropped++; -+ } -+ } else if (result < 0) { -+ DEBUGPRINT("%s: Receive error code %d, packet " -+ "dropped\n", -+ dev->name, result); -+ priv->stats.rx_errors++; -+ } -+ } while (result != 0); -+ -+ /* Clear any pending interrupts */ -+ cvmx_write_csr(CVMX_MIXX_ISR(priv->port), -+ cvmx_read_csr(CVMX_MIXX_ISR(priv->port))); -+ cvmx_read_csr(CVMX_MIXX_ISR(priv->port)); -+ -+ return IRQ_HANDLED; -+} -+ -+ -+#ifdef CONFIG_NET_POLL_CONTROLLER -+/** -+ * This is called when the kernel needs to manually poll the -+ * device. For Octeon, this is simply calling the interrupt -+ * handler. We actually poll all the devices, not just the -+ * one supplied. -+ * -+ * @param dev Device to poll. Unused -+ */ -+static void device_poll_controller(struct net_device *dev) -+{ -+ do_interrupt(0, dev); -+} -+#endif -+ -+ -+/** -+ * Open a device for use. Device should be able to send and -+ * receive packets after this is called. -+ * -+ * @param dev Device to bring up -+ * @return Zero on success -+ */ -+static int device_open(struct net_device *dev) -+{ -+ /* Clear the statistics whenever the interface is brought up */ -+ struct device_private *priv = netdev_priv(dev); -+ memset(&priv->stats, 0, sizeof(priv->stats)); -+ cvmx_mgmt_port_enable(priv->port); -+ return 0; -+} -+ -+ -+/** -+ * Stop an ethernet device. No more packets should be -+ * received from this device. -+ * -+ * @param dev Device to bring down -+ * @return Zero on success -+ */ -+static int device_close(struct net_device *dev) -+{ -+ struct device_private *priv = netdev_priv(dev); -+ cvmx_mgmt_port_disable(priv->port); -+ return 0; -+} -+ -+ -+/** -+ * Get the low level ethernet statistics -+ * -+ * @param dev Device to get the statistics from -+ * @return Pointer to the statistics -+ */ -+static struct net_device_stats *device_get_stats(struct net_device *dev) -+{ -+ struct device_private *priv = netdev_priv(dev); -+ return &priv->stats; -+} -+ -+/** -+ * Set the multicast list. Currently unimplemented. -+ * -+ * @param dev Device to work on -+ */ -+static void ethernet_mgmt_port_set_multicast_list(struct net_device *dev) -+{ -+ struct device_private *priv = netdev_priv(dev); -+ int port = priv->port; -+ int num_ports; -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ num_ports = 2; -+ else -+ num_ports = 1; -+ if (port < num_ports) -+ cvmx_mgmt_port_set_multicast_list(port, dev->flags); -+} -+ -+/** -+ * Set the hardware MAC address for a management port device -+ * -+ * @param dev Device to change the MAC address for -+ * @param addr Address structure to change it too. MAC address is addr + 2. -+ * @return Zero on success -+ */ -+static int ethernet_mgmt_port_set_mac_address(struct net_device *dev, -+ void *addr) -+{ -+ struct device_private *priv = netdev_priv(dev); -+ union cvmx_agl_gmx_prtx_cfg agl_gmx_cfg; -+ int port = priv->port; -+ int num_ports; -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ num_ports = 2; -+ else -+ num_ports = 1; -+ -+ memcpy(dev->dev_addr, addr + 2, 6); -+ -+ if (port < num_ports) { -+ int i; -+ uint8_t *ptr = addr; -+ uint64_t mac = 0; -+ for (i = 0; i < 6; i++) -+ mac = (mac<<8) | (uint64_t)(ptr[i+2]); -+ -+ agl_gmx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); -+ cvmx_mgmt_port_set_mac(port, mac); -+ ethernet_mgmt_port_set_multicast_list(dev); -+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_cfg.u64); -+ } -+ return 0; -+} -+ -+/** -+ * Per network device initialization -+ * -+ * @param dev Device to initialize -+ * @return Zero on success -+ */ -+static int device_init(struct net_device *dev) -+{ -+ struct device_private *priv = netdev_priv(dev); -+ uint64_t mac = cvmx_mgmt_port_get_mac(priv->port); -+ -+ dev->hard_start_xmit = packet_transmit; -+ dev->get_stats = device_get_stats; -+ dev->open = device_open; -+ dev->stop = device_close; -+#ifdef CONFIG_NET_POLL_CONTROLLER -+ dev->poll_controller = device_poll_controller; -+#endif -+ dev->dev_addr[0] = (mac >> 40) & 0xff; -+ dev->dev_addr[1] = (mac >> 32) & 0xff; -+ dev->dev_addr[2] = (mac >> 24) & 0xff; -+ dev->dev_addr[3] = (mac >> 16) & 0xff; -+ dev->dev_addr[4] = (mac >> 8) & 0xff; -+ dev->dev_addr[5] = (mac >> 0) & 0xff; -+ return 0; -+} -+ -+ -+/** -+ * Module/ driver initialization. Creates the linux network -+ * devices. -+ * -+ * @return Zero on success -+ */ -+static int __init ethernet_mgmt_port_init(void) -+{ -+ struct net_device *dev; -+ struct device_private *priv; -+ union cvmx_mixx_irhwm mix_irhwm; -+ union cvmx_mixx_intena mix_intena; -+ int num_ports; -+ int port; -+ -+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ return 0; -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ num_ports = 2; -+ else -+ num_ports = 1; -+ -+ printk("Octeon management port ethernet driver\n"); -+ -+ for (port = 0; port < num_ports; port++) { -+ if (cvmx_mgmt_port_initialize(port) != CVMX_MGMT_PORT_SUCCESS) { -+ pr_err("ERROR: cvmx_mgmt_port_initialize(%d) " -+ "failed\n", port); -+ return -1; -+ } -+ -+ /* Setup is complete, create the virtual ethernet devices */ -+ dev = alloc_etherdev(sizeof(struct device_private)); -+ if (dev == NULL) { -+ pr_err("ERROR: Failed to allocate ethernet device\n"); -+ return -1; -+ } -+ -+ dev->init = device_init; -+ strcpy(dev->name, "mgmt%d"); -+ -+ /* Initialize the device private structure. */ -+ priv = netdev_priv(dev); -+ memset(priv, 0, sizeof(struct device_private)); -+ priv->port = port; -+ -+ if (register_netdev(dev) < 0) { -+ pr_err("ERROR: Failed to register ethernet device\n"); -+ kfree(dev); -+ return -1; -+ } -+ -+ /* Clear any pending interrupts */ -+ cvmx_write_csr(CVMX_MIXX_ISR(priv->port), -+ cvmx_read_csr(CVMX_MIXX_ISR(priv->port))); -+ -+ /* Register an IRQ hander for to receive interrupts */ -+ dev->irq = -+ (priv->port == 0) ? OCTEON_IRQ_MII0 : OCTEON_IRQ_MII1; -+ if (request_irq(dev->irq, do_interrupt, IRQF_SHARED, dev->name, -+ dev)) -+ pr_err("ethernet-mgmt: Failed to assign " -+ "interrupt %d\n", dev->irq); -+ -+ /* Interrupt every single RX packet */ -+ mix_irhwm.u64 = 0; -+ mix_irhwm.s.irhwm = 0; -+ cvmx_write_csr(CVMX_MIXX_IRHWM(priv->port), mix_irhwm.u64); -+ -+ /* Enable receive interrupts */ -+ mix_intena.u64 = 0; -+ mix_intena.s.ithena = 1; -+ cvmx_write_csr(CVMX_MIXX_INTENA(priv->port), mix_intena.u64); -+ -+ global_dev[priv->port] = dev; -+ -+ dev->set_mac_address = ethernet_mgmt_port_set_mac_address; -+ dev->set_multicast_list = ethernet_mgmt_port_set_multicast_list; -+ } -+ return 0; -+} -+ -+ -+/** -+ * Module / driver shutdown -+ * -+ * @return Zero on success -+ */ -+static void __exit ethernet_mgmt_port_cleanup(void) -+{ -+ int port; -+ for (port = 0; port < 2; port++) { -+ if (global_dev[port]) { -+ struct device_private *priv = -+ netdev_priv(global_dev[port]); -+ /* Disable interrupt */ -+ cvmx_write_csr(CVMX_MIXX_IRHWM(priv->port), 0); -+ cvmx_write_csr(CVMX_MIXX_INTENA(priv->port), 0); -+ cvmx_mgmt_port_shutdown(priv->port); -+ -+ /* Free the interrupt handler */ -+ free_irq(global_dev[port]->irq, global_dev[port]); -+ -+ /* Free the ethernet devices */ -+ unregister_netdev(global_dev[port]); -+ kfree(global_dev[port]); -+ global_dev[port] = NULL; -+ } -+ } -+} -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Cavium Networks "); -+MODULE_DESCRIPTION("Cavium Networks Octeon management port ethernet driver."); -+module_init(ethernet_mgmt_port_init); -+module_exit(ethernet_mgmt_port_cleanup); diff --git a/target/linux/octeon/patches/007-export_cvmx_sysinfo.patch b/target/linux/octeon/patches/007-export_cvmx_sysinfo.patch deleted file mode 100644 index 318916d15b..0000000000 --- a/target/linux/octeon/patches/007-export_cvmx_sysinfo.patch +++ /dev/null @@ -1,23 +0,0 @@ -Signed-off-by: David Daney ---- - arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - ---- a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c -+++ b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c -@@ -29,6 +29,7 @@ - * This module provides system/board/application information obtained - * by the bootloader. - */ -+#include - - #include - #include -@@ -69,6 +70,7 @@ struct cvmx_sysinfo *cvmx_sysinfo_get(vo - { - return &(state.sysinfo); - } -+EXPORT_SYMBOL(cvmx_sysinfo_get); - - /** - * This function is used in non-simple executive environments (such as diff --git a/target/linux/octeon/patches/008-more_board_types_constraints.patch b/target/linux/octeon/patches/008-more_board_types_constraints.patch deleted file mode 100644 index bb375852ff..0000000000 --- a/target/linux/octeon/patches/008-more_board_types_constraints.patch +++ /dev/null @@ -1,37 +0,0 @@ -The bootloader now uses additional board type constants. The -octeon-ethernet driver needs some of the new values. - -Signed-off-by: David Daney ---- - arch/mips/include/asm/octeon/cvmx-bootinfo.h | 13 +++++++++++++ - 1 files changed, 13 insertions(+), 0 deletions(-) - ---- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h -+++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h -@@ -157,6 +157,13 @@ enum cvmx_board_types_enum { - CVMX_BOARD_TYPE_NIC_XLE_4G = 21, - CVMX_BOARD_TYPE_EBT5600 = 22, - CVMX_BOARD_TYPE_EBH5201 = 23, -+ CVMX_BOARD_TYPE_EBT5200 = 24, -+ CVMX_BOARD_TYPE_CB5600 = 25, -+ CVMX_BOARD_TYPE_CB5601 = 26, -+ CVMX_BOARD_TYPE_CB5200 = 27, -+ /* Special 'generic' board type, supports many boards */ -+ CVMX_BOARD_TYPE_GENERIC = 28, -+ CVMX_BOARD_TYPE_EBH5610 = 29, - CVMX_BOARD_TYPE_MAX, - - /* -@@ -228,6 +235,12 @@ static inline const char *cvmx_board_typ - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G) - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600) - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201) -+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5200) -+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5600) -+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5601) -+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5200) -+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC) -+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5610) - ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX) - - /* Customer boards listed here */ diff --git a/target/linux/octeon/patches/009-more_chip_specific_feature_tests.patch b/target/linux/octeon/patches/009-more_chip_specific_feature_tests.patch deleted file mode 100644 index 63dc4f13de..0000000000 --- a/target/linux/octeon/patches/009-more_chip_specific_feature_tests.patch +++ /dev/null @@ -1,51 +0,0 @@ -The octeon-ethernet driver needs to check for additional chip specific -features, we add them to the octeon_has_feature() framework. - -Signed-off-by: David Daney ---- - arch/mips/include/asm/octeon/octeon-feature.h | 27 +++++++++++++++++++++++++ - 1 files changed, 27 insertions(+), 0 deletions(-) - ---- a/arch/mips/include/asm/octeon/octeon-feature.h -+++ b/arch/mips/include/asm/octeon/octeon-feature.h -@@ -57,6 +57,13 @@ enum octeon_feature { - OCTEON_FEATURE_RAID, - /* Octeon has a builtin USB */ - OCTEON_FEATURE_USB, -+ /* Octeon IPD can run without using work queue entries */ -+ OCTEON_FEATURE_NO_WPTR, -+ /* Octeon has DFA state machines */ -+ OCTEON_FEATURE_DFA, -+ /* Octeon MDIO block supports clause 45 transactions for 10 -+ * Gig support */ -+ OCTEON_FEATURE_MDIO_CLAUSE_45, - }; - - static inline int cvmx_fuse_read(int fuse); -@@ -112,6 +119,26 @@ static inline int octeon_has_feature(enu - case OCTEON_FEATURE_USB: - return !(OCTEON_IS_MODEL(OCTEON_CN38XX) - || OCTEON_IS_MODEL(OCTEON_CN58XX)); -+ case OCTEON_FEATURE_NO_WPTR: -+ return (OCTEON_IS_MODEL(OCTEON_CN56XX) -+ || OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) -+ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X); -+ case OCTEON_FEATURE_DFA: -+ if (!OCTEON_IS_MODEL(OCTEON_CN38XX) -+ && !OCTEON_IS_MODEL(OCTEON_CN31XX) -+ && !OCTEON_IS_MODEL(OCTEON_CN58XX)) -+ return 0; -+ else if (OCTEON_IS_MODEL(OCTEON_CN3020)) -+ return 0; -+ else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) -+ return 1; -+ else -+ return !cvmx_fuse_read(120); -+ case OCTEON_FEATURE_MDIO_CLAUSE_45: -+ return !(OCTEON_IS_MODEL(OCTEON_CN3XXX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)); - } - return 0; - } diff --git a/target/linux/octeon/patches/010-export_erratum_function.patch b/target/linux/octeon/patches/010-export_erratum_function.patch deleted file mode 100644 index 83b09fbede..0000000000 --- a/target/linux/octeon/patches/010-export_erratum_function.patch +++ /dev/null @@ -1,21 +0,0 @@ -Signed-off-by: David Daney ---- - .../cavium-octeon/executive/cvmx-helper-errata.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - ---- a/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c -+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c -@@ -33,6 +33,8 @@ - * these functions directly. - * - */ -+#include -+ - #include - - #include -@@ -377,3 +379,4 @@ void __cvmx_helper_errata_qlm_disable_2n - } - cvmx_helper_qlm_jtag_update(qlm); - } -+EXPORT_SYMBOL(__cvmx_helper_errata_qlm_disable_2nd_order_cdr); diff --git a/target/linux/octeon/patches/011-octeon_ethernet_driver.patch b/target/linux/octeon/patches/011-octeon_ethernet_driver.patch deleted file mode 100644 index dec15866b0..0000000000 --- a/target/linux/octeon/patches/011-octeon_ethernet_driver.patch +++ /dev/null @@ -1,26533 +0,0 @@ -The octeon-ethernet driver supports the sgmii, rgmii, spi, and xaui -ports present on the Cavium OCTEON family of SOCs. These SOCs are -multi-core mips64 processors with existing support over in arch/mips. - -The driver files can be categorized into three basic groups: - -1) Register definitions, these are named cvmx-*-defs.h - -2) Main driver code, these have names that don't start cvmx-. - -3) Interface specific functions and other utility code, names starting -with cvmx- - -Signed-off-by: David Daney ---- - drivers/staging/octeon/Kconfig | 12 + - drivers/staging/octeon/Makefile | 30 + - drivers/staging/octeon/cvmx-address.h | 274 +++ - drivers/staging/octeon/cvmx-asxx-defs.h | 475 +++++ - drivers/staging/octeon/cvmx-cmd-queue.c | 306 +++ - drivers/staging/octeon/cvmx-cmd-queue.h | 617 ++++++ - drivers/staging/octeon/cvmx-config.h | 169 ++ - drivers/staging/octeon/cvmx-dbg-defs.h | 72 + - drivers/staging/octeon/cvmx-fau.h | 597 ++++++ - drivers/staging/octeon/cvmx-fpa-defs.h | 403 ++++ - drivers/staging/octeon/cvmx-fpa.c | 183 ++ - drivers/staging/octeon/cvmx-fpa.h | 299 +++ - drivers/staging/octeon/cvmx-gmxx-defs.h | 2529 +++++++++++++++++++++++ - drivers/staging/octeon/cvmx-helper-board.c | 706 +++++++ - drivers/staging/octeon/cvmx-helper-board.h | 180 ++ - drivers/staging/octeon/cvmx-helper-fpa.c | 243 +++ - drivers/staging/octeon/cvmx-helper-fpa.h | 64 + - drivers/staging/octeon/cvmx-helper-loop.c | 85 + - drivers/staging/octeon/cvmx-helper-loop.h | 59 + - drivers/staging/octeon/cvmx-helper-npi.c | 113 + - drivers/staging/octeon/cvmx-helper-npi.h | 60 + - drivers/staging/octeon/cvmx-helper-rgmii.c | 525 +++++ - drivers/staging/octeon/cvmx-helper-rgmii.h | 110 + - drivers/staging/octeon/cvmx-helper-sgmii.c | 550 +++++ - drivers/staging/octeon/cvmx-helper-sgmii.h | 104 + - drivers/staging/octeon/cvmx-helper-spi.c | 195 ++ - drivers/staging/octeon/cvmx-helper-spi.h | 84 + - drivers/staging/octeon/cvmx-helper-util.c | 433 ++++ - drivers/staging/octeon/cvmx-helper-util.h | 215 ++ - drivers/staging/octeon/cvmx-helper-xaui.c | 348 ++++ - drivers/staging/octeon/cvmx-helper-xaui.h | 103 + - drivers/staging/octeon/cvmx-helper.c | 1058 ++++++++++ - drivers/staging/octeon/cvmx-helper.h | 227 ++ - drivers/staging/octeon/cvmx-interrupt-decodes.c | 371 ++++ - drivers/staging/octeon/cvmx-interrupt-rsl.c | 140 ++ - drivers/staging/octeon/cvmx-ipd.h | 338 +++ - drivers/staging/octeon/cvmx-mdio.h | 506 +++++ - drivers/staging/octeon/cvmx-packet.h | 65 + - drivers/staging/octeon/cvmx-pcsx-defs.h | 370 ++++ - drivers/staging/octeon/cvmx-pcsxx-defs.h | 316 +++ - drivers/staging/octeon/cvmx-pip-defs.h | 1267 ++++++++++++ - drivers/staging/octeon/cvmx-pip.h | 524 +++++ - drivers/staging/octeon/cvmx-pko-defs.h | 1133 ++++++++++ - drivers/staging/octeon/cvmx-pko.c | 506 +++++ - drivers/staging/octeon/cvmx-pko.h | 610 ++++++ - drivers/staging/octeon/cvmx-pow.h | 1982 ++++++++++++++++++ - drivers/staging/octeon/cvmx-scratch.h | 139 ++ - drivers/staging/octeon/cvmx-smix-defs.h | 178 ++ - drivers/staging/octeon/cvmx-spi.c | 667 ++++++ - drivers/staging/octeon/cvmx-spi.h | 269 +++ - drivers/staging/octeon/cvmx-spxx-defs.h | 347 ++++ - drivers/staging/octeon/cvmx-srxx-defs.h | 126 ++ - drivers/staging/octeon/cvmx-stxx-defs.h | 292 +++ - drivers/staging/octeon/cvmx-wqe.h | 397 ++++ - drivers/staging/octeon/ethernet-common.c | 328 +++ - drivers/staging/octeon/ethernet-common.h | 29 + - drivers/staging/octeon/ethernet-defines.h | 134 ++ - drivers/staging/octeon/ethernet-mdio.c | 231 +++ - drivers/staging/octeon/ethernet-mdio.h | 46 + - drivers/staging/octeon/ethernet-mem.c | 198 ++ - drivers/staging/octeon/ethernet-mem.h | 29 + - drivers/staging/octeon/ethernet-proc.c | 256 +++ - drivers/staging/octeon/ethernet-proc.h | 29 + - drivers/staging/octeon/ethernet-rgmii.c | 397 ++++ - drivers/staging/octeon/ethernet-rx.c | 505 +++++ - drivers/staging/octeon/ethernet-rx.h | 33 + - drivers/staging/octeon/ethernet-sgmii.c | 129 ++ - drivers/staging/octeon/ethernet-spi.c | 323 +++ - drivers/staging/octeon/ethernet-tx.c | 634 ++++++ - drivers/staging/octeon/ethernet-tx.h | 32 + - drivers/staging/octeon/ethernet-util.h | 81 + - drivers/staging/octeon/ethernet-xaui.c | 127 ++ - drivers/staging/octeon/ethernet.c | 507 +++++ - drivers/staging/octeon/octeon-ethernet.h | 127 ++ - 74 files changed, 26146 insertions(+), 0 deletions(-) - create mode 100644 drivers/staging/octeon/Kconfig - create mode 100644 drivers/staging/octeon/Makefile - create mode 100644 drivers/staging/octeon/cvmx-address.h - create mode 100644 drivers/staging/octeon/cvmx-asxx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-cmd-queue.c - create mode 100644 drivers/staging/octeon/cvmx-cmd-queue.h - create mode 100644 drivers/staging/octeon/cvmx-config.h - create mode 100644 drivers/staging/octeon/cvmx-dbg-defs.h - create mode 100644 drivers/staging/octeon/cvmx-fau.h - create mode 100644 drivers/staging/octeon/cvmx-fpa-defs.h - create mode 100644 drivers/staging/octeon/cvmx-fpa.c - create mode 100644 drivers/staging/octeon/cvmx-fpa.h - create mode 100644 drivers/staging/octeon/cvmx-gmxx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-helper-board.c - create mode 100644 drivers/staging/octeon/cvmx-helper-board.h - create mode 100644 drivers/staging/octeon/cvmx-helper-fpa.c - create mode 100644 drivers/staging/octeon/cvmx-helper-fpa.h - create mode 100644 drivers/staging/octeon/cvmx-helper-loop.c - create mode 100644 drivers/staging/octeon/cvmx-helper-loop.h - create mode 100644 drivers/staging/octeon/cvmx-helper-npi.c - create mode 100644 drivers/staging/octeon/cvmx-helper-npi.h - create mode 100644 drivers/staging/octeon/cvmx-helper-rgmii.c - create mode 100644 drivers/staging/octeon/cvmx-helper-rgmii.h - create mode 100644 drivers/staging/octeon/cvmx-helper-sgmii.c - create mode 100644 drivers/staging/octeon/cvmx-helper-sgmii.h - create mode 100644 drivers/staging/octeon/cvmx-helper-spi.c - create mode 100644 drivers/staging/octeon/cvmx-helper-spi.h - create mode 100644 drivers/staging/octeon/cvmx-helper-util.c - create mode 100644 drivers/staging/octeon/cvmx-helper-util.h - create mode 100644 drivers/staging/octeon/cvmx-helper-xaui.c - create mode 100644 drivers/staging/octeon/cvmx-helper-xaui.h - create mode 100644 drivers/staging/octeon/cvmx-helper.c - create mode 100644 drivers/staging/octeon/cvmx-helper.h - create mode 100644 drivers/staging/octeon/cvmx-interrupt-decodes.c - create mode 100644 drivers/staging/octeon/cvmx-interrupt-rsl.c - create mode 100644 drivers/staging/octeon/cvmx-ipd.h - create mode 100644 drivers/staging/octeon/cvmx-mdio.h - create mode 100644 drivers/staging/octeon/cvmx-packet.h - create mode 100644 drivers/staging/octeon/cvmx-pcsx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-pcsxx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-pip-defs.h - create mode 100644 drivers/staging/octeon/cvmx-pip.h - create mode 100644 drivers/staging/octeon/cvmx-pko-defs.h - create mode 100644 drivers/staging/octeon/cvmx-pko.c - create mode 100644 drivers/staging/octeon/cvmx-pko.h - create mode 100644 drivers/staging/octeon/cvmx-pow.h - create mode 100644 drivers/staging/octeon/cvmx-scratch.h - create mode 100644 drivers/staging/octeon/cvmx-smix-defs.h - create mode 100644 drivers/staging/octeon/cvmx-spi.c - create mode 100644 drivers/staging/octeon/cvmx-spi.h - create mode 100644 drivers/staging/octeon/cvmx-spxx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-srxx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-stxx-defs.h - create mode 100644 drivers/staging/octeon/cvmx-wqe.h - create mode 100644 drivers/staging/octeon/ethernet-common.c - create mode 100644 drivers/staging/octeon/ethernet-common.h - create mode 100644 drivers/staging/octeon/ethernet-defines.h - create mode 100644 drivers/staging/octeon/ethernet-mdio.c - create mode 100644 drivers/staging/octeon/ethernet-mdio.h - create mode 100644 drivers/staging/octeon/ethernet-mem.c - create mode 100644 drivers/staging/octeon/ethernet-mem.h - create mode 100644 drivers/staging/octeon/ethernet-proc.c - create mode 100644 drivers/staging/octeon/ethernet-proc.h - create mode 100644 drivers/staging/octeon/ethernet-rgmii.c - create mode 100644 drivers/staging/octeon/ethernet-rx.c - create mode 100644 drivers/staging/octeon/ethernet-rx.h - create mode 100644 drivers/staging/octeon/ethernet-sgmii.c - create mode 100644 drivers/staging/octeon/ethernet-spi.c - create mode 100644 drivers/staging/octeon/ethernet-tx.c - create mode 100644 drivers/staging/octeon/ethernet-tx.h - create mode 100644 drivers/staging/octeon/ethernet-util.h - create mode 100644 drivers/staging/octeon/ethernet-xaui.c - create mode 100644 drivers/staging/octeon/ethernet.c - create mode 100644 drivers/staging/octeon/octeon-ethernet.h - ---- /dev/null -+++ b/drivers/staging/octeon/Kconfig -@@ -0,0 +1,12 @@ -+config OCTEON_ETHERNET -+ tristate "Cavium Networks Octeon Ethernet support" -+ depends on CPU_CAVIUM_OCTEON -+ select MII -+ help -+ This driver supports the builtin ethernet ports on Cavium -+ Networks' products in the Octeon family. This driver supports the -+ CN3XXX and CN5XXX Octeon processors. -+ -+ To compile this driver as a module, choose M here. The module -+ will be called octeon-ethernet. -+ ---- /dev/null -+++ b/drivers/staging/octeon/Makefile -@@ -0,0 +1,30 @@ -+# This file is subject to the terms and conditions of the GNU General Public -+# License. See the file "COPYING" in the main directory of this archive -+# for more details. -+# -+# Copyright (C) 2005-2009 Cavium Networks -+# -+ -+# -+# Makefile for Cavium OCTEON on-board ethernet driver -+# -+ -+obj-${CONFIG_OCTEON_ETHERNET} := octeon-ethernet.o -+ -+octeon-ethernet-objs := ethernet.o -+octeon-ethernet-objs += ethernet-common.o -+octeon-ethernet-objs += ethernet-mdio.o -+octeon-ethernet-objs += ethernet-mem.o -+octeon-ethernet-objs += ethernet-proc.o -+octeon-ethernet-objs += ethernet-rgmii.o -+octeon-ethernet-objs += ethernet-rx.o -+octeon-ethernet-objs += ethernet-sgmii.o -+octeon-ethernet-objs += ethernet-spi.o -+octeon-ethernet-objs += ethernet-tx.o -+octeon-ethernet-objs += ethernet-xaui.o -+octeon-ethernet-objs += cvmx-pko.o cvmx-spi.o cvmx-cmd-queue.o \ -+ cvmx-helper-board.o cvmx-helper.o cvmx-helper-xaui.o \ -+ cvmx-helper-rgmii.o cvmx-helper-sgmii.o cvmx-helper-npi.o \ -+ cvmx-helper-loop.o cvmx-helper-spi.o cvmx-helper-util.o \ -+ cvmx-interrupt-decodes.o cvmx-interrupt-rsl.o -+ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-address.h -@@ -0,0 +1,274 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2009 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * Typedefs and defines for working with Octeon physical addresses. -+ * -+ */ -+#ifndef __CVMX_ADDRESS_H__ -+#define __CVMX_ADDRESS_H__ -+ -+#if 0 -+typedef enum { -+ CVMX_MIPS_SPACE_XKSEG = 3LL, -+ CVMX_MIPS_SPACE_XKPHYS = 2LL, -+ CVMX_MIPS_SPACE_XSSEG = 1LL, -+ CVMX_MIPS_SPACE_XUSEG = 0LL -+} cvmx_mips_space_t; -+#endif -+ -+typedef enum { -+ CVMX_MIPS_XKSEG_SPACE_KSEG0 = 0LL, -+ CVMX_MIPS_XKSEG_SPACE_KSEG1 = 1LL, -+ CVMX_MIPS_XKSEG_SPACE_SSEG = 2LL, -+ CVMX_MIPS_XKSEG_SPACE_KSEG3 = 3LL -+} cvmx_mips_xkseg_space_t; -+ -+/* decodes <14:13> of a kseg3 window address */ -+typedef enum { -+ CVMX_ADD_WIN_SCR = 0L, -+ /* see cvmx_add_win_dma_dec_t for further decode */ -+ CVMX_ADD_WIN_DMA = 1L, -+ CVMX_ADD_WIN_UNUSED = 2L, -+ CVMX_ADD_WIN_UNUSED2 = 3L -+} cvmx_add_win_dec_t; -+ -+/* decode within DMA space */ -+typedef enum { -+ /* -+ * Add store data to the write buffer entry, allocating it if -+ * necessary. -+ */ -+ CVMX_ADD_WIN_DMA_ADD = 0L, -+ /* send out the write buffer entry to DRAM */ -+ CVMX_ADD_WIN_DMA_SENDMEM = 1L, -+ /* store data must be normal DRAM memory space address in this case */ -+ /* send out the write buffer entry as an IOBDMA command */ -+ CVMX_ADD_WIN_DMA_SENDDMA = 2L, -+ /* see CVMX_ADD_WIN_DMA_SEND_DEC for data contents */ -+ /* send out the write buffer entry as an IO write */ -+ CVMX_ADD_WIN_DMA_SENDIO = 3L, -+ /* store data must be normal IO space address in this case */ -+ /* send out a single-tick command on the NCB bus */ -+ CVMX_ADD_WIN_DMA_SENDSINGLE = 4L, -+ /* no write buffer data needed/used */ -+} cvmx_add_win_dma_dec_t; -+ -+/* -+ * Physical Address Decode -+ * -+ * Octeon-I HW never interprets this X (<39:36> reserved -+ * for future expansion), software should set to 0. -+ * -+ * - 0x0 XXX0 0000 0000 to DRAM Cached -+ * - 0x0 XXX0 0FFF FFFF -+ * -+ * - 0x0 XXX0 1000 0000 to Boot Bus Uncached (Converted to 0x1 00X0 1000 0000 -+ * - 0x0 XXX0 1FFF FFFF + EJTAG to 0x1 00X0 1FFF FFFF) -+ * -+ * - 0x0 XXX0 2000 0000 to DRAM Cached -+ * - 0x0 XXXF FFFF FFFF -+ * -+ * - 0x1 00X0 0000 0000 to Boot Bus Uncached -+ * - 0x1 00XF FFFF FFFF -+ * -+ * - 0x1 01X0 0000 0000 to Other NCB Uncached -+ * - 0x1 FFXF FFFF FFFF devices -+ * -+ * Decode of all Octeon addresses -+ */ -+typedef union { -+ -+ uint64_t u64; -+ /* mapped or unmapped virtual address */ -+ struct { -+ uint64_t R:2; -+ uint64_t offset:62; -+ } sva; -+ -+ /* mapped USEG virtual addresses (typically) */ -+ struct { -+ uint64_t zeroes:33; -+ uint64_t offset:31; -+ } suseg; -+ -+ /* mapped or unmapped virtual address */ -+ struct { -+ uint64_t ones:33; -+ uint64_t sp:2; -+ uint64_t offset:29; -+ } sxkseg; -+ -+ /* -+ * physical address accessed through xkphys unmapped virtual -+ * address. -+ */ -+ struct { -+ uint64_t R:2; /* CVMX_MIPS_SPACE_XKPHYS in this case */ -+ uint64_t cca:3; /* ignored by octeon */ -+ uint64_t mbz:10; -+ uint64_t pa:49; /* physical address */ -+ } sxkphys; -+ -+ /* physical address */ -+ struct { -+ uint64_t mbz:15; -+ /* if set, the address is uncached and resides on MCB bus */ -+ uint64_t is_io:1; -+ /* -+ * the hardware ignores this field when is_io==0, else -+ * device ID. -+ */ -+ uint64_t did:8; -+ /* the hardware ignores <39:36> in Octeon I */ -+ uint64_t unaddr:4; -+ uint64_t offset:36; -+ } sphys; -+ -+ /* physical mem address */ -+ struct { -+ /* techically, <47:40> are dont-cares */ -+ uint64_t zeroes:24; -+ /* the hardware ignores <39:36> in Octeon I */ -+ uint64_t unaddr:4; -+ uint64_t offset:36; -+ } smem; -+ -+ /* physical IO address */ -+ struct { -+ uint64_t mem_region:2; -+ uint64_t mbz:13; -+ /* 1 in this case */ -+ uint64_t is_io:1; -+ /* -+ * The hardware ignores this field when is_io==0, else -+ * device ID. -+ */ -+ uint64_t did:8; -+ /* the hardware ignores <39:36> in Octeon I */ -+ uint64_t unaddr:4; -+ uint64_t offset:36; -+ } sio; -+ -+ /* -+ * Scratchpad virtual address - accessed through a window at -+ * the end of kseg3 -+ */ -+ struct { -+ uint64_t ones:49; -+ /* CVMX_ADD_WIN_SCR (0) in this case */ -+ cvmx_add_win_dec_t csrdec:2; -+ uint64_t addr:13; -+ } sscr; -+ -+ /* there should only be stores to IOBDMA space, no loads */ -+ /* -+ * IOBDMA virtual address - accessed through a window at the -+ * end of kseg3 -+ */ -+ struct { -+ uint64_t ones:49; -+ uint64_t csrdec:2; /* CVMX_ADD_WIN_DMA (1) in this case */ -+ uint64_t unused2:3; -+ uint64_t type:3; -+ uint64_t addr:7; -+ } sdma; -+ -+ struct { -+ uint64_t didspace:24; -+ uint64_t unused:40; -+ } sfilldidspace; -+ -+} cvmx_addr_t; -+ -+/* These macros for used by 32 bit applications */ -+ -+#define CVMX_MIPS32_SPACE_KSEG0 1l -+#define CVMX_ADD_SEG32(segment, add) \ -+ (((int32_t)segment << 31) | (int32_t)(add)) -+ -+/* -+ * Currently all IOs are performed using XKPHYS addressing. Linux uses -+ * the CvmMemCtl register to enable XKPHYS addressing to IO space from -+ * user mode. Future OSes may need to change the upper bits of IO -+ * addresses. The following define controls the upper two bits for all -+ * IO addresses generated by the simple executive library. -+ */ -+#define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS -+ -+/* These macros simplify the process of creating common IO addresses */ -+#define CVMX_ADD_SEG(segment, add) ((((uint64_t)segment) << 62) | (add)) -+#ifndef CVMX_ADD_IO_SEG -+#define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add)) -+#endif -+#define CVMX_ADDR_DIDSPACE(did) (((CVMX_IO_SEG) << 22) | ((1ULL) << 8) | (did)) -+#define CVMX_ADDR_DID(did) (CVMX_ADDR_DIDSPACE(did) << 40) -+#define CVMX_FULL_DID(did, subdid) (((did) << 3) | (subdid)) -+ -+ /* from include/ncb_rsl_id.v */ -+#define CVMX_OCT_DID_MIS 0ULL /* misc stuff */ -+#define CVMX_OCT_DID_GMX0 1ULL -+#define CVMX_OCT_DID_GMX1 2ULL -+#define CVMX_OCT_DID_PCI 3ULL -+#define CVMX_OCT_DID_KEY 4ULL -+#define CVMX_OCT_DID_FPA 5ULL -+#define CVMX_OCT_DID_DFA 6ULL -+#define CVMX_OCT_DID_ZIP 7ULL -+#define CVMX_OCT_DID_RNG 8ULL -+#define CVMX_OCT_DID_IPD 9ULL -+#define CVMX_OCT_DID_PKT 10ULL -+#define CVMX_OCT_DID_TIM 11ULL -+#define CVMX_OCT_DID_TAG 12ULL -+ /* the rest are not on the IO bus */ -+#define CVMX_OCT_DID_L2C 16ULL -+#define CVMX_OCT_DID_LMC 17ULL -+#define CVMX_OCT_DID_SPX0 18ULL -+#define CVMX_OCT_DID_SPX1 19ULL -+#define CVMX_OCT_DID_PIP 20ULL -+#define CVMX_OCT_DID_ASX0 22ULL -+#define CVMX_OCT_DID_ASX1 23ULL -+#define CVMX_OCT_DID_IOB 30ULL -+ -+#define CVMX_OCT_DID_PKT_SEND CVMX_FULL_DID(CVMX_OCT_DID_PKT, 2ULL) -+#define CVMX_OCT_DID_TAG_SWTAG CVMX_FULL_DID(CVMX_OCT_DID_TAG, 0ULL) -+#define CVMX_OCT_DID_TAG_TAG1 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 1ULL) -+#define CVMX_OCT_DID_TAG_TAG2 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 2ULL) -+#define CVMX_OCT_DID_TAG_TAG3 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 3ULL) -+#define CVMX_OCT_DID_TAG_NULL_RD CVMX_FULL_DID(CVMX_OCT_DID_TAG, 4ULL) -+#define CVMX_OCT_DID_TAG_CSR CVMX_FULL_DID(CVMX_OCT_DID_TAG, 7ULL) -+#define CVMX_OCT_DID_FAU_FAI CVMX_FULL_DID(CVMX_OCT_DID_IOB, 0ULL) -+#define CVMX_OCT_DID_TIM_CSR CVMX_FULL_DID(CVMX_OCT_DID_TIM, 0ULL) -+#define CVMX_OCT_DID_KEY_RW CVMX_FULL_DID(CVMX_OCT_DID_KEY, 0ULL) -+#define CVMX_OCT_DID_PCI_6 CVMX_FULL_DID(CVMX_OCT_DID_PCI, 6ULL) -+#define CVMX_OCT_DID_MIS_BOO CVMX_FULL_DID(CVMX_OCT_DID_MIS, 0ULL) -+#define CVMX_OCT_DID_PCI_RML CVMX_FULL_DID(CVMX_OCT_DID_PCI, 0ULL) -+#define CVMX_OCT_DID_IPD_CSR CVMX_FULL_DID(CVMX_OCT_DID_IPD, 7ULL) -+#define CVMX_OCT_DID_DFA_CSR CVMX_FULL_DID(CVMX_OCT_DID_DFA, 7ULL) -+#define CVMX_OCT_DID_MIS_CSR CVMX_FULL_DID(CVMX_OCT_DID_MIS, 7ULL) -+#define CVMX_OCT_DID_ZIP_CSR CVMX_FULL_DID(CVMX_OCT_DID_ZIP, 0ULL) -+ -+#endif /* __CVMX_ADDRESS_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-asxx-defs.h -@@ -0,0 +1,475 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_ASXX_DEFS_H__ -+#define __CVMX_ASXX_DEFS_H__ -+ -+#define CVMX_ASXX_GMII_RX_CLK_SET(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000180ull + (((block_id) & 0) * 0x8000000ull)) -+#define CVMX_ASXX_GMII_RX_DAT_SET(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000188ull + (((block_id) & 0) * 0x8000000ull)) -+#define CVMX_ASXX_INT_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000018ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_INT_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000010ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_MII_RX_DAT_SET(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000190ull + (((block_id) & 0) * 0x8000000ull)) -+#define CVMX_ASXX_PRT_LOOP(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000040ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_BYPASS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000248ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_BYPASS_SETTING(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000250ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_COMP(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000220ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_DATA_DRV(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000218ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_FCRAM_MODE(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000210ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_NCTL_STRONG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000230ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_NCTL_WEAK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000240ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_PCTL_STRONG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000228ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_PCTL_WEAK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000238ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RLD_SETTING(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000258ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RX_CLK_SETX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000020ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RX_PRT_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000000ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RX_WOL(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000100ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RX_WOL_MSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000108ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RX_WOL_POWOK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000118ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_RX_WOL_SIG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000110ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_TX_CLK_SETX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000048ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_TX_COMP_BYP(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000068ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_TX_HI_WATERX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000080ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_ASXX_TX_PRT_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000008ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_asxx_gmii_rx_clk_set { -+ uint64_t u64; -+ struct cvmx_asxx_gmii_rx_clk_set_s { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_gmii_rx_clk_set_s cn30xx; -+ struct cvmx_asxx_gmii_rx_clk_set_s cn31xx; -+ struct cvmx_asxx_gmii_rx_clk_set_s cn50xx; -+}; -+ -+union cvmx_asxx_gmii_rx_dat_set { -+ uint64_t u64; -+ struct cvmx_asxx_gmii_rx_dat_set_s { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_gmii_rx_dat_set_s cn30xx; -+ struct cvmx_asxx_gmii_rx_dat_set_s cn31xx; -+ struct cvmx_asxx_gmii_rx_dat_set_s cn50xx; -+}; -+ -+union cvmx_asxx_int_en { -+ uint64_t u64; -+ struct cvmx_asxx_int_en_s { -+ uint64_t reserved_12_63:52; -+ uint64_t txpsh:4; -+ uint64_t txpop:4; -+ uint64_t ovrflw:4; -+ } s; -+ struct cvmx_asxx_int_en_cn30xx { -+ uint64_t reserved_11_63:53; -+ uint64_t txpsh:3; -+ uint64_t reserved_7_7:1; -+ uint64_t txpop:3; -+ uint64_t reserved_3_3:1; -+ uint64_t ovrflw:3; -+ } cn30xx; -+ struct cvmx_asxx_int_en_cn30xx cn31xx; -+ struct cvmx_asxx_int_en_s cn38xx; -+ struct cvmx_asxx_int_en_s cn38xxp2; -+ struct cvmx_asxx_int_en_cn30xx cn50xx; -+ struct cvmx_asxx_int_en_s cn58xx; -+ struct cvmx_asxx_int_en_s cn58xxp1; -+}; -+ -+union cvmx_asxx_int_reg { -+ uint64_t u64; -+ struct cvmx_asxx_int_reg_s { -+ uint64_t reserved_12_63:52; -+ uint64_t txpsh:4; -+ uint64_t txpop:4; -+ uint64_t ovrflw:4; -+ } s; -+ struct cvmx_asxx_int_reg_cn30xx { -+ uint64_t reserved_11_63:53; -+ uint64_t txpsh:3; -+ uint64_t reserved_7_7:1; -+ uint64_t txpop:3; -+ uint64_t reserved_3_3:1; -+ uint64_t ovrflw:3; -+ } cn30xx; -+ struct cvmx_asxx_int_reg_cn30xx cn31xx; -+ struct cvmx_asxx_int_reg_s cn38xx; -+ struct cvmx_asxx_int_reg_s cn38xxp2; -+ struct cvmx_asxx_int_reg_cn30xx cn50xx; -+ struct cvmx_asxx_int_reg_s cn58xx; -+ struct cvmx_asxx_int_reg_s cn58xxp1; -+}; -+ -+union cvmx_asxx_mii_rx_dat_set { -+ uint64_t u64; -+ struct cvmx_asxx_mii_rx_dat_set_s { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_mii_rx_dat_set_s cn30xx; -+ struct cvmx_asxx_mii_rx_dat_set_s cn50xx; -+}; -+ -+union cvmx_asxx_prt_loop { -+ uint64_t u64; -+ struct cvmx_asxx_prt_loop_s { -+ uint64_t reserved_8_63:56; -+ uint64_t ext_loop:4; -+ uint64_t int_loop:4; -+ } s; -+ struct cvmx_asxx_prt_loop_cn30xx { -+ uint64_t reserved_7_63:57; -+ uint64_t ext_loop:3; -+ uint64_t reserved_3_3:1; -+ uint64_t int_loop:3; -+ } cn30xx; -+ struct cvmx_asxx_prt_loop_cn30xx cn31xx; -+ struct cvmx_asxx_prt_loop_s cn38xx; -+ struct cvmx_asxx_prt_loop_s cn38xxp2; -+ struct cvmx_asxx_prt_loop_cn30xx cn50xx; -+ struct cvmx_asxx_prt_loop_s cn58xx; -+ struct cvmx_asxx_prt_loop_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_bypass { -+ uint64_t u64; -+ struct cvmx_asxx_rld_bypass_s { -+ uint64_t reserved_1_63:63; -+ uint64_t bypass:1; -+ } s; -+ struct cvmx_asxx_rld_bypass_s cn38xx; -+ struct cvmx_asxx_rld_bypass_s cn38xxp2; -+ struct cvmx_asxx_rld_bypass_s cn58xx; -+ struct cvmx_asxx_rld_bypass_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_bypass_setting { -+ uint64_t u64; -+ struct cvmx_asxx_rld_bypass_setting_s { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_rld_bypass_setting_s cn38xx; -+ struct cvmx_asxx_rld_bypass_setting_s cn38xxp2; -+ struct cvmx_asxx_rld_bypass_setting_s cn58xx; -+ struct cvmx_asxx_rld_bypass_setting_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_comp { -+ uint64_t u64; -+ struct cvmx_asxx_rld_comp_s { -+ uint64_t reserved_9_63:55; -+ uint64_t pctl:5; -+ uint64_t nctl:4; -+ } s; -+ struct cvmx_asxx_rld_comp_cn38xx { -+ uint64_t reserved_8_63:56; -+ uint64_t pctl:4; -+ uint64_t nctl:4; -+ } cn38xx; -+ struct cvmx_asxx_rld_comp_cn38xx cn38xxp2; -+ struct cvmx_asxx_rld_comp_s cn58xx; -+ struct cvmx_asxx_rld_comp_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_data_drv { -+ uint64_t u64; -+ struct cvmx_asxx_rld_data_drv_s { -+ uint64_t reserved_8_63:56; -+ uint64_t pctl:4; -+ uint64_t nctl:4; -+ } s; -+ struct cvmx_asxx_rld_data_drv_s cn38xx; -+ struct cvmx_asxx_rld_data_drv_s cn38xxp2; -+ struct cvmx_asxx_rld_data_drv_s cn58xx; -+ struct cvmx_asxx_rld_data_drv_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_fcram_mode { -+ uint64_t u64; -+ struct cvmx_asxx_rld_fcram_mode_s { -+ uint64_t reserved_1_63:63; -+ uint64_t mode:1; -+ } s; -+ struct cvmx_asxx_rld_fcram_mode_s cn38xx; -+ struct cvmx_asxx_rld_fcram_mode_s cn38xxp2; -+}; -+ -+union cvmx_asxx_rld_nctl_strong { -+ uint64_t u64; -+ struct cvmx_asxx_rld_nctl_strong_s { -+ uint64_t reserved_5_63:59; -+ uint64_t nctl:5; -+ } s; -+ struct cvmx_asxx_rld_nctl_strong_s cn38xx; -+ struct cvmx_asxx_rld_nctl_strong_s cn38xxp2; -+ struct cvmx_asxx_rld_nctl_strong_s cn58xx; -+ struct cvmx_asxx_rld_nctl_strong_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_nctl_weak { -+ uint64_t u64; -+ struct cvmx_asxx_rld_nctl_weak_s { -+ uint64_t reserved_5_63:59; -+ uint64_t nctl:5; -+ } s; -+ struct cvmx_asxx_rld_nctl_weak_s cn38xx; -+ struct cvmx_asxx_rld_nctl_weak_s cn38xxp2; -+ struct cvmx_asxx_rld_nctl_weak_s cn58xx; -+ struct cvmx_asxx_rld_nctl_weak_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_pctl_strong { -+ uint64_t u64; -+ struct cvmx_asxx_rld_pctl_strong_s { -+ uint64_t reserved_5_63:59; -+ uint64_t pctl:5; -+ } s; -+ struct cvmx_asxx_rld_pctl_strong_s cn38xx; -+ struct cvmx_asxx_rld_pctl_strong_s cn38xxp2; -+ struct cvmx_asxx_rld_pctl_strong_s cn58xx; -+ struct cvmx_asxx_rld_pctl_strong_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_pctl_weak { -+ uint64_t u64; -+ struct cvmx_asxx_rld_pctl_weak_s { -+ uint64_t reserved_5_63:59; -+ uint64_t pctl:5; -+ } s; -+ struct cvmx_asxx_rld_pctl_weak_s cn38xx; -+ struct cvmx_asxx_rld_pctl_weak_s cn38xxp2; -+ struct cvmx_asxx_rld_pctl_weak_s cn58xx; -+ struct cvmx_asxx_rld_pctl_weak_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rld_setting { -+ uint64_t u64; -+ struct cvmx_asxx_rld_setting_s { -+ uint64_t reserved_13_63:51; -+ uint64_t dfaset:5; -+ uint64_t dfalag:1; -+ uint64_t dfalead:1; -+ uint64_t dfalock:1; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_rld_setting_cn38xx { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } cn38xx; -+ struct cvmx_asxx_rld_setting_cn38xx cn38xxp2; -+ struct cvmx_asxx_rld_setting_s cn58xx; -+ struct cvmx_asxx_rld_setting_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rx_clk_setx { -+ uint64_t u64; -+ struct cvmx_asxx_rx_clk_setx_s { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_rx_clk_setx_s cn30xx; -+ struct cvmx_asxx_rx_clk_setx_s cn31xx; -+ struct cvmx_asxx_rx_clk_setx_s cn38xx; -+ struct cvmx_asxx_rx_clk_setx_s cn38xxp2; -+ struct cvmx_asxx_rx_clk_setx_s cn50xx; -+ struct cvmx_asxx_rx_clk_setx_s cn58xx; -+ struct cvmx_asxx_rx_clk_setx_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rx_prt_en { -+ uint64_t u64; -+ struct cvmx_asxx_rx_prt_en_s { -+ uint64_t reserved_4_63:60; -+ uint64_t prt_en:4; -+ } s; -+ struct cvmx_asxx_rx_prt_en_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t prt_en:3; -+ } cn30xx; -+ struct cvmx_asxx_rx_prt_en_cn30xx cn31xx; -+ struct cvmx_asxx_rx_prt_en_s cn38xx; -+ struct cvmx_asxx_rx_prt_en_s cn38xxp2; -+ struct cvmx_asxx_rx_prt_en_cn30xx cn50xx; -+ struct cvmx_asxx_rx_prt_en_s cn58xx; -+ struct cvmx_asxx_rx_prt_en_s cn58xxp1; -+}; -+ -+union cvmx_asxx_rx_wol { -+ uint64_t u64; -+ struct cvmx_asxx_rx_wol_s { -+ uint64_t reserved_2_63:62; -+ uint64_t status:1; -+ uint64_t enable:1; -+ } s; -+ struct cvmx_asxx_rx_wol_s cn38xx; -+ struct cvmx_asxx_rx_wol_s cn38xxp2; -+}; -+ -+union cvmx_asxx_rx_wol_msk { -+ uint64_t u64; -+ struct cvmx_asxx_rx_wol_msk_s { -+ uint64_t msk:64; -+ } s; -+ struct cvmx_asxx_rx_wol_msk_s cn38xx; -+ struct cvmx_asxx_rx_wol_msk_s cn38xxp2; -+}; -+ -+union cvmx_asxx_rx_wol_powok { -+ uint64_t u64; -+ struct cvmx_asxx_rx_wol_powok_s { -+ uint64_t reserved_1_63:63; -+ uint64_t powerok:1; -+ } s; -+ struct cvmx_asxx_rx_wol_powok_s cn38xx; -+ struct cvmx_asxx_rx_wol_powok_s cn38xxp2; -+}; -+ -+union cvmx_asxx_rx_wol_sig { -+ uint64_t u64; -+ struct cvmx_asxx_rx_wol_sig_s { -+ uint64_t reserved_32_63:32; -+ uint64_t sig:32; -+ } s; -+ struct cvmx_asxx_rx_wol_sig_s cn38xx; -+ struct cvmx_asxx_rx_wol_sig_s cn38xxp2; -+}; -+ -+union cvmx_asxx_tx_clk_setx { -+ uint64_t u64; -+ struct cvmx_asxx_tx_clk_setx_s { -+ uint64_t reserved_5_63:59; -+ uint64_t setting:5; -+ } s; -+ struct cvmx_asxx_tx_clk_setx_s cn30xx; -+ struct cvmx_asxx_tx_clk_setx_s cn31xx; -+ struct cvmx_asxx_tx_clk_setx_s cn38xx; -+ struct cvmx_asxx_tx_clk_setx_s cn38xxp2; -+ struct cvmx_asxx_tx_clk_setx_s cn50xx; -+ struct cvmx_asxx_tx_clk_setx_s cn58xx; -+ struct cvmx_asxx_tx_clk_setx_s cn58xxp1; -+}; -+ -+union cvmx_asxx_tx_comp_byp { -+ uint64_t u64; -+ struct cvmx_asxx_tx_comp_byp_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_asxx_tx_comp_byp_cn30xx { -+ uint64_t reserved_9_63:55; -+ uint64_t bypass:1; -+ uint64_t pctl:4; -+ uint64_t nctl:4; -+ } cn30xx; -+ struct cvmx_asxx_tx_comp_byp_cn30xx cn31xx; -+ struct cvmx_asxx_tx_comp_byp_cn38xx { -+ uint64_t reserved_8_63:56; -+ uint64_t pctl:4; -+ uint64_t nctl:4; -+ } cn38xx; -+ struct cvmx_asxx_tx_comp_byp_cn38xx cn38xxp2; -+ struct cvmx_asxx_tx_comp_byp_cn50xx { -+ uint64_t reserved_17_63:47; -+ uint64_t bypass:1; -+ uint64_t reserved_13_15:3; -+ uint64_t pctl:5; -+ uint64_t reserved_5_7:3; -+ uint64_t nctl:5; -+ } cn50xx; -+ struct cvmx_asxx_tx_comp_byp_cn58xx { -+ uint64_t reserved_13_63:51; -+ uint64_t pctl:5; -+ uint64_t reserved_5_7:3; -+ uint64_t nctl:5; -+ } cn58xx; -+ struct cvmx_asxx_tx_comp_byp_cn58xx cn58xxp1; -+}; -+ -+union cvmx_asxx_tx_hi_waterx { -+ uint64_t u64; -+ struct cvmx_asxx_tx_hi_waterx_s { -+ uint64_t reserved_4_63:60; -+ uint64_t mark:4; -+ } s; -+ struct cvmx_asxx_tx_hi_waterx_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t mark:3; -+ } cn30xx; -+ struct cvmx_asxx_tx_hi_waterx_cn30xx cn31xx; -+ struct cvmx_asxx_tx_hi_waterx_s cn38xx; -+ struct cvmx_asxx_tx_hi_waterx_s cn38xxp2; -+ struct cvmx_asxx_tx_hi_waterx_cn30xx cn50xx; -+ struct cvmx_asxx_tx_hi_waterx_s cn58xx; -+ struct cvmx_asxx_tx_hi_waterx_s cn58xxp1; -+}; -+ -+union cvmx_asxx_tx_prt_en { -+ uint64_t u64; -+ struct cvmx_asxx_tx_prt_en_s { -+ uint64_t reserved_4_63:60; -+ uint64_t prt_en:4; -+ } s; -+ struct cvmx_asxx_tx_prt_en_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t prt_en:3; -+ } cn30xx; -+ struct cvmx_asxx_tx_prt_en_cn30xx cn31xx; -+ struct cvmx_asxx_tx_prt_en_s cn38xx; -+ struct cvmx_asxx_tx_prt_en_s cn38xxp2; -+ struct cvmx_asxx_tx_prt_en_cn30xx cn50xx; -+ struct cvmx_asxx_tx_prt_en_s cn58xx; -+ struct cvmx_asxx_tx_prt_en_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-cmd-queue.c -@@ -0,0 +1,306 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Support functions for managing command queues used for -+ * various hardware blocks. -+ */ -+ -+#include -+ -+#include -+ -+#include "cvmx-config.h" -+#include "cvmx-fpa.h" -+#include "cvmx-cmd-queue.h" -+ -+#include -+#include -+#include "cvmx-pko-defs.h" -+ -+/** -+ * This application uses this pointer to access the global queue -+ * state. It points to a bootmem named block. -+ */ -+__cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr; -+ -+/** -+ * Initialize the Global queue state pointer. -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void) -+{ -+ char *alloc_name = "cvmx_cmd_queues"; -+#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32 -+ extern uint64_t octeon_reserve32_memory; -+#endif -+ -+ if (likely(__cvmx_cmd_queue_state_ptr)) -+ return CVMX_CMD_QUEUE_SUCCESS; -+ -+#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32 -+ if (octeon_reserve32_memory) -+ __cvmx_cmd_queue_state_ptr = -+ cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr), -+ octeon_reserve32_memory, -+ octeon_reserve32_memory + -+ (CONFIG_CAVIUM_RESERVE32 << -+ 20) - 1, 128, alloc_name); -+ else -+#endif -+ __cvmx_cmd_queue_state_ptr = -+ cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr), -+ 128, -+ alloc_name); -+ if (__cvmx_cmd_queue_state_ptr) -+ memset(__cvmx_cmd_queue_state_ptr, 0, -+ sizeof(*__cvmx_cmd_queue_state_ptr)); -+ else { -+ struct cvmx_bootmem_named_block_desc *block_desc = -+ cvmx_bootmem_find_named_block(alloc_name); -+ if (block_desc) -+ __cvmx_cmd_queue_state_ptr = -+ cvmx_phys_to_ptr(block_desc->base_addr); -+ else { -+ cvmx_dprintf -+ ("ERROR: cvmx_cmd_queue_initialize: Unable to get named block %s.\n", -+ alloc_name); -+ return CVMX_CMD_QUEUE_NO_MEMORY; -+ } -+ } -+ return CVMX_CMD_QUEUE_SUCCESS; -+} -+ -+/** -+ * Initialize a command queue for use. The initial FPA buffer is -+ * allocated and the hardware unit is configured to point to the -+ * new command queue. -+ * -+ * @queue_id: Hardware command queue to initialize. -+ * @max_depth: Maximum outstanding commands that can be queued. -+ * @fpa_pool: FPA pool the command queues should come from. -+ * @pool_size: Size of each buffer in the FPA pool (bytes) -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id, -+ int max_depth, int fpa_pool, -+ int pool_size) -+{ -+ __cvmx_cmd_queue_state_t *qstate; -+ cvmx_cmd_queue_result_t result = __cvmx_cmd_queue_init_state_ptr(); -+ if (result != CVMX_CMD_QUEUE_SUCCESS) -+ return result; -+ -+ qstate = __cvmx_cmd_queue_get_state(queue_id); -+ if (qstate == NULL) -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ -+ /* -+ * We artificially limit max_depth to 1<<20 words. It is an -+ * arbitrary limit. -+ */ -+ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH) { -+ if ((max_depth < 0) || (max_depth > 1 << 20)) -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } else if (max_depth != 0) -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ -+ if ((fpa_pool < 0) || (fpa_pool > 7)) -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ if ((pool_size < 128) || (pool_size > 65536)) -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ -+ /* See if someone else has already initialized the queue */ -+ if (qstate->base_ptr_div128) { -+ if (max_depth != (int)qstate->max_depth) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " -+ "Queue already initalized with different " -+ "max_depth (%d).\n", -+ (int)qstate->max_depth); -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } -+ if (fpa_pool != qstate->fpa_pool) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " -+ "Queue already initalized with different " -+ "FPA pool (%u).\n", -+ qstate->fpa_pool); -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } -+ if ((pool_size >> 3) - 1 != qstate->pool_size_m1) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " -+ "Queue already initalized with different " -+ "FPA pool size (%u).\n", -+ (qstate->pool_size_m1 + 1) << 3); -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } -+ CVMX_SYNCWS; -+ return CVMX_CMD_QUEUE_ALREADY_SETUP; -+ } else { -+ union cvmx_fpa_ctl_status status; -+ void *buffer; -+ -+ status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS); -+ if (!status.s.enb) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " -+ "FPA is not enabled.\n"); -+ return CVMX_CMD_QUEUE_NO_MEMORY; -+ } -+ buffer = cvmx_fpa_alloc(fpa_pool); -+ if (buffer == NULL) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: " -+ "Unable to allocate initial buffer.\n"); -+ return CVMX_CMD_QUEUE_NO_MEMORY; -+ } -+ -+ memset(qstate, 0, sizeof(*qstate)); -+ qstate->max_depth = max_depth; -+ qstate->fpa_pool = fpa_pool; -+ qstate->pool_size_m1 = (pool_size >> 3) - 1; -+ qstate->base_ptr_div128 = cvmx_ptr_to_phys(buffer) / 128; -+ /* -+ * We zeroed the now serving field so we need to also -+ * zero the ticket. -+ */ -+ __cvmx_cmd_queue_state_ptr-> -+ ticket[__cvmx_cmd_queue_get_index(queue_id)] = 0; -+ CVMX_SYNCWS; -+ return CVMX_CMD_QUEUE_SUCCESS; -+ } -+} -+ -+/** -+ * Shutdown a queue a free it's command buffers to the FPA. The -+ * hardware connected to the queue must be stopped before this -+ * function is called. -+ * -+ * @queue_id: Queue to shutdown -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id) -+{ -+ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); -+ if (qptr == NULL) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Unable to " -+ "get queue information.\n"); -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } -+ -+ if (cvmx_cmd_queue_length(queue_id) > 0) { -+ cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Queue still " -+ "has data in it.\n"); -+ return CVMX_CMD_QUEUE_FULL; -+ } -+ -+ __cvmx_cmd_queue_lock(queue_id, qptr); -+ if (qptr->base_ptr_div128) { -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) qptr->base_ptr_div128 << 7), -+ qptr->fpa_pool, 0); -+ qptr->base_ptr_div128 = 0; -+ } -+ __cvmx_cmd_queue_unlock(qptr); -+ -+ return CVMX_CMD_QUEUE_SUCCESS; -+} -+ -+/** -+ * Return the number of command words pending in the queue. This -+ * function may be relatively slow for some hardware units. -+ * -+ * @queue_id: Hardware command queue to query -+ * -+ * Returns Number of outstanding commands -+ */ -+int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id) -+{ -+ if (CVMX_ENABLE_PARAMETER_CHECKING) { -+ if (__cvmx_cmd_queue_get_state(queue_id) == NULL) -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } -+ -+ /* -+ * The cast is here so gcc with check that all values in the -+ * cvmx_cmd_queue_id_t enumeration are here. -+ */ -+ switch ((cvmx_cmd_queue_id_t) (queue_id & 0xff0000)) { -+ case CVMX_CMD_QUEUE_PKO_BASE: -+ /* -+ * FIXME: Need atomic lock on -+ * CVMX_PKO_REG_READ_IDX. Right now we are normally -+ * called with the queue lock, so that is a SLIGHT -+ * amount of protection. -+ */ -+ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue_id & 0xffff); -+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ union cvmx_pko_mem_debug9 debug9; -+ debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9); -+ return debug9.cn38xx.doorbell; -+ } else { -+ union cvmx_pko_mem_debug8 debug8; -+ debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); -+ return debug8.cn58xx.doorbell; -+ } -+ case CVMX_CMD_QUEUE_ZIP: -+ case CVMX_CMD_QUEUE_DFA: -+ case CVMX_CMD_QUEUE_RAID: -+ /* FIXME: Implement other lengths */ -+ return 0; -+ case CVMX_CMD_QUEUE_DMA_BASE: -+ { -+ union cvmx_npei_dmax_counts dmax_counts; -+ dmax_counts.u64 = -+ cvmx_read_csr(CVMX_PEXP_NPEI_DMAX_COUNTS -+ (queue_id & 0x7)); -+ return dmax_counts.s.dbell; -+ } -+ case CVMX_CMD_QUEUE_END: -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+ } -+ return CVMX_CMD_QUEUE_INVALID_PARAM; -+} -+ -+/** -+ * Return the command buffer to be written to. The purpose of this -+ * function is to allow CVMX routine access t othe low level buffer -+ * for initial hardware setup. User applications should not call this -+ * function directly. -+ * -+ * @queue_id: Command queue to query -+ * -+ * Returns Command buffer or NULL on failure -+ */ -+void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id) -+{ -+ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); -+ if (qptr && qptr->base_ptr_div128) -+ return cvmx_phys_to_ptr((uint64_t) qptr->base_ptr_div128 << 7); -+ else -+ return NULL; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-cmd-queue.h -@@ -0,0 +1,617 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Support functions for managing command queues used for -+ * various hardware blocks. -+ * -+ * The common command queue infrastructure abstracts out the -+ * software necessary for adding to Octeon's chained queue -+ * structures. These structures are used for commands to the -+ * PKO, ZIP, DFA, RAID, and DMA engine blocks. Although each -+ * hardware unit takes commands and CSRs of different types, -+ * they all use basic linked command buffers to store the -+ * pending request. In general, users of the CVMX API don't -+ * call cvmx-cmd-queue functions directly. Instead the hardware -+ * unit specific wrapper should be used. The wrappers perform -+ * unit specific validation and CSR writes to submit the -+ * commands. -+ * -+ * Even though most software will never directly interact with -+ * cvmx-cmd-queue, knowledge of its internal working can help -+ * in diagnosing performance problems and help with debugging. -+ * -+ * Command queue pointers are stored in a global named block -+ * called "cvmx_cmd_queues". Except for the PKO queues, each -+ * hardware queue is stored in its own cache line to reduce SMP -+ * contention on spin locks. The PKO queues are stored such that -+ * every 16th queue is next to each other in memory. This scheme -+ * allows for queues being in separate cache lines when there -+ * are low number of queues per port. With 16 queues per port, -+ * the first queue for each port is in the same cache area. The -+ * second queues for each port are in another area, etc. This -+ * allows software to implement very efficient lockless PKO with -+ * 16 queues per port using a minimum of cache lines per core. -+ * All queues for a given core will be isolated in the same -+ * cache area. -+ * -+ * In addition to the memory pointer layout, cvmx-cmd-queue -+ * provides an optimized fair ll/sc locking mechanism for the -+ * queues. The lock uses a "ticket / now serving" model to -+ * maintain fair order on contended locks. In addition, it uses -+ * predicted locking time to limit cache contention. When a core -+ * know it must wait in line for a lock, it spins on the -+ * internal cycle counter to completely eliminate any causes of -+ * bus traffic. -+ * -+ */ -+ -+#ifndef __CVMX_CMD_QUEUE_H__ -+#define __CVMX_CMD_QUEUE_H__ -+ -+#include -+ -+#include "cvmx-fpa.h" -+/** -+ * By default we disable the max depth support. Most programs -+ * don't use it and it slows down the command queue processing -+ * significantly. -+ */ -+#ifndef CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH -+#define CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH 0 -+#endif -+ -+/** -+ * Enumeration representing all hardware blocks that use command -+ * queues. Each hardware block has up to 65536 sub identifiers for -+ * multiple command queues. Not all chips support all hardware -+ * units. -+ */ -+typedef enum { -+ CVMX_CMD_QUEUE_PKO_BASE = 0x00000, -+ -+#define CVMX_CMD_QUEUE_PKO(queue) \ -+ ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_PKO_BASE + (0xffff&(queue)))) -+ -+ CVMX_CMD_QUEUE_ZIP = 0x10000, -+ CVMX_CMD_QUEUE_DFA = 0x20000, -+ CVMX_CMD_QUEUE_RAID = 0x30000, -+ CVMX_CMD_QUEUE_DMA_BASE = 0x40000, -+ -+#define CVMX_CMD_QUEUE_DMA(queue) \ -+ ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_DMA_BASE + (0xffff&(queue)))) -+ -+ CVMX_CMD_QUEUE_END = 0x50000, -+} cvmx_cmd_queue_id_t; -+ -+/** -+ * Command write operations can fail if the comamnd queue needs -+ * a new buffer and the associated FPA pool is empty. It can also -+ * fail if the number of queued command words reaches the maximum -+ * set at initialization. -+ */ -+typedef enum { -+ CVMX_CMD_QUEUE_SUCCESS = 0, -+ CVMX_CMD_QUEUE_NO_MEMORY = -1, -+ CVMX_CMD_QUEUE_FULL = -2, -+ CVMX_CMD_QUEUE_INVALID_PARAM = -3, -+ CVMX_CMD_QUEUE_ALREADY_SETUP = -4, -+} cvmx_cmd_queue_result_t; -+ -+typedef struct { -+ /* You have lock when this is your ticket */ -+ uint8_t now_serving; -+ uint64_t unused1:24; -+ /* Maximum outstanding command words */ -+ uint32_t max_depth; -+ /* FPA pool buffers come from */ -+ uint64_t fpa_pool:3; -+ /* Top of command buffer pointer shifted 7 */ -+ uint64_t base_ptr_div128:29; -+ uint64_t unused2:6; -+ /* FPA buffer size in 64bit words minus 1 */ -+ uint64_t pool_size_m1:13; -+ /* Number of comamnds already used in buffer */ -+ uint64_t index:13; -+} __cvmx_cmd_queue_state_t; -+ -+/** -+ * This structure contains the global state of all comamnd queues. -+ * It is stored in a bootmem named block and shared by all -+ * applications running on Octeon. Tickets are stored in a differnet -+ * cahce line that queue information to reduce the contention on the -+ * ll/sc used to get a ticket. If this is not the case, the update -+ * of queue state causes the ll/sc to fail quite often. -+ */ -+typedef struct { -+ uint64_t ticket[(CVMX_CMD_QUEUE_END >> 16) * 256]; -+ __cvmx_cmd_queue_state_t state[(CVMX_CMD_QUEUE_END >> 16) * 256]; -+} __cvmx_cmd_queue_all_state_t; -+ -+/** -+ * Initialize a command queue for use. The initial FPA buffer is -+ * allocated and the hardware unit is configured to point to the -+ * new command queue. -+ * -+ * @queue_id: Hardware command queue to initialize. -+ * @max_depth: Maximum outstanding commands that can be queued. -+ * @fpa_pool: FPA pool the command queues should come from. -+ * @pool_size: Size of each buffer in the FPA pool (bytes) -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id, -+ int max_depth, int fpa_pool, -+ int pool_size); -+ -+/** -+ * Shutdown a queue a free it's command buffers to the FPA. The -+ * hardware connected to the queue must be stopped before this -+ * function is called. -+ * -+ * @queue_id: Queue to shutdown -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id); -+ -+/** -+ * Return the number of command words pending in the queue. This -+ * function may be relatively slow for some hardware units. -+ * -+ * @queue_id: Hardware command queue to query -+ * -+ * Returns Number of outstanding commands -+ */ -+int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id); -+ -+/** -+ * Return the command buffer to be written to. The purpose of this -+ * function is to allow CVMX routine access t othe low level buffer -+ * for initial hardware setup. User applications should not call this -+ * function directly. -+ * -+ * @queue_id: Command queue to query -+ * -+ * Returns Command buffer or NULL on failure -+ */ -+void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id); -+ -+/** -+ * Get the index into the state arrays for the supplied queue id. -+ * -+ * @queue_id: Queue ID to get an index for -+ * -+ * Returns Index into the state arrays -+ */ -+static inline int __cvmx_cmd_queue_get_index(cvmx_cmd_queue_id_t queue_id) -+{ -+ /* -+ * Warning: This code currently only works with devices that -+ * have 256 queues or less. Devices with more than 16 queues -+ * are layed out in memory to allow cores quick access to -+ * every 16th queue. This reduces cache thrashing when you are -+ * running 16 queues per port to support lockless operation. -+ */ -+ int unit = queue_id >> 16; -+ int q = (queue_id >> 4) & 0xf; -+ int core = queue_id & 0xf; -+ return unit * 256 + core * 16 + q; -+} -+ -+/** -+ * Lock the supplied queue so nobody else is updating it at the same -+ * time as us. -+ * -+ * @queue_id: Queue ID to lock -+ * @qptr: Pointer to the queue's global state -+ */ -+static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id, -+ __cvmx_cmd_queue_state_t *qptr) -+{ -+ extern __cvmx_cmd_queue_all_state_t -+ *__cvmx_cmd_queue_state_ptr; -+ int tmp; -+ int my_ticket; -+ prefetch(qptr); -+ asm volatile ( -+ ".set push\n" -+ ".set noreorder\n" -+ "1:\n" -+ /* Atomic add one to ticket_ptr */ -+ "ll %[my_ticket], %[ticket_ptr]\n" -+ /* and store the original value */ -+ "li %[ticket], 1\n" -+ /* in my_ticket */ -+ "baddu %[ticket], %[my_ticket]\n" -+ "sc %[ticket], %[ticket_ptr]\n" -+ "beqz %[ticket], 1b\n" -+ " nop\n" -+ /* Load the current now_serving ticket */ -+ "lbu %[ticket], %[now_serving]\n" -+ "2:\n" -+ /* Jump out if now_serving == my_ticket */ -+ "beq %[ticket], %[my_ticket], 4f\n" -+ /* Find out how many tickets are in front of me */ -+ " subu %[ticket], %[my_ticket], %[ticket]\n" -+ /* Use tickets in front of me minus one to delay */ -+ "subu %[ticket], 1\n" -+ /* Delay will be ((tickets in front)-1)*32 loops */ -+ "cins %[ticket], %[ticket], 5, 7\n" -+ "3:\n" -+ /* Loop here until our ticket might be up */ -+ "bnez %[ticket], 3b\n" -+ " subu %[ticket], 1\n" -+ /* Jump back up to check out ticket again */ -+ "b 2b\n" -+ /* Load the current now_serving ticket */ -+ " lbu %[ticket], %[now_serving]\n" -+ "4:\n" -+ ".set pop\n" : -+ [ticket_ptr] "=m"(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]), -+ [now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp), -+ [my_ticket] "=r"(my_ticket) -+ ); -+} -+ -+/** -+ * Unlock the queue, flushing all writes. -+ * -+ * @qptr: Queue to unlock -+ */ -+static inline void __cvmx_cmd_queue_unlock(__cvmx_cmd_queue_state_t *qptr) -+{ -+ qptr->now_serving++; -+ CVMX_SYNCWS; -+} -+ -+/** -+ * Get the queue state structure for the given queue id -+ * -+ * @queue_id: Queue id to get -+ * -+ * Returns Queue structure or NULL on failure -+ */ -+static inline __cvmx_cmd_queue_state_t -+ *__cvmx_cmd_queue_get_state(cvmx_cmd_queue_id_t queue_id) -+{ -+ extern __cvmx_cmd_queue_all_state_t -+ *__cvmx_cmd_queue_state_ptr; -+ return &__cvmx_cmd_queue_state_ptr-> -+ state[__cvmx_cmd_queue_get_index(queue_id)]; -+} -+ -+/** -+ * Write an arbitrary number of command words to a command queue. -+ * This is a generic function; the fixed number of comamnd word -+ * functions yield higher performance. -+ * -+ * @queue_id: Hardware command queue to write to -+ * @use_locking: -+ * Use internal locking to ensure exclusive access for queue -+ * updates. If you don't use this locking you must ensure -+ * exclusivity some other way. Locking is strongly recommended. -+ * @cmd_count: Number of command words to write -+ * @cmds: Array of comamnds to write -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write(cvmx_cmd_queue_id_t -+ queue_id, -+ int use_locking, -+ int cmd_count, -+ uint64_t *cmds) -+{ -+ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); -+ -+ /* Make sure nobody else is updating the same queue */ -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_lock(queue_id, qptr); -+ -+ /* -+ * If a max queue length was specified then make sure we don't -+ * exceed it. If any part of the command would be below the -+ * limit we allow it. -+ */ -+ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { -+ if (unlikely -+ (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_FULL; -+ } -+ } -+ -+ /* -+ * Normally there is plenty of room in the current buffer for -+ * the command. -+ */ -+ if (likely(qptr->index + cmd_count < qptr->pool_size_m1)) { -+ uint64_t *ptr = -+ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> -+ base_ptr_div128 << 7); -+ ptr += qptr->index; -+ qptr->index += cmd_count; -+ while (cmd_count--) -+ *ptr++ = *cmds++; -+ } else { -+ uint64_t *ptr; -+ int count; -+ /* -+ * We need a new comamnd buffer. Fail if there isn't -+ * one available. -+ */ -+ uint64_t *new_buffer = -+ (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); -+ if (unlikely(new_buffer == NULL)) { -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_NO_MEMORY; -+ } -+ ptr = -+ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> -+ base_ptr_div128 << 7); -+ /* -+ * Figure out how many command words will fit in this -+ * buffer. One location will be needed for the next -+ * buffer pointer. -+ */ -+ count = qptr->pool_size_m1 - qptr->index; -+ ptr += qptr->index; -+ cmd_count -= count; -+ while (count--) -+ *ptr++ = *cmds++; -+ *ptr = cvmx_ptr_to_phys(new_buffer); -+ /* -+ * The current buffer is full and has a link to the -+ * next buffer. Time to write the rest of the commands -+ * into the new buffer. -+ */ -+ qptr->base_ptr_div128 = *ptr >> 7; -+ qptr->index = cmd_count; -+ ptr = new_buffer; -+ while (cmd_count--) -+ *ptr++ = *cmds++; -+ } -+ -+ /* All updates are complete. Release the lock and return */ -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_SUCCESS; -+} -+ -+/** -+ * Simple function to write two command words to a command -+ * queue. -+ * -+ * @queue_id: Hardware command queue to write to -+ * @use_locking: -+ * Use internal locking to ensure exclusive access for queue -+ * updates. If you don't use this locking you must ensure -+ * exclusivity some other way. Locking is strongly recommended. -+ * @cmd1: Command -+ * @cmd2: Command -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write2(cvmx_cmd_queue_id_t -+ queue_id, -+ int use_locking, -+ uint64_t cmd1, -+ uint64_t cmd2) -+{ -+ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); -+ -+ /* Make sure nobody else is updating the same queue */ -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_lock(queue_id, qptr); -+ -+ /* -+ * If a max queue length was specified then make sure we don't -+ * exceed it. If any part of the command would be below the -+ * limit we allow it. -+ */ -+ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { -+ if (unlikely -+ (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_FULL; -+ } -+ } -+ -+ /* -+ * Normally there is plenty of room in the current buffer for -+ * the command. -+ */ -+ if (likely(qptr->index + 2 < qptr->pool_size_m1)) { -+ uint64_t *ptr = -+ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> -+ base_ptr_div128 << 7); -+ ptr += qptr->index; -+ qptr->index += 2; -+ ptr[0] = cmd1; -+ ptr[1] = cmd2; -+ } else { -+ uint64_t *ptr; -+ /* -+ * Figure out how many command words will fit in this -+ * buffer. One location will be needed for the next -+ * buffer pointer. -+ */ -+ int count = qptr->pool_size_m1 - qptr->index; -+ /* -+ * We need a new comamnd buffer. Fail if there isn't -+ * one available. -+ */ -+ uint64_t *new_buffer = -+ (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); -+ if (unlikely(new_buffer == NULL)) { -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_NO_MEMORY; -+ } -+ count--; -+ ptr = -+ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> -+ base_ptr_div128 << 7); -+ ptr += qptr->index; -+ *ptr++ = cmd1; -+ if (likely(count)) -+ *ptr++ = cmd2; -+ *ptr = cvmx_ptr_to_phys(new_buffer); -+ /* -+ * The current buffer is full and has a link to the -+ * next buffer. Time to write the rest of the commands -+ * into the new buffer. -+ */ -+ qptr->base_ptr_div128 = *ptr >> 7; -+ qptr->index = 0; -+ if (unlikely(count == 0)) { -+ qptr->index = 1; -+ new_buffer[0] = cmd2; -+ } -+ } -+ -+ /* All updates are complete. Release the lock and return */ -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_SUCCESS; -+} -+ -+/** -+ * Simple function to write three command words to a command -+ * queue. -+ * -+ * @queue_id: Hardware command queue to write to -+ * @use_locking: -+ * Use internal locking to ensure exclusive access for queue -+ * updates. If you don't use this locking you must ensure -+ * exclusivity some other way. Locking is strongly recommended. -+ * @cmd1: Command -+ * @cmd2: Command -+ * @cmd3: Command -+ * -+ * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code -+ */ -+static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write3(cvmx_cmd_queue_id_t -+ queue_id, -+ int use_locking, -+ uint64_t cmd1, -+ uint64_t cmd2, -+ uint64_t cmd3) -+{ -+ __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id); -+ -+ /* Make sure nobody else is updating the same queue */ -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_lock(queue_id, qptr); -+ -+ /* -+ * If a max queue length was specified then make sure we don't -+ * exceed it. If any part of the command would be below the -+ * limit we allow it. -+ */ -+ if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) { -+ if (unlikely -+ (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) { -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_FULL; -+ } -+ } -+ -+ /* -+ * Normally there is plenty of room in the current buffer for -+ * the command. -+ */ -+ if (likely(qptr->index + 3 < qptr->pool_size_m1)) { -+ uint64_t *ptr = -+ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> -+ base_ptr_div128 << 7); -+ ptr += qptr->index; -+ qptr->index += 3; -+ ptr[0] = cmd1; -+ ptr[1] = cmd2; -+ ptr[2] = cmd3; -+ } else { -+ uint64_t *ptr; -+ /* -+ * Figure out how many command words will fit in this -+ * buffer. One location will be needed for the next -+ * buffer pointer -+ */ -+ int count = qptr->pool_size_m1 - qptr->index; -+ /* -+ * We need a new comamnd buffer. Fail if there isn't -+ * one available -+ */ -+ uint64_t *new_buffer = -+ (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool); -+ if (unlikely(new_buffer == NULL)) { -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_NO_MEMORY; -+ } -+ count--; -+ ptr = -+ (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr-> -+ base_ptr_div128 << 7); -+ ptr += qptr->index; -+ *ptr++ = cmd1; -+ if (count) { -+ *ptr++ = cmd2; -+ if (count > 1) -+ *ptr++ = cmd3; -+ } -+ *ptr = cvmx_ptr_to_phys(new_buffer); -+ /* -+ * The current buffer is full and has a link to the -+ * next buffer. Time to write the rest of the commands -+ * into the new buffer. -+ */ -+ qptr->base_ptr_div128 = *ptr >> 7; -+ qptr->index = 0; -+ ptr = new_buffer; -+ if (count == 0) { -+ *ptr++ = cmd2; -+ qptr->index++; -+ } -+ if (count < 2) { -+ *ptr++ = cmd3; -+ qptr->index++; -+ } -+ } -+ -+ /* All updates are complete. Release the lock and return */ -+ if (likely(use_locking)) -+ __cvmx_cmd_queue_unlock(qptr); -+ return CVMX_CMD_QUEUE_SUCCESS; -+} -+ -+#endif /* __CVMX_CMD_QUEUE_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-config.h -@@ -0,0 +1,169 @@ -+#ifndef __CVMX_CONFIG_H__ -+#define __CVMX_CONFIG_H__ -+ -+/************************* Config Specific Defines ************************/ -+#define CVMX_LLM_NUM_PORTS 1 -+#define CVMX_NULL_POINTER_PROTECT 1 -+#define CVMX_ENABLE_DEBUG_PRINTS 1 -+/* PKO queues per port for interface 0 (ports 0-15) */ -+#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 1 -+/* PKO queues per port for interface 1 (ports 16-31) */ -+#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 1 -+/* Limit on the number of PKO ports enabled for interface 0 */ -+#define CVMX_PKO_MAX_PORTS_INTERFACE0 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 -+/* Limit on the number of PKO ports enabled for interface 1 */ -+#define CVMX_PKO_MAX_PORTS_INTERFACE1 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 -+/* PKO queues per port for PCI (ports 32-35) */ -+#define CVMX_PKO_QUEUES_PER_PORT_PCI 1 -+/* PKO queues per port for Loop devices (ports 36-39) */ -+#define CVMX_PKO_QUEUES_PER_PORT_LOOP 1 -+ -+/************************* FPA allocation *********************************/ -+/* Pool sizes in bytes, must be multiple of a cache line */ -+#define CVMX_FPA_POOL_0_SIZE (16 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_1_SIZE (1 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_2_SIZE (8 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_3_SIZE (0 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_4_SIZE (0 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_5_SIZE (0 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_6_SIZE (0 * CVMX_CACHE_LINE_SIZE) -+#define CVMX_FPA_POOL_7_SIZE (0 * CVMX_CACHE_LINE_SIZE) -+ -+/* Pools in use */ -+/* Packet buffers */ -+#define CVMX_FPA_PACKET_POOL (0) -+#define CVMX_FPA_PACKET_POOL_SIZE CVMX_FPA_POOL_0_SIZE -+/* Work queue entrys */ -+#define CVMX_FPA_WQE_POOL (1) -+#define CVMX_FPA_WQE_POOL_SIZE CVMX_FPA_POOL_1_SIZE -+/* PKO queue command buffers */ -+#define CVMX_FPA_OUTPUT_BUFFER_POOL (2) -+#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE CVMX_FPA_POOL_2_SIZE -+ -+/************************* FAU allocation ********************************/ -+/* The fetch and add registers are allocated here. They are arranged -+ * in order of descending size so that all alignment constraints are -+ * automatically met. The enums are linked so that the following enum -+ * continues allocating where the previous one left off, so the -+ * numbering within each enum always starts with zero. The macros -+ * take care of the address increment size, so the values entered -+ * always increase by 1. FAU registers are accessed with byte -+ * addresses. -+ */ -+ -+#define CVMX_FAU_REG_64_ADDR(x) ((x << 3) + CVMX_FAU_REG_64_START) -+typedef enum { -+ CVMX_FAU_REG_64_START = 0, -+ CVMX_FAU_REG_64_END = CVMX_FAU_REG_64_ADDR(0), -+} cvmx_fau_reg_64_t; -+ -+#define CVMX_FAU_REG_32_ADDR(x) ((x << 2) + CVMX_FAU_REG_32_START) -+typedef enum { -+ CVMX_FAU_REG_32_START = CVMX_FAU_REG_64_END, -+ CVMX_FAU_REG_32_END = CVMX_FAU_REG_32_ADDR(0), -+} cvmx_fau_reg_32_t; -+ -+#define CVMX_FAU_REG_16_ADDR(x) ((x << 1) + CVMX_FAU_REG_16_START) -+typedef enum { -+ CVMX_FAU_REG_16_START = CVMX_FAU_REG_32_END, -+ CVMX_FAU_REG_16_END = CVMX_FAU_REG_16_ADDR(0), -+} cvmx_fau_reg_16_t; -+ -+#define CVMX_FAU_REG_8_ADDR(x) ((x) + CVMX_FAU_REG_8_START) -+typedef enum { -+ CVMX_FAU_REG_8_START = CVMX_FAU_REG_16_END, -+ CVMX_FAU_REG_8_END = CVMX_FAU_REG_8_ADDR(0), -+} cvmx_fau_reg_8_t; -+ -+/* -+ * The name CVMX_FAU_REG_AVAIL_BASE is provided to indicate the first -+ * available FAU address that is not allocated in cvmx-config.h. This -+ * is 64 bit aligned. -+ */ -+#define CVMX_FAU_REG_AVAIL_BASE ((CVMX_FAU_REG_8_END + 0x7) & (~0x7ULL)) -+#define CVMX_FAU_REG_END (2048) -+ -+/********************** scratch memory allocation *************************/ -+/* Scratchpad memory allocation. Note that these are byte memory -+ * addresses. Some uses of scratchpad (IOBDMA for example) require -+ * the use of 8-byte aligned addresses, so proper alignment needs to -+ * be taken into account. -+ */ -+/* Generic scratch iobdma area */ -+#define CVMX_SCR_SCRATCH (0) -+/* First location available after cvmx-config.h allocated region. */ -+#define CVMX_SCR_REG_AVAIL_BASE (8) -+ -+/* -+ * CVMX_HELPER_FIRST_MBUFF_SKIP is the number of bytes to reserve -+ * before the beginning of the packet. If necessary, override the -+ * default here. See the IPD section of the hardware manual for MBUFF -+ * SKIP details. -+ */ -+#define CVMX_HELPER_FIRST_MBUFF_SKIP 184 -+ -+/* -+ * CVMX_HELPER_NOT_FIRST_MBUFF_SKIP is the number of bytes to reserve -+ * in each chained packet element. If necessary, override the default -+ * here. -+ */ -+#define CVMX_HELPER_NOT_FIRST_MBUFF_SKIP 0 -+ -+/* -+ * CVMX_HELPER_ENABLE_BACK_PRESSURE controls whether back pressure is -+ * enabled for all input ports. This controls if IPD sends -+ * backpressure to all ports if Octeon's FPA pools don't have enough -+ * packet or work queue entries. Even when this is off, it is still -+ * possible to get backpressure from individual hardware ports. When -+ * configuring backpressure, also check -+ * CVMX_HELPER_DISABLE_*_BACKPRESSURE below. If necessary, override -+ * the default here. -+ */ -+#define CVMX_HELPER_ENABLE_BACK_PRESSURE 1 -+ -+/* -+ * CVMX_HELPER_ENABLE_IPD controls if the IPD is enabled in the helper -+ * function. Once it is enabled the hardware starts accepting -+ * packets. You might want to skip the IPD enable if configuration -+ * changes are need from the default helper setup. If necessary, -+ * override the default here. -+ */ -+#define CVMX_HELPER_ENABLE_IPD 0 -+ -+/* -+ * CVMX_HELPER_INPUT_TAG_TYPE selects the type of tag that the IPD assigns -+ * to incoming packets. -+ */ -+#define CVMX_HELPER_INPUT_TAG_TYPE CVMX_POW_TAG_TYPE_ORDERED -+ -+#define CVMX_ENABLE_PARAMETER_CHECKING 0 -+ -+/* -+ * The following select which fields are used by the PIP to generate -+ * the tag on INPUT -+ * 0: don't include -+ * 1: include -+ */ -+#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP 0 -+#define CVMX_HELPER_INPUT_TAG_IPV6_DST_IP 0 -+#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT 0 -+#define CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT 0 -+#define CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER 0 -+#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP 0 -+#define CVMX_HELPER_INPUT_TAG_IPV4_DST_IP 0 -+#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT 0 -+#define CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT 0 -+#define CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL 0 -+#define CVMX_HELPER_INPUT_TAG_INPUT_PORT 1 -+ -+/* Select skip mode for input ports */ -+#define CVMX_HELPER_INPUT_PORT_SKIP_MODE CVMX_PIP_PORT_CFG_MODE_SKIPL2 -+ -+/* -+ * Force backpressure to be disabled. This overrides all other -+ * backpressure configuration. -+ */ -+#define CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 0 -+ -+#endif /* __CVMX_CONFIG_H__ */ -+ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-dbg-defs.h -@@ -0,0 +1,72 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_DBG_DEFS_H__ -+#define __CVMX_DBG_DEFS_H__ -+ -+#define CVMX_DBG_DATA \ -+ CVMX_ADD_IO_SEG(0x00011F00000001E8ull) -+ -+union cvmx_dbg_data { -+ uint64_t u64; -+ struct cvmx_dbg_data_s { -+ uint64_t reserved_23_63:41; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } s; -+ struct cvmx_dbg_data_cn30xx { -+ uint64_t reserved_31_63:33; -+ uint64_t pll_mul:3; -+ uint64_t reserved_23_27:5; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } cn30xx; -+ struct cvmx_dbg_data_cn30xx cn31xx; -+ struct cvmx_dbg_data_cn38xx { -+ uint64_t reserved_29_63:35; -+ uint64_t d_mul:4; -+ uint64_t dclk_mul2:1; -+ uint64_t cclk_div2:1; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } cn38xx; -+ struct cvmx_dbg_data_cn38xx cn38xxp2; -+ struct cvmx_dbg_data_cn30xx cn50xx; -+ struct cvmx_dbg_data_cn58xx { -+ uint64_t reserved_29_63:35; -+ uint64_t rem:6; -+ uint64_t c_mul:5; -+ uint64_t dsel_ext:1; -+ uint64_t data:17; -+ } cn58xx; -+ struct cvmx_dbg_data_cn58xx cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-fau.h -@@ -0,0 +1,597 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Interface to the hardware Fetch and Add Unit. -+ */ -+ -+#ifndef __CVMX_FAU_H__ -+#define __CVMX_FAU_H__ -+ -+/* -+ * Octeon Fetch and Add Unit (FAU) -+ */ -+ -+#define CVMX_FAU_LOAD_IO_ADDRESS cvmx_build_io_address(0x1e, 0) -+#define CVMX_FAU_BITS_SCRADDR 63, 56 -+#define CVMX_FAU_BITS_LEN 55, 48 -+#define CVMX_FAU_BITS_INEVAL 35, 14 -+#define CVMX_FAU_BITS_TAGWAIT 13, 13 -+#define CVMX_FAU_BITS_NOADD 13, 13 -+#define CVMX_FAU_BITS_SIZE 12, 11 -+#define CVMX_FAU_BITS_REGISTER 10, 0 -+ -+typedef enum { -+ CVMX_FAU_OP_SIZE_8 = 0, -+ CVMX_FAU_OP_SIZE_16 = 1, -+ CVMX_FAU_OP_SIZE_32 = 2, -+ CVMX_FAU_OP_SIZE_64 = 3 -+} cvmx_fau_op_size_t; -+ -+/** -+ * Tagwait return definition. If a timeout occurs, the error -+ * bit will be set. Otherwise the value of the register before -+ * the update will be returned. -+ */ -+typedef struct { -+ uint64_t error:1; -+ int64_t value:63; -+} cvmx_fau_tagwait64_t; -+ -+/** -+ * Tagwait return definition. If a timeout occurs, the error -+ * bit will be set. Otherwise the value of the register before -+ * the update will be returned. -+ */ -+typedef struct { -+ uint64_t error:1; -+ int32_t value:31; -+} cvmx_fau_tagwait32_t; -+ -+/** -+ * Tagwait return definition. If a timeout occurs, the error -+ * bit will be set. Otherwise the value of the register before -+ * the update will be returned. -+ */ -+typedef struct { -+ uint64_t error:1; -+ int16_t value:15; -+} cvmx_fau_tagwait16_t; -+ -+/** -+ * Tagwait return definition. If a timeout occurs, the error -+ * bit will be set. Otherwise the value of the register before -+ * the update will be returned. -+ */ -+typedef struct { -+ uint64_t error:1; -+ int8_t value:7; -+} cvmx_fau_tagwait8_t; -+ -+/** -+ * Asynchronous tagwait return definition. If a timeout occurs, -+ * the error bit will be set. Otherwise the value of the -+ * register before the update will be returned. -+ */ -+typedef union { -+ uint64_t u64; -+ struct { -+ uint64_t invalid:1; -+ uint64_t data:63; /* unpredictable if invalid is set */ -+ } s; -+} cvmx_fau_async_tagwait_result_t; -+ -+/** -+ * Builds a store I/O address for writing to the FAU -+ * -+ * @noadd: 0 = Store value is atomically added to the current value -+ * 1 = Store value is atomically written over the current value -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * - Step by 4 for 32 bit access. -+ * - Step by 8 for 64 bit access. -+ * Returns Address to store for atomic update -+ */ -+static inline uint64_t __cvmx_fau_store_address(uint64_t noadd, uint64_t reg) -+{ -+ return CVMX_ADD_IO_SEG(CVMX_FAU_LOAD_IO_ADDRESS) | -+ cvmx_build_bits(CVMX_FAU_BITS_NOADD, noadd) | -+ cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg); -+} -+ -+/** -+ * Builds a I/O address for accessing the FAU -+ * -+ * @tagwait: Should the atomic add wait for the current tag switch -+ * operation to complete. -+ * - 0 = Don't wait -+ * - 1 = Wait for tag switch to complete -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * - Step by 4 for 32 bit access. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to add. -+ * Note: When performing 32 and 64 bit access, only the low -+ * 22 bits are available. -+ * Returns Address to read from for atomic update -+ */ -+static inline uint64_t __cvmx_fau_atomic_address(uint64_t tagwait, uint64_t reg, -+ int64_t value) -+{ -+ return CVMX_ADD_IO_SEG(CVMX_FAU_LOAD_IO_ADDRESS) | -+ cvmx_build_bits(CVMX_FAU_BITS_INEVAL, value) | -+ cvmx_build_bits(CVMX_FAU_BITS_TAGWAIT, tagwait) | -+ cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg); -+} -+ -+/** -+ * Perform an atomic 64 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns Value of the register before the update -+ */ -+static inline int64_t cvmx_fau_fetch_and_add64(cvmx_fau_reg_64_t reg, -+ int64_t value) -+{ -+ return cvmx_read64_int64(__cvmx_fau_atomic_address(0, reg, value)); -+} -+ -+/** -+ * Perform an atomic 32 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 4 for 32 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns Value of the register before the update -+ */ -+static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg, -+ int32_t value) -+{ -+ return cvmx_read64_int32(__cvmx_fau_atomic_address(0, reg, value)); -+} -+ -+/** -+ * Perform an atomic 16 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * @value: Signed value to add. -+ * Returns Value of the register before the update -+ */ -+static inline int16_t cvmx_fau_fetch_and_add16(cvmx_fau_reg_16_t reg, -+ int16_t value) -+{ -+ return cvmx_read64_int16(__cvmx_fau_atomic_address(0, reg, value)); -+} -+ -+/** -+ * Perform an atomic 8 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * @value: Signed value to add. -+ * Returns Value of the register before the update -+ */ -+static inline int8_t cvmx_fau_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value) -+{ -+ return cvmx_read64_int8(__cvmx_fau_atomic_address(0, reg, value)); -+} -+ -+/** -+ * Perform an atomic 64 bit add after the current tag switch -+ * completes -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns If a timeout occurs, the error bit will be set. Otherwise -+ * the value of the register before the update will be -+ * returned -+ */ -+static inline cvmx_fau_tagwait64_t -+cvmx_fau_tagwait_fetch_and_add64(cvmx_fau_reg_64_t reg, int64_t value) -+{ -+ union { -+ uint64_t i64; -+ cvmx_fau_tagwait64_t t; -+ } result; -+ result.i64 = -+ cvmx_read64_int64(__cvmx_fau_atomic_address(1, reg, value)); -+ return result.t; -+} -+ -+/** -+ * Perform an atomic 32 bit add after the current tag switch -+ * completes -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 4 for 32 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns If a timeout occurs, the error bit will be set. Otherwise -+ * the value of the register before the update will be -+ * returned -+ */ -+static inline cvmx_fau_tagwait32_t -+cvmx_fau_tagwait_fetch_and_add32(cvmx_fau_reg_32_t reg, int32_t value) -+{ -+ union { -+ uint64_t i32; -+ cvmx_fau_tagwait32_t t; -+ } result; -+ result.i32 = -+ cvmx_read64_int32(__cvmx_fau_atomic_address(1, reg, value)); -+ return result.t; -+} -+ -+/** -+ * Perform an atomic 16 bit add after the current tag switch -+ * completes -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * @value: Signed value to add. -+ * Returns If a timeout occurs, the error bit will be set. Otherwise -+ * the value of the register before the update will be -+ * returned -+ */ -+static inline cvmx_fau_tagwait16_t -+cvmx_fau_tagwait_fetch_and_add16(cvmx_fau_reg_16_t reg, int16_t value) -+{ -+ union { -+ uint64_t i16; -+ cvmx_fau_tagwait16_t t; -+ } result; -+ result.i16 = -+ cvmx_read64_int16(__cvmx_fau_atomic_address(1, reg, value)); -+ return result.t; -+} -+ -+/** -+ * Perform an atomic 8 bit add after the current tag switch -+ * completes -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * @value: Signed value to add. -+ * Returns If a timeout occurs, the error bit will be set. Otherwise -+ * the value of the register before the update will be -+ * returned -+ */ -+static inline cvmx_fau_tagwait8_t -+cvmx_fau_tagwait_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value) -+{ -+ union { -+ uint64_t i8; -+ cvmx_fau_tagwait8_t t; -+ } result; -+ result.i8 = cvmx_read64_int8(__cvmx_fau_atomic_address(1, reg, value)); -+ return result.t; -+} -+ -+/** -+ * Builds I/O data for async operations -+ * -+ * @scraddr: Scratch pad byte addres to write to. Must be 8 byte aligned -+ * @value: Signed value to add. -+ * Note: When performing 32 and 64 bit access, only the low -+ * 22 bits are available. -+ * @tagwait: Should the atomic add wait for the current tag switch -+ * operation to complete. -+ * - 0 = Don't wait -+ * - 1 = Wait for tag switch to complete -+ * @size: The size of the operation: -+ * - CVMX_FAU_OP_SIZE_8 (0) = 8 bits -+ * - CVMX_FAU_OP_SIZE_16 (1) = 16 bits -+ * - CVMX_FAU_OP_SIZE_32 (2) = 32 bits -+ * - CVMX_FAU_OP_SIZE_64 (3) = 64 bits -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * - Step by 4 for 32 bit access. -+ * - Step by 8 for 64 bit access. -+ * Returns Data to write using cvmx_send_single -+ */ -+static inline uint64_t __cvmx_fau_iobdma_data(uint64_t scraddr, int64_t value, -+ uint64_t tagwait, -+ cvmx_fau_op_size_t size, -+ uint64_t reg) -+{ -+ return CVMX_FAU_LOAD_IO_ADDRESS | -+ cvmx_build_bits(CVMX_FAU_BITS_SCRADDR, scraddr >> 3) | -+ cvmx_build_bits(CVMX_FAU_BITS_LEN, 1) | -+ cvmx_build_bits(CVMX_FAU_BITS_INEVAL, value) | -+ cvmx_build_bits(CVMX_FAU_BITS_TAGWAIT, tagwait) | -+ cvmx_build_bits(CVMX_FAU_BITS_SIZE, size) | -+ cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg); -+} -+ -+/** -+ * Perform an async atomic 64 bit add. The old value is -+ * placed in the scratch memory at byte address scraddr. -+ * -+ * @scraddr: Scratch memory byte address to put response in. -+ * Must be 8 byte aligned. -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_fetch_and_add64(uint64_t scraddr, -+ cvmx_fau_reg_64_t reg, -+ int64_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 0, CVMX_FAU_OP_SIZE_64, reg)); -+} -+ -+/** -+ * Perform an async atomic 32 bit add. The old value is -+ * placed in the scratch memory at byte address scraddr. -+ * -+ * @scraddr: Scratch memory byte address to put response in. -+ * Must be 8 byte aligned. -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 4 for 32 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr, -+ cvmx_fau_reg_32_t reg, -+ int32_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 0, CVMX_FAU_OP_SIZE_32, reg)); -+} -+ -+/** -+ * Perform an async atomic 16 bit add. The old value is -+ * placed in the scratch memory at byte address scraddr. -+ * -+ * @scraddr: Scratch memory byte address to put response in. -+ * Must be 8 byte aligned. -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * @value: Signed value to add. -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_fetch_and_add16(uint64_t scraddr, -+ cvmx_fau_reg_16_t reg, -+ int16_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 0, CVMX_FAU_OP_SIZE_16, reg)); -+} -+ -+/** -+ * Perform an async atomic 8 bit add. The old value is -+ * placed in the scratch memory at byte address scraddr. -+ * -+ * @scraddr: Scratch memory byte address to put response in. -+ * Must be 8 byte aligned. -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * @value: Signed value to add. -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_fetch_and_add8(uint64_t scraddr, -+ cvmx_fau_reg_8_t reg, -+ int8_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 0, CVMX_FAU_OP_SIZE_8, reg)); -+} -+ -+/** -+ * Perform an async atomic 64 bit add after the current tag -+ * switch completes. -+ * -+ * @scraddr: Scratch memory byte address to put response in. Must be -+ * 8 byte aligned. If a timeout occurs, the error bit (63) -+ * will be set. Otherwise the value of the register before -+ * the update will be returned -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_tagwait_fetch_and_add64(uint64_t scraddr, -+ cvmx_fau_reg_64_t reg, -+ int64_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 1, CVMX_FAU_OP_SIZE_64, reg)); -+} -+ -+/** -+ * Perform an async atomic 32 bit add after the current tag -+ * switch completes. -+ * -+ * @scraddr: Scratch memory byte address to put response in. Must be -+ * 8 byte aligned. If a timeout occurs, the error bit (63) -+ * will be set. Otherwise the value of the register before -+ * the update will be returned -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 4 for 32 bit access. -+ * @value: Signed value to add. -+ * Note: Only the low 22 bits are available. -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_tagwait_fetch_and_add32(uint64_t scraddr, -+ cvmx_fau_reg_32_t reg, -+ int32_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 1, CVMX_FAU_OP_SIZE_32, reg)); -+} -+ -+/** -+ * Perform an async atomic 16 bit add after the current tag -+ * switch completes. -+ * -+ * @scraddr: Scratch memory byte address to put response in. Must be -+ * 8 byte aligned. If a timeout occurs, the error bit (63) -+ * will be set. Otherwise the value of the register before -+ * the update will be returned -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * @value: Signed value to add. -+ * -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_tagwait_fetch_and_add16(uint64_t scraddr, -+ cvmx_fau_reg_16_t reg, -+ int16_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 1, CVMX_FAU_OP_SIZE_16, reg)); -+} -+ -+/** -+ * Perform an async atomic 8 bit add after the current tag -+ * switch completes. -+ * -+ * @scraddr: Scratch memory byte address to put response in. Must be -+ * 8 byte aligned. If a timeout occurs, the error bit (63) -+ * will be set. Otherwise the value of the register before -+ * the update will be returned -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * @value: Signed value to add. -+ * -+ * Returns Placed in the scratch pad register -+ */ -+static inline void cvmx_fau_async_tagwait_fetch_and_add8(uint64_t scraddr, -+ cvmx_fau_reg_8_t reg, -+ int8_t value) -+{ -+ cvmx_send_single(__cvmx_fau_iobdma_data -+ (scraddr, value, 1, CVMX_FAU_OP_SIZE_8, reg)); -+} -+ -+/** -+ * Perform an atomic 64 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to add. -+ */ -+static inline void cvmx_fau_atomic_add64(cvmx_fau_reg_64_t reg, int64_t value) -+{ -+ cvmx_write64_int64(__cvmx_fau_store_address(0, reg), value); -+} -+ -+/** -+ * Perform an atomic 32 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 4 for 32 bit access. -+ * @value: Signed value to add. -+ */ -+static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value) -+{ -+ cvmx_write64_int32(__cvmx_fau_store_address(0, reg), value); -+} -+ -+/** -+ * Perform an atomic 16 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * @value: Signed value to add. -+ */ -+static inline void cvmx_fau_atomic_add16(cvmx_fau_reg_16_t reg, int16_t value) -+{ -+ cvmx_write64_int16(__cvmx_fau_store_address(0, reg), value); -+} -+ -+/** -+ * Perform an atomic 8 bit add -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * @value: Signed value to add. -+ */ -+static inline void cvmx_fau_atomic_add8(cvmx_fau_reg_8_t reg, int8_t value) -+{ -+ cvmx_write64_int8(__cvmx_fau_store_address(0, reg), value); -+} -+ -+/** -+ * Perform an atomic 64 bit write -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 8 for 64 bit access. -+ * @value: Signed value to write. -+ */ -+static inline void cvmx_fau_atomic_write64(cvmx_fau_reg_64_t reg, int64_t value) -+{ -+ cvmx_write64_int64(__cvmx_fau_store_address(1, reg), value); -+} -+ -+/** -+ * Perform an atomic 32 bit write -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 4 for 32 bit access. -+ * @value: Signed value to write. -+ */ -+static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value) -+{ -+ cvmx_write64_int32(__cvmx_fau_store_address(1, reg), value); -+} -+ -+/** -+ * Perform an atomic 16 bit write -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * - Step by 2 for 16 bit access. -+ * @value: Signed value to write. -+ */ -+static inline void cvmx_fau_atomic_write16(cvmx_fau_reg_16_t reg, int16_t value) -+{ -+ cvmx_write64_int16(__cvmx_fau_store_address(1, reg), value); -+} -+ -+/** -+ * Perform an atomic 8 bit write -+ * -+ * @reg: FAU atomic register to access. 0 <= reg < 2048. -+ * @value: Signed value to write. -+ */ -+static inline void cvmx_fau_atomic_write8(cvmx_fau_reg_8_t reg, int8_t value) -+{ -+ cvmx_write64_int8(__cvmx_fau_store_address(1, reg), value); -+} -+ -+#endif /* __CVMX_FAU_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-fpa-defs.h -@@ -0,0 +1,403 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_FPA_DEFS_H__ -+#define __CVMX_FPA_DEFS_H__ -+ -+#define CVMX_FPA_BIST_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011800280000E8ull) -+#define CVMX_FPA_CTL_STATUS \ -+ CVMX_ADD_IO_SEG(0x0001180028000050ull) -+#define CVMX_FPA_FPF0_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000000ull) -+#define CVMX_FPA_FPF0_SIZE \ -+ CVMX_ADD_IO_SEG(0x0001180028000058ull) -+#define CVMX_FPA_FPF1_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000008ull) -+#define CVMX_FPA_FPF2_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000010ull) -+#define CVMX_FPA_FPF3_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000018ull) -+#define CVMX_FPA_FPF4_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000020ull) -+#define CVMX_FPA_FPF5_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000028ull) -+#define CVMX_FPA_FPF6_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000030ull) -+#define CVMX_FPA_FPF7_MARKS \ -+ CVMX_ADD_IO_SEG(0x0001180028000038ull) -+#define CVMX_FPA_FPFX_MARKS(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180028000008ull + (((offset) & 7) * 8) - 8 * 1) -+#define CVMX_FPA_FPFX_SIZE(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180028000060ull + (((offset) & 7) * 8) - 8 * 1) -+#define CVMX_FPA_INT_ENB \ -+ CVMX_ADD_IO_SEG(0x0001180028000048ull) -+#define CVMX_FPA_INT_SUM \ -+ CVMX_ADD_IO_SEG(0x0001180028000040ull) -+#define CVMX_FPA_QUE0_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x00011800280000F0ull) -+#define CVMX_FPA_QUE1_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x00011800280000F8ull) -+#define CVMX_FPA_QUE2_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x0001180028000100ull) -+#define CVMX_FPA_QUE3_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x0001180028000108ull) -+#define CVMX_FPA_QUE4_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x0001180028000110ull) -+#define CVMX_FPA_QUE5_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x0001180028000118ull) -+#define CVMX_FPA_QUE6_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x0001180028000120ull) -+#define CVMX_FPA_QUE7_PAGE_INDEX \ -+ CVMX_ADD_IO_SEG(0x0001180028000128ull) -+#define CVMX_FPA_QUEX_AVAILABLE(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180028000098ull + (((offset) & 7) * 8)) -+#define CVMX_FPA_QUEX_PAGE_INDEX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800280000F0ull + (((offset) & 7) * 8)) -+#define CVMX_FPA_QUE_ACT \ -+ CVMX_ADD_IO_SEG(0x0001180028000138ull) -+#define CVMX_FPA_QUE_EXP \ -+ CVMX_ADD_IO_SEG(0x0001180028000130ull) -+#define CVMX_FPA_WART_CTL \ -+ CVMX_ADD_IO_SEG(0x00011800280000D8ull) -+#define CVMX_FPA_WART_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011800280000E0ull) -+ -+union cvmx_fpa_bist_status { -+ uint64_t u64; -+ struct cvmx_fpa_bist_status_s { -+ uint64_t reserved_5_63:59; -+ uint64_t frd:1; -+ uint64_t fpf0:1; -+ uint64_t fpf1:1; -+ uint64_t ffr:1; -+ uint64_t fdr:1; -+ } s; -+ struct cvmx_fpa_bist_status_s cn30xx; -+ struct cvmx_fpa_bist_status_s cn31xx; -+ struct cvmx_fpa_bist_status_s cn38xx; -+ struct cvmx_fpa_bist_status_s cn38xxp2; -+ struct cvmx_fpa_bist_status_s cn50xx; -+ struct cvmx_fpa_bist_status_s cn52xx; -+ struct cvmx_fpa_bist_status_s cn52xxp1; -+ struct cvmx_fpa_bist_status_s cn56xx; -+ struct cvmx_fpa_bist_status_s cn56xxp1; -+ struct cvmx_fpa_bist_status_s cn58xx; -+ struct cvmx_fpa_bist_status_s cn58xxp1; -+}; -+ -+union cvmx_fpa_ctl_status { -+ uint64_t u64; -+ struct cvmx_fpa_ctl_status_s { -+ uint64_t reserved_18_63:46; -+ uint64_t reset:1; -+ uint64_t use_ldt:1; -+ uint64_t use_stt:1; -+ uint64_t enb:1; -+ uint64_t mem1_err:7; -+ uint64_t mem0_err:7; -+ } s; -+ struct cvmx_fpa_ctl_status_s cn30xx; -+ struct cvmx_fpa_ctl_status_s cn31xx; -+ struct cvmx_fpa_ctl_status_s cn38xx; -+ struct cvmx_fpa_ctl_status_s cn38xxp2; -+ struct cvmx_fpa_ctl_status_s cn50xx; -+ struct cvmx_fpa_ctl_status_s cn52xx; -+ struct cvmx_fpa_ctl_status_s cn52xxp1; -+ struct cvmx_fpa_ctl_status_s cn56xx; -+ struct cvmx_fpa_ctl_status_s cn56xxp1; -+ struct cvmx_fpa_ctl_status_s cn58xx; -+ struct cvmx_fpa_ctl_status_s cn58xxp1; -+}; -+ -+union cvmx_fpa_fpfx_marks { -+ uint64_t u64; -+ struct cvmx_fpa_fpfx_marks_s { -+ uint64_t reserved_22_63:42; -+ uint64_t fpf_wr:11; -+ uint64_t fpf_rd:11; -+ } s; -+ struct cvmx_fpa_fpfx_marks_s cn38xx; -+ struct cvmx_fpa_fpfx_marks_s cn38xxp2; -+ struct cvmx_fpa_fpfx_marks_s cn56xx; -+ struct cvmx_fpa_fpfx_marks_s cn56xxp1; -+ struct cvmx_fpa_fpfx_marks_s cn58xx; -+ struct cvmx_fpa_fpfx_marks_s cn58xxp1; -+}; -+ -+union cvmx_fpa_fpfx_size { -+ uint64_t u64; -+ struct cvmx_fpa_fpfx_size_s { -+ uint64_t reserved_11_63:53; -+ uint64_t fpf_siz:11; -+ } s; -+ struct cvmx_fpa_fpfx_size_s cn38xx; -+ struct cvmx_fpa_fpfx_size_s cn38xxp2; -+ struct cvmx_fpa_fpfx_size_s cn56xx; -+ struct cvmx_fpa_fpfx_size_s cn56xxp1; -+ struct cvmx_fpa_fpfx_size_s cn58xx; -+ struct cvmx_fpa_fpfx_size_s cn58xxp1; -+}; -+ -+union cvmx_fpa_fpf0_marks { -+ uint64_t u64; -+ struct cvmx_fpa_fpf0_marks_s { -+ uint64_t reserved_24_63:40; -+ uint64_t fpf_wr:12; -+ uint64_t fpf_rd:12; -+ } s; -+ struct cvmx_fpa_fpf0_marks_s cn38xx; -+ struct cvmx_fpa_fpf0_marks_s cn38xxp2; -+ struct cvmx_fpa_fpf0_marks_s cn56xx; -+ struct cvmx_fpa_fpf0_marks_s cn56xxp1; -+ struct cvmx_fpa_fpf0_marks_s cn58xx; -+ struct cvmx_fpa_fpf0_marks_s cn58xxp1; -+}; -+ -+union cvmx_fpa_fpf0_size { -+ uint64_t u64; -+ struct cvmx_fpa_fpf0_size_s { -+ uint64_t reserved_12_63:52; -+ uint64_t fpf_siz:12; -+ } s; -+ struct cvmx_fpa_fpf0_size_s cn38xx; -+ struct cvmx_fpa_fpf0_size_s cn38xxp2; -+ struct cvmx_fpa_fpf0_size_s cn56xx; -+ struct cvmx_fpa_fpf0_size_s cn56xxp1; -+ struct cvmx_fpa_fpf0_size_s cn58xx; -+ struct cvmx_fpa_fpf0_size_s cn58xxp1; -+}; -+ -+union cvmx_fpa_int_enb { -+ uint64_t u64; -+ struct cvmx_fpa_int_enb_s { -+ uint64_t reserved_28_63:36; -+ uint64_t q7_perr:1; -+ uint64_t q7_coff:1; -+ uint64_t q7_und:1; -+ uint64_t q6_perr:1; -+ uint64_t q6_coff:1; -+ uint64_t q6_und:1; -+ uint64_t q5_perr:1; -+ uint64_t q5_coff:1; -+ uint64_t q5_und:1; -+ uint64_t q4_perr:1; -+ uint64_t q4_coff:1; -+ uint64_t q4_und:1; -+ uint64_t q3_perr:1; -+ uint64_t q3_coff:1; -+ uint64_t q3_und:1; -+ uint64_t q2_perr:1; -+ uint64_t q2_coff:1; -+ uint64_t q2_und:1; -+ uint64_t q1_perr:1; -+ uint64_t q1_coff:1; -+ uint64_t q1_und:1; -+ uint64_t q0_perr:1; -+ uint64_t q0_coff:1; -+ uint64_t q0_und:1; -+ uint64_t fed1_dbe:1; -+ uint64_t fed1_sbe:1; -+ uint64_t fed0_dbe:1; -+ uint64_t fed0_sbe:1; -+ } s; -+ struct cvmx_fpa_int_enb_s cn30xx; -+ struct cvmx_fpa_int_enb_s cn31xx; -+ struct cvmx_fpa_int_enb_s cn38xx; -+ struct cvmx_fpa_int_enb_s cn38xxp2; -+ struct cvmx_fpa_int_enb_s cn50xx; -+ struct cvmx_fpa_int_enb_s cn52xx; -+ struct cvmx_fpa_int_enb_s cn52xxp1; -+ struct cvmx_fpa_int_enb_s cn56xx; -+ struct cvmx_fpa_int_enb_s cn56xxp1; -+ struct cvmx_fpa_int_enb_s cn58xx; -+ struct cvmx_fpa_int_enb_s cn58xxp1; -+}; -+ -+union cvmx_fpa_int_sum { -+ uint64_t u64; -+ struct cvmx_fpa_int_sum_s { -+ uint64_t reserved_28_63:36; -+ uint64_t q7_perr:1; -+ uint64_t q7_coff:1; -+ uint64_t q7_und:1; -+ uint64_t q6_perr:1; -+ uint64_t q6_coff:1; -+ uint64_t q6_und:1; -+ uint64_t q5_perr:1; -+ uint64_t q5_coff:1; -+ uint64_t q5_und:1; -+ uint64_t q4_perr:1; -+ uint64_t q4_coff:1; -+ uint64_t q4_und:1; -+ uint64_t q3_perr:1; -+ uint64_t q3_coff:1; -+ uint64_t q3_und:1; -+ uint64_t q2_perr:1; -+ uint64_t q2_coff:1; -+ uint64_t q2_und:1; -+ uint64_t q1_perr:1; -+ uint64_t q1_coff:1; -+ uint64_t q1_und:1; -+ uint64_t q0_perr:1; -+ uint64_t q0_coff:1; -+ uint64_t q0_und:1; -+ uint64_t fed1_dbe:1; -+ uint64_t fed1_sbe:1; -+ uint64_t fed0_dbe:1; -+ uint64_t fed0_sbe:1; -+ } s; -+ struct cvmx_fpa_int_sum_s cn30xx; -+ struct cvmx_fpa_int_sum_s cn31xx; -+ struct cvmx_fpa_int_sum_s cn38xx; -+ struct cvmx_fpa_int_sum_s cn38xxp2; -+ struct cvmx_fpa_int_sum_s cn50xx; -+ struct cvmx_fpa_int_sum_s cn52xx; -+ struct cvmx_fpa_int_sum_s cn52xxp1; -+ struct cvmx_fpa_int_sum_s cn56xx; -+ struct cvmx_fpa_int_sum_s cn56xxp1; -+ struct cvmx_fpa_int_sum_s cn58xx; -+ struct cvmx_fpa_int_sum_s cn58xxp1; -+}; -+ -+union cvmx_fpa_quex_available { -+ uint64_t u64; -+ struct cvmx_fpa_quex_available_s { -+ uint64_t reserved_29_63:35; -+ uint64_t que_siz:29; -+ } s; -+ struct cvmx_fpa_quex_available_s cn30xx; -+ struct cvmx_fpa_quex_available_s cn31xx; -+ struct cvmx_fpa_quex_available_s cn38xx; -+ struct cvmx_fpa_quex_available_s cn38xxp2; -+ struct cvmx_fpa_quex_available_s cn50xx; -+ struct cvmx_fpa_quex_available_s cn52xx; -+ struct cvmx_fpa_quex_available_s cn52xxp1; -+ struct cvmx_fpa_quex_available_s cn56xx; -+ struct cvmx_fpa_quex_available_s cn56xxp1; -+ struct cvmx_fpa_quex_available_s cn58xx; -+ struct cvmx_fpa_quex_available_s cn58xxp1; -+}; -+ -+union cvmx_fpa_quex_page_index { -+ uint64_t u64; -+ struct cvmx_fpa_quex_page_index_s { -+ uint64_t reserved_25_63:39; -+ uint64_t pg_num:25; -+ } s; -+ struct cvmx_fpa_quex_page_index_s cn30xx; -+ struct cvmx_fpa_quex_page_index_s cn31xx; -+ struct cvmx_fpa_quex_page_index_s cn38xx; -+ struct cvmx_fpa_quex_page_index_s cn38xxp2; -+ struct cvmx_fpa_quex_page_index_s cn50xx; -+ struct cvmx_fpa_quex_page_index_s cn52xx; -+ struct cvmx_fpa_quex_page_index_s cn52xxp1; -+ struct cvmx_fpa_quex_page_index_s cn56xx; -+ struct cvmx_fpa_quex_page_index_s cn56xxp1; -+ struct cvmx_fpa_quex_page_index_s cn58xx; -+ struct cvmx_fpa_quex_page_index_s cn58xxp1; -+}; -+ -+union cvmx_fpa_que_act { -+ uint64_t u64; -+ struct cvmx_fpa_que_act_s { -+ uint64_t reserved_29_63:35; -+ uint64_t act_que:3; -+ uint64_t act_indx:26; -+ } s; -+ struct cvmx_fpa_que_act_s cn30xx; -+ struct cvmx_fpa_que_act_s cn31xx; -+ struct cvmx_fpa_que_act_s cn38xx; -+ struct cvmx_fpa_que_act_s cn38xxp2; -+ struct cvmx_fpa_que_act_s cn50xx; -+ struct cvmx_fpa_que_act_s cn52xx; -+ struct cvmx_fpa_que_act_s cn52xxp1; -+ struct cvmx_fpa_que_act_s cn56xx; -+ struct cvmx_fpa_que_act_s cn56xxp1; -+ struct cvmx_fpa_que_act_s cn58xx; -+ struct cvmx_fpa_que_act_s cn58xxp1; -+}; -+ -+union cvmx_fpa_que_exp { -+ uint64_t u64; -+ struct cvmx_fpa_que_exp_s { -+ uint64_t reserved_29_63:35; -+ uint64_t exp_que:3; -+ uint64_t exp_indx:26; -+ } s; -+ struct cvmx_fpa_que_exp_s cn30xx; -+ struct cvmx_fpa_que_exp_s cn31xx; -+ struct cvmx_fpa_que_exp_s cn38xx; -+ struct cvmx_fpa_que_exp_s cn38xxp2; -+ struct cvmx_fpa_que_exp_s cn50xx; -+ struct cvmx_fpa_que_exp_s cn52xx; -+ struct cvmx_fpa_que_exp_s cn52xxp1; -+ struct cvmx_fpa_que_exp_s cn56xx; -+ struct cvmx_fpa_que_exp_s cn56xxp1; -+ struct cvmx_fpa_que_exp_s cn58xx; -+ struct cvmx_fpa_que_exp_s cn58xxp1; -+}; -+ -+union cvmx_fpa_wart_ctl { -+ uint64_t u64; -+ struct cvmx_fpa_wart_ctl_s { -+ uint64_t reserved_16_63:48; -+ uint64_t ctl:16; -+ } s; -+ struct cvmx_fpa_wart_ctl_s cn30xx; -+ struct cvmx_fpa_wart_ctl_s cn31xx; -+ struct cvmx_fpa_wart_ctl_s cn38xx; -+ struct cvmx_fpa_wart_ctl_s cn38xxp2; -+ struct cvmx_fpa_wart_ctl_s cn50xx; -+ struct cvmx_fpa_wart_ctl_s cn52xx; -+ struct cvmx_fpa_wart_ctl_s cn52xxp1; -+ struct cvmx_fpa_wart_ctl_s cn56xx; -+ struct cvmx_fpa_wart_ctl_s cn56xxp1; -+ struct cvmx_fpa_wart_ctl_s cn58xx; -+ struct cvmx_fpa_wart_ctl_s cn58xxp1; -+}; -+ -+union cvmx_fpa_wart_status { -+ uint64_t u64; -+ struct cvmx_fpa_wart_status_s { -+ uint64_t reserved_32_63:32; -+ uint64_t status:32; -+ } s; -+ struct cvmx_fpa_wart_status_s cn30xx; -+ struct cvmx_fpa_wart_status_s cn31xx; -+ struct cvmx_fpa_wart_status_s cn38xx; -+ struct cvmx_fpa_wart_status_s cn38xxp2; -+ struct cvmx_fpa_wart_status_s cn50xx; -+ struct cvmx_fpa_wart_status_s cn52xx; -+ struct cvmx_fpa_wart_status_s cn52xxp1; -+ struct cvmx_fpa_wart_status_s cn56xx; -+ struct cvmx_fpa_wart_status_s cn56xxp1; -+ struct cvmx_fpa_wart_status_s cn58xx; -+ struct cvmx_fpa_wart_status_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-fpa.c -@@ -0,0 +1,183 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Support library for the hardware Free Pool Allocator. -+ * -+ * -+ */ -+ -+#include "cvmx-config.h" -+#include "cvmx.h" -+#include "cvmx-fpa.h" -+#include "cvmx-ipd.h" -+ -+/** -+ * Current state of all the pools. Use access functions -+ * instead of using it directly. -+ */ -+CVMX_SHARED cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS]; -+ -+/** -+ * Setup a FPA pool to control a new block of memory. The -+ * buffer pointer must be a physical address. -+ * -+ * @pool: Pool to initialize -+ * 0 <= pool < 8 -+ * @name: Constant character string to name this pool. -+ * String is not copied. -+ * @buffer: Pointer to the block of memory to use. This must be -+ * accessable by all processors and external hardware. -+ * @block_size: Size for each block controlled by the FPA -+ * @num_blocks: Number of blocks -+ * -+ * Returns 0 on Success, -+ * -1 on failure -+ */ -+int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer, -+ uint64_t block_size, uint64_t num_blocks) -+{ -+ char *ptr; -+ if (!buffer) { -+ cvmx_dprintf -+ ("ERROR: cvmx_fpa_setup_pool: NULL buffer pointer!\n"); -+ return -1; -+ } -+ if (pool >= CVMX_FPA_NUM_POOLS) { -+ cvmx_dprintf("ERROR: cvmx_fpa_setup_pool: Illegal pool!\n"); -+ return -1; -+ } -+ -+ if (block_size < CVMX_FPA_MIN_BLOCK_SIZE) { -+ cvmx_dprintf -+ ("ERROR: cvmx_fpa_setup_pool: Block size too small.\n"); -+ return -1; -+ } -+ -+ if (((unsigned long)buffer & (CVMX_FPA_ALIGNMENT - 1)) != 0) { -+ cvmx_dprintf -+ ("ERROR: cvmx_fpa_setup_pool: Buffer not aligned properly.\n"); -+ return -1; -+ } -+ -+ cvmx_fpa_pool_info[pool].name = name; -+ cvmx_fpa_pool_info[pool].size = block_size; -+ cvmx_fpa_pool_info[pool].starting_element_count = num_blocks; -+ cvmx_fpa_pool_info[pool].base = buffer; -+ -+ ptr = (char *)buffer; -+ while (num_blocks--) { -+ cvmx_fpa_free(ptr, pool, 0); -+ ptr += block_size; -+ } -+ return 0; -+} -+ -+/** -+ * Shutdown a Memory pool and validate that it had all of -+ * the buffers originally placed in it. -+ * -+ * @pool: Pool to shutdown -+ * Returns Zero on success -+ * - Positive is count of missing buffers -+ * - Negative is too many buffers or corrupted pointers -+ */ -+uint64_t cvmx_fpa_shutdown_pool(uint64_t pool) -+{ -+ uint64_t errors = 0; -+ uint64_t count = 0; -+ uint64_t base = cvmx_ptr_to_phys(cvmx_fpa_pool_info[pool].base); -+ uint64_t finish = -+ base + -+ cvmx_fpa_pool_info[pool].size * -+ cvmx_fpa_pool_info[pool].starting_element_count; -+ void *ptr; -+ uint64_t address; -+ -+ count = 0; -+ do { -+ ptr = cvmx_fpa_alloc(pool); -+ if (ptr) -+ address = cvmx_ptr_to_phys(ptr); -+ else -+ address = 0; -+ if (address) { -+ if ((address >= base) && (address < finish) && -+ (((address - -+ base) % cvmx_fpa_pool_info[pool].size) == 0)) { -+ count++; -+ } else { -+ cvmx_dprintf -+ ("ERROR: cvmx_fpa_shutdown_pool: Illegal address 0x%llx in pool %s(%d)\n", -+ (unsigned long long)address, -+ cvmx_fpa_pool_info[pool].name, (int)pool); -+ errors++; -+ } -+ } -+ } while (address); -+ -+#ifdef CVMX_ENABLE_PKO_FUNCTIONS -+ if (pool == 0) -+ cvmx_ipd_free_ptr(); -+#endif -+ -+ if (errors) { -+ cvmx_dprintf -+ ("ERROR: cvmx_fpa_shutdown_pool: Pool %s(%d) started at 0x%llx, ended at 0x%llx, with a step of 0x%llx\n", -+ cvmx_fpa_pool_info[pool].name, (int)pool, -+ (unsigned long long)base, (unsigned long long)finish, -+ (unsigned long long)cvmx_fpa_pool_info[pool].size); -+ return -errors; -+ } else -+ return 0; -+} -+ -+uint64_t cvmx_fpa_get_block_size(uint64_t pool) -+{ -+ switch (pool) { -+ case 0: -+ return CVMX_FPA_POOL_0_SIZE; -+ case 1: -+ return CVMX_FPA_POOL_1_SIZE; -+ case 2: -+ return CVMX_FPA_POOL_2_SIZE; -+ case 3: -+ return CVMX_FPA_POOL_3_SIZE; -+ case 4: -+ return CVMX_FPA_POOL_4_SIZE; -+ case 5: -+ return CVMX_FPA_POOL_5_SIZE; -+ case 6: -+ return CVMX_FPA_POOL_6_SIZE; -+ case 7: -+ return CVMX_FPA_POOL_7_SIZE; -+ default: -+ return 0; -+ } -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-fpa.h -@@ -0,0 +1,299 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Interface to the hardware Free Pool Allocator. -+ * -+ * -+ */ -+ -+#ifndef __CVMX_FPA_H__ -+#define __CVMX_FPA_H__ -+ -+#include "cvmx-address.h" -+#include "cvmx-fpa-defs.h" -+ -+#define CVMX_FPA_NUM_POOLS 8 -+#define CVMX_FPA_MIN_BLOCK_SIZE 128 -+#define CVMX_FPA_ALIGNMENT 128 -+ -+/** -+ * Structure describing the data format used for stores to the FPA. -+ */ -+typedef union { -+ uint64_t u64; -+ struct { -+ /* -+ * the (64-bit word) location in scratchpad to write -+ * to (if len != 0) -+ */ -+ uint64_t scraddr:8; -+ /* the number of words in the response (0 => no response) */ -+ uint64_t len:8; -+ /* the ID of the device on the non-coherent bus */ -+ uint64_t did:8; -+ /* -+ * the address that will appear in the first tick on -+ * the NCB bus. -+ */ -+ uint64_t addr:40; -+ } s; -+} cvmx_fpa_iobdma_data_t; -+ -+/** -+ * Structure describing the current state of a FPA pool. -+ */ -+typedef struct { -+ /* Name it was created under */ -+ const char *name; -+ /* Size of each block */ -+ uint64_t size; -+ /* The base memory address of whole block */ -+ void *base; -+ /* The number of elements in the pool at creation */ -+ uint64_t starting_element_count; -+} cvmx_fpa_pool_info_t; -+ -+/** -+ * Current state of all the pools. Use access functions -+ * instead of using it directly. -+ */ -+extern cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS]; -+ -+/* CSR typedefs have been moved to cvmx-csr-*.h */ -+ -+/** -+ * Return the name of the pool -+ * -+ * @pool: Pool to get the name of -+ * Returns The name -+ */ -+static inline const char *cvmx_fpa_get_name(uint64_t pool) -+{ -+ return cvmx_fpa_pool_info[pool].name; -+} -+ -+/** -+ * Return the base of the pool -+ * -+ * @pool: Pool to get the base of -+ * Returns The base -+ */ -+static inline void *cvmx_fpa_get_base(uint64_t pool) -+{ -+ return cvmx_fpa_pool_info[pool].base; -+} -+ -+/** -+ * Check if a pointer belongs to an FPA pool. Return non-zero -+ * if the supplied pointer is inside the memory controlled by -+ * an FPA pool. -+ * -+ * @pool: Pool to check -+ * @ptr: Pointer to check -+ * Returns Non-zero if pointer is in the pool. Zero if not -+ */ -+static inline int cvmx_fpa_is_member(uint64_t pool, void *ptr) -+{ -+ return ((ptr >= cvmx_fpa_pool_info[pool].base) && -+ ((char *)ptr < -+ ((char *)(cvmx_fpa_pool_info[pool].base)) + -+ cvmx_fpa_pool_info[pool].size * -+ cvmx_fpa_pool_info[pool].starting_element_count)); -+} -+ -+/** -+ * Enable the FPA for use. Must be performed after any CSR -+ * configuration but before any other FPA functions. -+ */ -+static inline void cvmx_fpa_enable(void) -+{ -+ union cvmx_fpa_ctl_status status; -+ -+ status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS); -+ if (status.s.enb) { -+ cvmx_dprintf -+ ("Warning: Enabling FPA when FPA already enabled.\n"); -+ } -+ -+ /* -+ * Do runtime check as we allow pass1 compiled code to run on -+ * pass2 chips. -+ */ -+ if (cvmx_octeon_is_pass1()) { -+ union cvmx_fpa_fpfx_marks marks; -+ int i; -+ for (i = 1; i < 8; i++) { -+ marks.u64 = -+ cvmx_read_csr(CVMX_FPA_FPF1_MARKS + (i - 1) * 8ull); -+ marks.s.fpf_wr = 0xe0; -+ cvmx_write_csr(CVMX_FPA_FPF1_MARKS + (i - 1) * 8ull, -+ marks.u64); -+ } -+ -+ /* Enforce a 10 cycle delay between config and enable */ -+ cvmx_wait(10); -+ } -+ -+ /* FIXME: CVMX_FPA_CTL_STATUS read is unmodelled */ -+ status.u64 = 0; -+ status.s.enb = 1; -+ cvmx_write_csr(CVMX_FPA_CTL_STATUS, status.u64); -+} -+ -+/** -+ * Get a new block from the FPA -+ * -+ * @pool: Pool to get the block from -+ * Returns Pointer to the block or NULL on failure -+ */ -+static inline void *cvmx_fpa_alloc(uint64_t pool) -+{ -+ uint64_t address = -+ cvmx_read_csr(CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool))); -+ if (address) -+ return cvmx_phys_to_ptr(address); -+ else -+ return NULL; -+} -+ -+/** -+ * Asynchronously get a new block from the FPA -+ * -+ * @scr_addr: Local scratch address to put response in. This is a byte address, -+ * but must be 8 byte aligned. -+ * @pool: Pool to get the block from -+ */ -+static inline void cvmx_fpa_async_alloc(uint64_t scr_addr, uint64_t pool) -+{ -+ cvmx_fpa_iobdma_data_t data; -+ -+ /* -+ * Hardware only uses 64 bit alligned locations, so convert -+ * from byte address to 64-bit index -+ */ -+ data.s.scraddr = scr_addr >> 3; -+ data.s.len = 1; -+ data.s.did = CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool); -+ data.s.addr = 0; -+ cvmx_send_single(data.u64); -+} -+ -+/** -+ * Free a block allocated with a FPA pool. Does NOT provide memory -+ * ordering in cases where the memory block was modified by the core. -+ * -+ * @ptr: Block to free -+ * @pool: Pool to put it in -+ * @num_cache_lines: -+ * Cache lines to invalidate -+ */ -+static inline void cvmx_fpa_free_nosync(void *ptr, uint64_t pool, -+ uint64_t num_cache_lines) -+{ -+ cvmx_addr_t newptr; -+ newptr.u64 = cvmx_ptr_to_phys(ptr); -+ newptr.sfilldidspace.didspace = -+ CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)); -+ /* Prevent GCC from reordering around free */ -+ barrier(); -+ /* value written is number of cache lines not written back */ -+ cvmx_write_io(newptr.u64, num_cache_lines); -+} -+ -+/** -+ * Free a block allocated with a FPA pool. Provides required memory -+ * ordering in cases where memory block was modified by core. -+ * -+ * @ptr: Block to free -+ * @pool: Pool to put it in -+ * @num_cache_lines: -+ * Cache lines to invalidate -+ */ -+static inline void cvmx_fpa_free(void *ptr, uint64_t pool, -+ uint64_t num_cache_lines) -+{ -+ cvmx_addr_t newptr; -+ newptr.u64 = cvmx_ptr_to_phys(ptr); -+ newptr.sfilldidspace.didspace = -+ CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)); -+ /* -+ * Make sure that any previous writes to memory go out before -+ * we free this buffer. This also serves as a barrier to -+ * prevent GCC from reordering operations to after the -+ * free. -+ */ -+ CVMX_SYNCWS; -+ /* value written is number of cache lines not written back */ -+ cvmx_write_io(newptr.u64, num_cache_lines); -+} -+ -+/** -+ * Setup a FPA pool to control a new block of memory. -+ * This can only be called once per pool. Make sure proper -+ * locking enforces this. -+ * -+ * @pool: Pool to initialize -+ * 0 <= pool < 8 -+ * @name: Constant character string to name this pool. -+ * String is not copied. -+ * @buffer: Pointer to the block of memory to use. This must be -+ * accessable by all processors and external hardware. -+ * @block_size: Size for each block controlled by the FPA -+ * @num_blocks: Number of blocks -+ * -+ * Returns 0 on Success, -+ * -1 on failure -+ */ -+extern int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer, -+ uint64_t block_size, uint64_t num_blocks); -+ -+/** -+ * Shutdown a Memory pool and validate that it had all of -+ * the buffers originally placed in it. This should only be -+ * called by one processor after all hardware has finished -+ * using the pool. -+ * -+ * @pool: Pool to shutdown -+ * Returns Zero on success -+ * - Positive is count of missing buffers -+ * - Negative is too many buffers or corrupted pointers -+ */ -+extern uint64_t cvmx_fpa_shutdown_pool(uint64_t pool); -+ -+/** -+ * Get the size of blocks controlled by the pool -+ * This is resolved to a constant at compile time. -+ * -+ * @pool: Pool to access -+ * Returns Size of the block in bytes -+ */ -+uint64_t cvmx_fpa_get_block_size(uint64_t pool); -+ -+#endif /* __CVM_FPA_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-gmxx-defs.h -@@ -0,0 +1,2529 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_GMXX_DEFS_H__ -+#define __CVMX_GMXX_DEFS_H__ -+ -+#define CVMX_GMXX_BAD_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000518ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_BIST(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000400ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_CLK_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080007F0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_HG2_CONTROL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000550ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_INF_MODE(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080007F8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_NXA_ADR(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000510ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_PRTX_CBFC_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000580ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_PRTX_CFG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000010ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM0(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000180ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM1(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000188ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM2(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000190ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM3(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000198ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM4(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080001A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM5(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080001A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CAM_EN(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000108ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_ADR_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000100ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_DECISION(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000040ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_FRM_CHK(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000020ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_FRM_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000018ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_FRM_MAX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000030ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_FRM_MIN(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000028ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_IFG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000058ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_INT_EN(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000008ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_INT_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000000ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_JABBER(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000038ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_PAUSE_DROP_TIME(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000068ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_RX_INBND(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000060ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000050ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_OCTS(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000088ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_OCTS_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000098ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_OCTS_DMAC(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080000A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_OCTS_DRP(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080000B8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_PKTS(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000080ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_PKTS_BAD(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080000C0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_PKTS_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000090ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_PKTS_DMAC(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080000A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_STATS_PKTS_DRP(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080000B0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RXX_UDD_SKP(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000048ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_BP_DROPX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000420ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_BP_OFFX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000460ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_BP_ONX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000440ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_HG2_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000548ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_PASS_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080005F8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_PASS_MAPX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000600ull + (((offset) & 15) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_PRTS(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000410ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_PRT_INFO(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004E8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_TX_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080007E8ull + (((block_id) & 0) * 0x8000000ull)) -+#define CVMX_GMXX_RX_XAUI_BAD_COL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000538ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_RX_XAUI_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000530ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_SMACX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000230ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_STAT_BP(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000520ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_APPEND(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000218ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_BURST(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000228ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_CBFC_XOFF(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080005A0ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_CBFC_XON(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080005C0ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_CLK(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000208ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000270ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_MIN_PKT(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000240ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000248ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_PAUSE_PKT_TIME(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000238ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_PAUSE_TOGO(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000258ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_PAUSE_ZERO(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000260ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_SGMII_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000300ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_SLOT(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000220ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_SOFT_PAUSE(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000250ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT0(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000280ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT1(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000288ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT2(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000290ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT3(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000298ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT4(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080002A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT5(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080002A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT6(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080002B0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT7(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080002B8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT8(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080002C0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STAT9(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080002C8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_STATS_CTL(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000268ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TXX_THRESH(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000210ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_BP(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004D0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_CLK_MSKX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000780ull + (((offset) & 1) * 8) + (((block_id) & 0) * 0x0ull)) -+#define CVMX_GMXX_TX_COL_ATTEMPT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000498ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_CORRUPT(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004D8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_HG2_REG1(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000558ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_HG2_REG2(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000560ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_IFG(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000488ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_INT_EN(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000508ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_INT_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000500ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_JAM(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000490ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_LFSR(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004F8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_OVR_BP(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004C8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_PAUSE_PKT_DMAC(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004A0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_PAUSE_PKT_TYPE(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004A8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_PRTS(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000480ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_SPI_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004C0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_SPI_DRAIN(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004E0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_SPI_MAX(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004B0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_SPI_ROUNDX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000680ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_SPI_THRESH(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800080004B8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_TX_XAUI_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000528ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_GMXX_XAUI_EXT_LOOPBACK(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180008000540ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_gmxx_bad_reg { -+ uint64_t u64; -+ struct cvmx_gmxx_bad_reg_s { -+ uint64_t reserved_31_63:33; -+ uint64_t inb_nxa:4; -+ uint64_t statovr:1; -+ uint64_t loststat:4; -+ uint64_t reserved_18_21:4; -+ uint64_t out_ovr:16; -+ uint64_t ncb_ovr:1; -+ uint64_t out_col:1; -+ } s; -+ struct cvmx_gmxx_bad_reg_cn30xx { -+ uint64_t reserved_31_63:33; -+ uint64_t inb_nxa:4; -+ uint64_t statovr:1; -+ uint64_t reserved_25_25:1; -+ uint64_t loststat:3; -+ uint64_t reserved_5_21:17; -+ uint64_t out_ovr:3; -+ uint64_t reserved_0_1:2; -+ } cn30xx; -+ struct cvmx_gmxx_bad_reg_cn30xx cn31xx; -+ struct cvmx_gmxx_bad_reg_s cn38xx; -+ struct cvmx_gmxx_bad_reg_s cn38xxp2; -+ struct cvmx_gmxx_bad_reg_cn30xx cn50xx; -+ struct cvmx_gmxx_bad_reg_cn52xx { -+ uint64_t reserved_31_63:33; -+ uint64_t inb_nxa:4; -+ uint64_t statovr:1; -+ uint64_t loststat:4; -+ uint64_t reserved_6_21:16; -+ uint64_t out_ovr:4; -+ uint64_t reserved_0_1:2; -+ } cn52xx; -+ struct cvmx_gmxx_bad_reg_cn52xx cn52xxp1; -+ struct cvmx_gmxx_bad_reg_cn52xx cn56xx; -+ struct cvmx_gmxx_bad_reg_cn52xx cn56xxp1; -+ struct cvmx_gmxx_bad_reg_s cn58xx; -+ struct cvmx_gmxx_bad_reg_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_bist { -+ uint64_t u64; -+ struct cvmx_gmxx_bist_s { -+ uint64_t reserved_17_63:47; -+ uint64_t status:17; -+ } s; -+ struct cvmx_gmxx_bist_cn30xx { -+ uint64_t reserved_10_63:54; -+ uint64_t status:10; -+ } cn30xx; -+ struct cvmx_gmxx_bist_cn30xx cn31xx; -+ struct cvmx_gmxx_bist_cn30xx cn38xx; -+ struct cvmx_gmxx_bist_cn30xx cn38xxp2; -+ struct cvmx_gmxx_bist_cn50xx { -+ uint64_t reserved_12_63:52; -+ uint64_t status:12; -+ } cn50xx; -+ struct cvmx_gmxx_bist_cn52xx { -+ uint64_t reserved_16_63:48; -+ uint64_t status:16; -+ } cn52xx; -+ struct cvmx_gmxx_bist_cn52xx cn52xxp1; -+ struct cvmx_gmxx_bist_cn52xx cn56xx; -+ struct cvmx_gmxx_bist_cn52xx cn56xxp1; -+ struct cvmx_gmxx_bist_s cn58xx; -+ struct cvmx_gmxx_bist_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_clk_en { -+ uint64_t u64; -+ struct cvmx_gmxx_clk_en_s { -+ uint64_t reserved_1_63:63; -+ uint64_t clk_en:1; -+ } s; -+ struct cvmx_gmxx_clk_en_s cn52xx; -+ struct cvmx_gmxx_clk_en_s cn52xxp1; -+ struct cvmx_gmxx_clk_en_s cn56xx; -+ struct cvmx_gmxx_clk_en_s cn56xxp1; -+}; -+ -+union cvmx_gmxx_hg2_control { -+ uint64_t u64; -+ struct cvmx_gmxx_hg2_control_s { -+ uint64_t reserved_19_63:45; -+ uint64_t hg2tx_en:1; -+ uint64_t hg2rx_en:1; -+ uint64_t phys_en:1; -+ uint64_t logl_en:16; -+ } s; -+ struct cvmx_gmxx_hg2_control_s cn52xx; -+ struct cvmx_gmxx_hg2_control_s cn52xxp1; -+ struct cvmx_gmxx_hg2_control_s cn56xx; -+}; -+ -+union cvmx_gmxx_inf_mode { -+ uint64_t u64; -+ struct cvmx_gmxx_inf_mode_s { -+ uint64_t reserved_10_63:54; -+ uint64_t speed:2; -+ uint64_t reserved_6_7:2; -+ uint64_t mode:2; -+ uint64_t reserved_3_3:1; -+ uint64_t p0mii:1; -+ uint64_t en:1; -+ uint64_t type:1; -+ } s; -+ struct cvmx_gmxx_inf_mode_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t p0mii:1; -+ uint64_t en:1; -+ uint64_t type:1; -+ } cn30xx; -+ struct cvmx_gmxx_inf_mode_cn31xx { -+ uint64_t reserved_2_63:62; -+ uint64_t en:1; -+ uint64_t type:1; -+ } cn31xx; -+ struct cvmx_gmxx_inf_mode_cn31xx cn38xx; -+ struct cvmx_gmxx_inf_mode_cn31xx cn38xxp2; -+ struct cvmx_gmxx_inf_mode_cn30xx cn50xx; -+ struct cvmx_gmxx_inf_mode_cn52xx { -+ uint64_t reserved_10_63:54; -+ uint64_t speed:2; -+ uint64_t reserved_6_7:2; -+ uint64_t mode:2; -+ uint64_t reserved_2_3:2; -+ uint64_t en:1; -+ uint64_t type:1; -+ } cn52xx; -+ struct cvmx_gmxx_inf_mode_cn52xx cn52xxp1; -+ struct cvmx_gmxx_inf_mode_cn52xx cn56xx; -+ struct cvmx_gmxx_inf_mode_cn52xx cn56xxp1; -+ struct cvmx_gmxx_inf_mode_cn31xx cn58xx; -+ struct cvmx_gmxx_inf_mode_cn31xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_nxa_adr { -+ uint64_t u64; -+ struct cvmx_gmxx_nxa_adr_s { -+ uint64_t reserved_6_63:58; -+ uint64_t prt:6; -+ } s; -+ struct cvmx_gmxx_nxa_adr_s cn30xx; -+ struct cvmx_gmxx_nxa_adr_s cn31xx; -+ struct cvmx_gmxx_nxa_adr_s cn38xx; -+ struct cvmx_gmxx_nxa_adr_s cn38xxp2; -+ struct cvmx_gmxx_nxa_adr_s cn50xx; -+ struct cvmx_gmxx_nxa_adr_s cn52xx; -+ struct cvmx_gmxx_nxa_adr_s cn52xxp1; -+ struct cvmx_gmxx_nxa_adr_s cn56xx; -+ struct cvmx_gmxx_nxa_adr_s cn56xxp1; -+ struct cvmx_gmxx_nxa_adr_s cn58xx; -+ struct cvmx_gmxx_nxa_adr_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_prtx_cbfc_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_prtx_cbfc_ctl_s { -+ uint64_t phys_en:16; -+ uint64_t logl_en:16; -+ uint64_t phys_bp:16; -+ uint64_t reserved_4_15:12; -+ uint64_t bck_en:1; -+ uint64_t drp_en:1; -+ uint64_t tx_en:1; -+ uint64_t rx_en:1; -+ } s; -+ struct cvmx_gmxx_prtx_cbfc_ctl_s cn52xx; -+ struct cvmx_gmxx_prtx_cbfc_ctl_s cn56xx; -+}; -+ -+union cvmx_gmxx_prtx_cfg { -+ uint64_t u64; -+ struct cvmx_gmxx_prtx_cfg_s { -+ uint64_t reserved_14_63:50; -+ uint64_t tx_idle:1; -+ uint64_t rx_idle:1; -+ uint64_t reserved_9_11:3; -+ uint64_t speed_msb:1; -+ uint64_t reserved_4_7:4; -+ uint64_t slottime:1; -+ uint64_t duplex:1; -+ uint64_t speed:1; -+ uint64_t en:1; -+ } s; -+ struct cvmx_gmxx_prtx_cfg_cn30xx { -+ uint64_t reserved_4_63:60; -+ uint64_t slottime:1; -+ uint64_t duplex:1; -+ uint64_t speed:1; -+ uint64_t en:1; -+ } cn30xx; -+ struct cvmx_gmxx_prtx_cfg_cn30xx cn31xx; -+ struct cvmx_gmxx_prtx_cfg_cn30xx cn38xx; -+ struct cvmx_gmxx_prtx_cfg_cn30xx cn38xxp2; -+ struct cvmx_gmxx_prtx_cfg_cn30xx cn50xx; -+ struct cvmx_gmxx_prtx_cfg_s cn52xx; -+ struct cvmx_gmxx_prtx_cfg_s cn52xxp1; -+ struct cvmx_gmxx_prtx_cfg_s cn56xx; -+ struct cvmx_gmxx_prtx_cfg_s cn56xxp1; -+ struct cvmx_gmxx_prtx_cfg_cn30xx cn58xx; -+ struct cvmx_gmxx_prtx_cfg_cn30xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam0 { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam0_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam0_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam1 { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam1_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam1_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam2 { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam2_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam2_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam3 { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam3_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam3_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam4 { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam4_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam4_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam5 { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam5_s { -+ uint64_t adr:64; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam5_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_cam_en { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_cam_en_s { -+ uint64_t reserved_8_63:56; -+ uint64_t en:8; -+ } s; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_cam_en_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_adr_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_adr_ctl_s { -+ uint64_t reserved_4_63:60; -+ uint64_t cam_mode:1; -+ uint64_t mcst:2; -+ uint64_t bcst:1; -+ } s; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn30xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn31xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn38xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn38xxp2; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn50xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn52xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn52xxp1; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn56xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn56xxp1; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn58xx; -+ struct cvmx_gmxx_rxx_adr_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_decision { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_decision_s { -+ uint64_t reserved_5_63:59; -+ uint64_t cnt:5; -+ } s; -+ struct cvmx_gmxx_rxx_decision_s cn30xx; -+ struct cvmx_gmxx_rxx_decision_s cn31xx; -+ struct cvmx_gmxx_rxx_decision_s cn38xx; -+ struct cvmx_gmxx_rxx_decision_s cn38xxp2; -+ struct cvmx_gmxx_rxx_decision_s cn50xx; -+ struct cvmx_gmxx_rxx_decision_s cn52xx; -+ struct cvmx_gmxx_rxx_decision_s cn52xxp1; -+ struct cvmx_gmxx_rxx_decision_s cn56xx; -+ struct cvmx_gmxx_rxx_decision_s cn56xxp1; -+ struct cvmx_gmxx_rxx_decision_s cn58xx; -+ struct cvmx_gmxx_rxx_decision_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_frm_chk { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_frm_chk_s { -+ uint64_t reserved_10_63:54; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } s; -+ struct cvmx_gmxx_rxx_frm_chk_s cn30xx; -+ struct cvmx_gmxx_rxx_frm_chk_s cn31xx; -+ struct cvmx_gmxx_rxx_frm_chk_s cn38xx; -+ struct cvmx_gmxx_rxx_frm_chk_s cn38xxp2; -+ struct cvmx_gmxx_rxx_frm_chk_cn50xx { -+ uint64_t reserved_10_63:54; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_6_6:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn50xx; -+ struct cvmx_gmxx_rxx_frm_chk_cn52xx { -+ uint64_t reserved_9_63:55; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_5_6:2; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn52xx; -+ struct cvmx_gmxx_rxx_frm_chk_cn52xx cn52xxp1; -+ struct cvmx_gmxx_rxx_frm_chk_cn52xx cn56xx; -+ struct cvmx_gmxx_rxx_frm_chk_cn52xx cn56xxp1; -+ struct cvmx_gmxx_rxx_frm_chk_s cn58xx; -+ struct cvmx_gmxx_rxx_frm_chk_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_frm_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_frm_ctl_s { -+ uint64_t reserved_11_63:53; -+ uint64_t null_dis:1; -+ uint64_t pre_align:1; -+ uint64_t pad_len:1; -+ uint64_t vlan_len:1; -+ uint64_t pre_free:1; -+ uint64_t ctl_smac:1; -+ uint64_t ctl_mcst:1; -+ uint64_t ctl_bck:1; -+ uint64_t ctl_drp:1; -+ uint64_t pre_strp:1; -+ uint64_t pre_chk:1; -+ } s; -+ struct cvmx_gmxx_rxx_frm_ctl_cn30xx { -+ uint64_t reserved_9_63:55; -+ uint64_t pad_len:1; -+ uint64_t vlan_len:1; -+ uint64_t pre_free:1; -+ uint64_t ctl_smac:1; -+ uint64_t ctl_mcst:1; -+ uint64_t ctl_bck:1; -+ uint64_t ctl_drp:1; -+ uint64_t pre_strp:1; -+ uint64_t pre_chk:1; -+ } cn30xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn31xx { -+ uint64_t reserved_8_63:56; -+ uint64_t vlan_len:1; -+ uint64_t pre_free:1; -+ uint64_t ctl_smac:1; -+ uint64_t ctl_mcst:1; -+ uint64_t ctl_bck:1; -+ uint64_t ctl_drp:1; -+ uint64_t pre_strp:1; -+ uint64_t pre_chk:1; -+ } cn31xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn30xx cn38xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn31xx cn38xxp2; -+ struct cvmx_gmxx_rxx_frm_ctl_cn50xx { -+ uint64_t reserved_11_63:53; -+ uint64_t null_dis:1; -+ uint64_t pre_align:1; -+ uint64_t reserved_7_8:2; -+ uint64_t pre_free:1; -+ uint64_t ctl_smac:1; -+ uint64_t ctl_mcst:1; -+ uint64_t ctl_bck:1; -+ uint64_t ctl_drp:1; -+ uint64_t pre_strp:1; -+ uint64_t pre_chk:1; -+ } cn50xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn52xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn52xxp1; -+ struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn56xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn56xxp1 { -+ uint64_t reserved_10_63:54; -+ uint64_t pre_align:1; -+ uint64_t reserved_7_8:2; -+ uint64_t pre_free:1; -+ uint64_t ctl_smac:1; -+ uint64_t ctl_mcst:1; -+ uint64_t ctl_bck:1; -+ uint64_t ctl_drp:1; -+ uint64_t pre_strp:1; -+ uint64_t pre_chk:1; -+ } cn56xxp1; -+ struct cvmx_gmxx_rxx_frm_ctl_s cn58xx; -+ struct cvmx_gmxx_rxx_frm_ctl_cn30xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_frm_max { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_frm_max_s { -+ uint64_t reserved_16_63:48; -+ uint64_t len:16; -+ } s; -+ struct cvmx_gmxx_rxx_frm_max_s cn30xx; -+ struct cvmx_gmxx_rxx_frm_max_s cn31xx; -+ struct cvmx_gmxx_rxx_frm_max_s cn38xx; -+ struct cvmx_gmxx_rxx_frm_max_s cn38xxp2; -+ struct cvmx_gmxx_rxx_frm_max_s cn58xx; -+ struct cvmx_gmxx_rxx_frm_max_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_frm_min { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_frm_min_s { -+ uint64_t reserved_16_63:48; -+ uint64_t len:16; -+ } s; -+ struct cvmx_gmxx_rxx_frm_min_s cn30xx; -+ struct cvmx_gmxx_rxx_frm_min_s cn31xx; -+ struct cvmx_gmxx_rxx_frm_min_s cn38xx; -+ struct cvmx_gmxx_rxx_frm_min_s cn38xxp2; -+ struct cvmx_gmxx_rxx_frm_min_s cn58xx; -+ struct cvmx_gmxx_rxx_frm_min_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_ifg { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_ifg_s { -+ uint64_t reserved_4_63:60; -+ uint64_t ifg:4; -+ } s; -+ struct cvmx_gmxx_rxx_ifg_s cn30xx; -+ struct cvmx_gmxx_rxx_ifg_s cn31xx; -+ struct cvmx_gmxx_rxx_ifg_s cn38xx; -+ struct cvmx_gmxx_rxx_ifg_s cn38xxp2; -+ struct cvmx_gmxx_rxx_ifg_s cn50xx; -+ struct cvmx_gmxx_rxx_ifg_s cn52xx; -+ struct cvmx_gmxx_rxx_ifg_s cn52xxp1; -+ struct cvmx_gmxx_rxx_ifg_s cn56xx; -+ struct cvmx_gmxx_rxx_ifg_s cn56xxp1; -+ struct cvmx_gmxx_rxx_ifg_s cn58xx; -+ struct cvmx_gmxx_rxx_ifg_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_int_en { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_int_en_s { -+ uint64_t reserved_29_63:35; -+ uint64_t hg2cc:1; -+ uint64_t hg2fld:1; -+ uint64_t undat:1; -+ uint64_t uneop:1; -+ uint64_t unsop:1; -+ uint64_t bad_term:1; -+ uint64_t bad_seq:1; -+ uint64_t rem_fault:1; -+ uint64_t loc_fault:1; -+ uint64_t pause_drp:1; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } s; -+ struct cvmx_gmxx_rxx_int_en_cn30xx { -+ uint64_t reserved_19_63:45; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } cn30xx; -+ struct cvmx_gmxx_rxx_int_en_cn30xx cn31xx; -+ struct cvmx_gmxx_rxx_int_en_cn30xx cn38xx; -+ struct cvmx_gmxx_rxx_int_en_cn30xx cn38xxp2; -+ struct cvmx_gmxx_rxx_int_en_cn50xx { -+ uint64_t reserved_20_63:44; -+ uint64_t pause_drp:1; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_6_6:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn50xx; -+ struct cvmx_gmxx_rxx_int_en_cn52xx { -+ uint64_t reserved_29_63:35; -+ uint64_t hg2cc:1; -+ uint64_t hg2fld:1; -+ uint64_t undat:1; -+ uint64_t uneop:1; -+ uint64_t unsop:1; -+ uint64_t bad_term:1; -+ uint64_t bad_seq:1; -+ uint64_t rem_fault:1; -+ uint64_t loc_fault:1; -+ uint64_t pause_drp:1; -+ uint64_t reserved_16_18:3; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t reserved_9_9:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_5_6:2; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn52xx; -+ struct cvmx_gmxx_rxx_int_en_cn52xx cn52xxp1; -+ struct cvmx_gmxx_rxx_int_en_cn52xx cn56xx; -+ struct cvmx_gmxx_rxx_int_en_cn56xxp1 { -+ uint64_t reserved_27_63:37; -+ uint64_t undat:1; -+ uint64_t uneop:1; -+ uint64_t unsop:1; -+ uint64_t bad_term:1; -+ uint64_t bad_seq:1; -+ uint64_t rem_fault:1; -+ uint64_t loc_fault:1; -+ uint64_t pause_drp:1; -+ uint64_t reserved_16_18:3; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t reserved_9_9:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_5_6:2; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn56xxp1; -+ struct cvmx_gmxx_rxx_int_en_cn58xx { -+ uint64_t reserved_20_63:44; -+ uint64_t pause_drp:1; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } cn58xx; -+ struct cvmx_gmxx_rxx_int_en_cn58xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_int_reg { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_int_reg_s { -+ uint64_t reserved_29_63:35; -+ uint64_t hg2cc:1; -+ uint64_t hg2fld:1; -+ uint64_t undat:1; -+ uint64_t uneop:1; -+ uint64_t unsop:1; -+ uint64_t bad_term:1; -+ uint64_t bad_seq:1; -+ uint64_t rem_fault:1; -+ uint64_t loc_fault:1; -+ uint64_t pause_drp:1; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } s; -+ struct cvmx_gmxx_rxx_int_reg_cn30xx { -+ uint64_t reserved_19_63:45; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } cn30xx; -+ struct cvmx_gmxx_rxx_int_reg_cn30xx cn31xx; -+ struct cvmx_gmxx_rxx_int_reg_cn30xx cn38xx; -+ struct cvmx_gmxx_rxx_int_reg_cn30xx cn38xxp2; -+ struct cvmx_gmxx_rxx_int_reg_cn50xx { -+ uint64_t reserved_20_63:44; -+ uint64_t pause_drp:1; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_6_6:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn50xx; -+ struct cvmx_gmxx_rxx_int_reg_cn52xx { -+ uint64_t reserved_29_63:35; -+ uint64_t hg2cc:1; -+ uint64_t hg2fld:1; -+ uint64_t undat:1; -+ uint64_t uneop:1; -+ uint64_t unsop:1; -+ uint64_t bad_term:1; -+ uint64_t bad_seq:1; -+ uint64_t rem_fault:1; -+ uint64_t loc_fault:1; -+ uint64_t pause_drp:1; -+ uint64_t reserved_16_18:3; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t reserved_9_9:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_5_6:2; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn52xx; -+ struct cvmx_gmxx_rxx_int_reg_cn52xx cn52xxp1; -+ struct cvmx_gmxx_rxx_int_reg_cn52xx cn56xx; -+ struct cvmx_gmxx_rxx_int_reg_cn56xxp1 { -+ uint64_t reserved_27_63:37; -+ uint64_t undat:1; -+ uint64_t uneop:1; -+ uint64_t unsop:1; -+ uint64_t bad_term:1; -+ uint64_t bad_seq:1; -+ uint64_t rem_fault:1; -+ uint64_t loc_fault:1; -+ uint64_t pause_drp:1; -+ uint64_t reserved_16_18:3; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t reserved_9_9:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t reserved_5_6:2; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t reserved_2_2:1; -+ uint64_t carext:1; -+ uint64_t reserved_0_0:1; -+ } cn56xxp1; -+ struct cvmx_gmxx_rxx_int_reg_cn58xx { -+ uint64_t reserved_20_63:44; -+ uint64_t pause_drp:1; -+ uint64_t phy_dupx:1; -+ uint64_t phy_spd:1; -+ uint64_t phy_link:1; -+ uint64_t ifgerr:1; -+ uint64_t coldet:1; -+ uint64_t falerr:1; -+ uint64_t rsverr:1; -+ uint64_t pcterr:1; -+ uint64_t ovrerr:1; -+ uint64_t niberr:1; -+ uint64_t skperr:1; -+ uint64_t rcverr:1; -+ uint64_t lenerr:1; -+ uint64_t alnerr:1; -+ uint64_t fcserr:1; -+ uint64_t jabber:1; -+ uint64_t maxerr:1; -+ uint64_t carext:1; -+ uint64_t minerr:1; -+ } cn58xx; -+ struct cvmx_gmxx_rxx_int_reg_cn58xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_jabber { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_jabber_s { -+ uint64_t reserved_16_63:48; -+ uint64_t cnt:16; -+ } s; -+ struct cvmx_gmxx_rxx_jabber_s cn30xx; -+ struct cvmx_gmxx_rxx_jabber_s cn31xx; -+ struct cvmx_gmxx_rxx_jabber_s cn38xx; -+ struct cvmx_gmxx_rxx_jabber_s cn38xxp2; -+ struct cvmx_gmxx_rxx_jabber_s cn50xx; -+ struct cvmx_gmxx_rxx_jabber_s cn52xx; -+ struct cvmx_gmxx_rxx_jabber_s cn52xxp1; -+ struct cvmx_gmxx_rxx_jabber_s cn56xx; -+ struct cvmx_gmxx_rxx_jabber_s cn56xxp1; -+ struct cvmx_gmxx_rxx_jabber_s cn58xx; -+ struct cvmx_gmxx_rxx_jabber_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_pause_drop_time { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_pause_drop_time_s { -+ uint64_t reserved_16_63:48; -+ uint64_t status:16; -+ } s; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn50xx; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn52xx; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn52xxp1; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn56xx; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn56xxp1; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn58xx; -+ struct cvmx_gmxx_rxx_pause_drop_time_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_rx_inbnd { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_rx_inbnd_s { -+ uint64_t reserved_4_63:60; -+ uint64_t duplex:1; -+ uint64_t speed:2; -+ uint64_t status:1; -+ } s; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn30xx; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn31xx; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn38xx; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn38xxp2; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn50xx; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn58xx; -+ struct cvmx_gmxx_rxx_rx_inbnd_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_ctl_s { -+ uint64_t reserved_1_63:63; -+ uint64_t rd_clr:1; -+ } s; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_octs { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_octs_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_gmxx_rxx_stats_octs_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_octs_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_octs_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_octs_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_octs_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_octs_dmac { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_octs_dmac_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_octs_drp { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s { -+ uint64_t reserved_48_63:16; -+ uint64_t cnt:48; -+ } s; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_octs_drp_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_pkts { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_pkts_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_pkts_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_pkts_bad { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_pkts_bad_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_pkts_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_pkts_dmac { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_stats_pkts_drp { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn30xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn31xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn38xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn38xxp2; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn50xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn52xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn52xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn56xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn56xxp1; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn58xx; -+ struct cvmx_gmxx_rxx_stats_pkts_drp_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rxx_udd_skp { -+ uint64_t u64; -+ struct cvmx_gmxx_rxx_udd_skp_s { -+ uint64_t reserved_9_63:55; -+ uint64_t fcssel:1; -+ uint64_t reserved_7_7:1; -+ uint64_t len:7; -+ } s; -+ struct cvmx_gmxx_rxx_udd_skp_s cn30xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn31xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn38xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn38xxp2; -+ struct cvmx_gmxx_rxx_udd_skp_s cn50xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn52xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn52xxp1; -+ struct cvmx_gmxx_rxx_udd_skp_s cn56xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn56xxp1; -+ struct cvmx_gmxx_rxx_udd_skp_s cn58xx; -+ struct cvmx_gmxx_rxx_udd_skp_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_bp_dropx { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_bp_dropx_s { -+ uint64_t reserved_6_63:58; -+ uint64_t mark:6; -+ } s; -+ struct cvmx_gmxx_rx_bp_dropx_s cn30xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn31xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn38xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn38xxp2; -+ struct cvmx_gmxx_rx_bp_dropx_s cn50xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn52xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn52xxp1; -+ struct cvmx_gmxx_rx_bp_dropx_s cn56xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn56xxp1; -+ struct cvmx_gmxx_rx_bp_dropx_s cn58xx; -+ struct cvmx_gmxx_rx_bp_dropx_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_bp_offx { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_bp_offx_s { -+ uint64_t reserved_6_63:58; -+ uint64_t mark:6; -+ } s; -+ struct cvmx_gmxx_rx_bp_offx_s cn30xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn31xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn38xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn38xxp2; -+ struct cvmx_gmxx_rx_bp_offx_s cn50xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn52xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn52xxp1; -+ struct cvmx_gmxx_rx_bp_offx_s cn56xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn56xxp1; -+ struct cvmx_gmxx_rx_bp_offx_s cn58xx; -+ struct cvmx_gmxx_rx_bp_offx_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_bp_onx { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_bp_onx_s { -+ uint64_t reserved_9_63:55; -+ uint64_t mark:9; -+ } s; -+ struct cvmx_gmxx_rx_bp_onx_s cn30xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn31xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn38xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn38xxp2; -+ struct cvmx_gmxx_rx_bp_onx_s cn50xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn52xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn52xxp1; -+ struct cvmx_gmxx_rx_bp_onx_s cn56xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn56xxp1; -+ struct cvmx_gmxx_rx_bp_onx_s cn58xx; -+ struct cvmx_gmxx_rx_bp_onx_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_hg2_status { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_hg2_status_s { -+ uint64_t reserved_48_63:16; -+ uint64_t phtim2go:16; -+ uint64_t xof:16; -+ uint64_t lgtim2go:16; -+ } s; -+ struct cvmx_gmxx_rx_hg2_status_s cn52xx; -+ struct cvmx_gmxx_rx_hg2_status_s cn52xxp1; -+ struct cvmx_gmxx_rx_hg2_status_s cn56xx; -+}; -+ -+union cvmx_gmxx_rx_pass_en { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_pass_en_s { -+ uint64_t reserved_16_63:48; -+ uint64_t en:16; -+ } s; -+ struct cvmx_gmxx_rx_pass_en_s cn38xx; -+ struct cvmx_gmxx_rx_pass_en_s cn38xxp2; -+ struct cvmx_gmxx_rx_pass_en_s cn58xx; -+ struct cvmx_gmxx_rx_pass_en_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_pass_mapx { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_pass_mapx_s { -+ uint64_t reserved_4_63:60; -+ uint64_t dprt:4; -+ } s; -+ struct cvmx_gmxx_rx_pass_mapx_s cn38xx; -+ struct cvmx_gmxx_rx_pass_mapx_s cn38xxp2; -+ struct cvmx_gmxx_rx_pass_mapx_s cn58xx; -+ struct cvmx_gmxx_rx_pass_mapx_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_prt_info { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_prt_info_s { -+ uint64_t reserved_32_63:32; -+ uint64_t drop:16; -+ uint64_t commit:16; -+ } s; -+ struct cvmx_gmxx_rx_prt_info_cn30xx { -+ uint64_t reserved_19_63:45; -+ uint64_t drop:3; -+ uint64_t reserved_3_15:13; -+ uint64_t commit:3; -+ } cn30xx; -+ struct cvmx_gmxx_rx_prt_info_cn30xx cn31xx; -+ struct cvmx_gmxx_rx_prt_info_s cn38xx; -+ struct cvmx_gmxx_rx_prt_info_cn30xx cn50xx; -+ struct cvmx_gmxx_rx_prt_info_cn52xx { -+ uint64_t reserved_20_63:44; -+ uint64_t drop:4; -+ uint64_t reserved_4_15:12; -+ uint64_t commit:4; -+ } cn52xx; -+ struct cvmx_gmxx_rx_prt_info_cn52xx cn52xxp1; -+ struct cvmx_gmxx_rx_prt_info_cn52xx cn56xx; -+ struct cvmx_gmxx_rx_prt_info_cn52xx cn56xxp1; -+ struct cvmx_gmxx_rx_prt_info_s cn58xx; -+ struct cvmx_gmxx_rx_prt_info_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_prts { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_prts_s { -+ uint64_t reserved_3_63:61; -+ uint64_t prts:3; -+ } s; -+ struct cvmx_gmxx_rx_prts_s cn30xx; -+ struct cvmx_gmxx_rx_prts_s cn31xx; -+ struct cvmx_gmxx_rx_prts_s cn38xx; -+ struct cvmx_gmxx_rx_prts_s cn38xxp2; -+ struct cvmx_gmxx_rx_prts_s cn50xx; -+ struct cvmx_gmxx_rx_prts_s cn52xx; -+ struct cvmx_gmxx_rx_prts_s cn52xxp1; -+ struct cvmx_gmxx_rx_prts_s cn56xx; -+ struct cvmx_gmxx_rx_prts_s cn56xxp1; -+ struct cvmx_gmxx_rx_prts_s cn58xx; -+ struct cvmx_gmxx_rx_prts_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_rx_tx_status { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_tx_status_s { -+ uint64_t reserved_7_63:57; -+ uint64_t tx:3; -+ uint64_t reserved_3_3:1; -+ uint64_t rx:3; -+ } s; -+ struct cvmx_gmxx_rx_tx_status_s cn30xx; -+ struct cvmx_gmxx_rx_tx_status_s cn31xx; -+ struct cvmx_gmxx_rx_tx_status_s cn50xx; -+}; -+ -+union cvmx_gmxx_rx_xaui_bad_col { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_xaui_bad_col_s { -+ uint64_t reserved_40_63:24; -+ uint64_t val:1; -+ uint64_t state:3; -+ uint64_t lane_rxc:4; -+ uint64_t lane_rxd:32; -+ } s; -+ struct cvmx_gmxx_rx_xaui_bad_col_s cn52xx; -+ struct cvmx_gmxx_rx_xaui_bad_col_s cn52xxp1; -+ struct cvmx_gmxx_rx_xaui_bad_col_s cn56xx; -+ struct cvmx_gmxx_rx_xaui_bad_col_s cn56xxp1; -+}; -+ -+union cvmx_gmxx_rx_xaui_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_rx_xaui_ctl_s { -+ uint64_t reserved_2_63:62; -+ uint64_t status:2; -+ } s; -+ struct cvmx_gmxx_rx_xaui_ctl_s cn52xx; -+ struct cvmx_gmxx_rx_xaui_ctl_s cn52xxp1; -+ struct cvmx_gmxx_rx_xaui_ctl_s cn56xx; -+ struct cvmx_gmxx_rx_xaui_ctl_s cn56xxp1; -+}; -+ -+union cvmx_gmxx_smacx { -+ uint64_t u64; -+ struct cvmx_gmxx_smacx_s { -+ uint64_t reserved_48_63:16; -+ uint64_t smac:48; -+ } s; -+ struct cvmx_gmxx_smacx_s cn30xx; -+ struct cvmx_gmxx_smacx_s cn31xx; -+ struct cvmx_gmxx_smacx_s cn38xx; -+ struct cvmx_gmxx_smacx_s cn38xxp2; -+ struct cvmx_gmxx_smacx_s cn50xx; -+ struct cvmx_gmxx_smacx_s cn52xx; -+ struct cvmx_gmxx_smacx_s cn52xxp1; -+ struct cvmx_gmxx_smacx_s cn56xx; -+ struct cvmx_gmxx_smacx_s cn56xxp1; -+ struct cvmx_gmxx_smacx_s cn58xx; -+ struct cvmx_gmxx_smacx_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_stat_bp { -+ uint64_t u64; -+ struct cvmx_gmxx_stat_bp_s { -+ uint64_t reserved_17_63:47; -+ uint64_t bp:1; -+ uint64_t cnt:16; -+ } s; -+ struct cvmx_gmxx_stat_bp_s cn30xx; -+ struct cvmx_gmxx_stat_bp_s cn31xx; -+ struct cvmx_gmxx_stat_bp_s cn38xx; -+ struct cvmx_gmxx_stat_bp_s cn38xxp2; -+ struct cvmx_gmxx_stat_bp_s cn50xx; -+ struct cvmx_gmxx_stat_bp_s cn52xx; -+ struct cvmx_gmxx_stat_bp_s cn52xxp1; -+ struct cvmx_gmxx_stat_bp_s cn56xx; -+ struct cvmx_gmxx_stat_bp_s cn56xxp1; -+ struct cvmx_gmxx_stat_bp_s cn58xx; -+ struct cvmx_gmxx_stat_bp_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_append { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_append_s { -+ uint64_t reserved_4_63:60; -+ uint64_t force_fcs:1; -+ uint64_t fcs:1; -+ uint64_t pad:1; -+ uint64_t preamble:1; -+ } s; -+ struct cvmx_gmxx_txx_append_s cn30xx; -+ struct cvmx_gmxx_txx_append_s cn31xx; -+ struct cvmx_gmxx_txx_append_s cn38xx; -+ struct cvmx_gmxx_txx_append_s cn38xxp2; -+ struct cvmx_gmxx_txx_append_s cn50xx; -+ struct cvmx_gmxx_txx_append_s cn52xx; -+ struct cvmx_gmxx_txx_append_s cn52xxp1; -+ struct cvmx_gmxx_txx_append_s cn56xx; -+ struct cvmx_gmxx_txx_append_s cn56xxp1; -+ struct cvmx_gmxx_txx_append_s cn58xx; -+ struct cvmx_gmxx_txx_append_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_burst { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_burst_s { -+ uint64_t reserved_16_63:48; -+ uint64_t burst:16; -+ } s; -+ struct cvmx_gmxx_txx_burst_s cn30xx; -+ struct cvmx_gmxx_txx_burst_s cn31xx; -+ struct cvmx_gmxx_txx_burst_s cn38xx; -+ struct cvmx_gmxx_txx_burst_s cn38xxp2; -+ struct cvmx_gmxx_txx_burst_s cn50xx; -+ struct cvmx_gmxx_txx_burst_s cn52xx; -+ struct cvmx_gmxx_txx_burst_s cn52xxp1; -+ struct cvmx_gmxx_txx_burst_s cn56xx; -+ struct cvmx_gmxx_txx_burst_s cn56xxp1; -+ struct cvmx_gmxx_txx_burst_s cn58xx; -+ struct cvmx_gmxx_txx_burst_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_cbfc_xoff { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_cbfc_xoff_s { -+ uint64_t reserved_16_63:48; -+ uint64_t xoff:16; -+ } s; -+ struct cvmx_gmxx_txx_cbfc_xoff_s cn52xx; -+ struct cvmx_gmxx_txx_cbfc_xoff_s cn56xx; -+}; -+ -+union cvmx_gmxx_txx_cbfc_xon { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_cbfc_xon_s { -+ uint64_t reserved_16_63:48; -+ uint64_t xon:16; -+ } s; -+ struct cvmx_gmxx_txx_cbfc_xon_s cn52xx; -+ struct cvmx_gmxx_txx_cbfc_xon_s cn56xx; -+}; -+ -+union cvmx_gmxx_txx_clk { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_clk_s { -+ uint64_t reserved_6_63:58; -+ uint64_t clk_cnt:6; -+ } s; -+ struct cvmx_gmxx_txx_clk_s cn30xx; -+ struct cvmx_gmxx_txx_clk_s cn31xx; -+ struct cvmx_gmxx_txx_clk_s cn38xx; -+ struct cvmx_gmxx_txx_clk_s cn38xxp2; -+ struct cvmx_gmxx_txx_clk_s cn50xx; -+ struct cvmx_gmxx_txx_clk_s cn58xx; -+ struct cvmx_gmxx_txx_clk_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_ctl_s { -+ uint64_t reserved_2_63:62; -+ uint64_t xsdef_en:1; -+ uint64_t xscol_en:1; -+ } s; -+ struct cvmx_gmxx_txx_ctl_s cn30xx; -+ struct cvmx_gmxx_txx_ctl_s cn31xx; -+ struct cvmx_gmxx_txx_ctl_s cn38xx; -+ struct cvmx_gmxx_txx_ctl_s cn38xxp2; -+ struct cvmx_gmxx_txx_ctl_s cn50xx; -+ struct cvmx_gmxx_txx_ctl_s cn52xx; -+ struct cvmx_gmxx_txx_ctl_s cn52xxp1; -+ struct cvmx_gmxx_txx_ctl_s cn56xx; -+ struct cvmx_gmxx_txx_ctl_s cn56xxp1; -+ struct cvmx_gmxx_txx_ctl_s cn58xx; -+ struct cvmx_gmxx_txx_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_min_pkt { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_min_pkt_s { -+ uint64_t reserved_8_63:56; -+ uint64_t min_size:8; -+ } s; -+ struct cvmx_gmxx_txx_min_pkt_s cn30xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn31xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn38xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn38xxp2; -+ struct cvmx_gmxx_txx_min_pkt_s cn50xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn52xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn52xxp1; -+ struct cvmx_gmxx_txx_min_pkt_s cn56xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn56xxp1; -+ struct cvmx_gmxx_txx_min_pkt_s cn58xx; -+ struct cvmx_gmxx_txx_min_pkt_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_pause_pkt_interval { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s { -+ uint64_t reserved_16_63:48; -+ uint64_t interval:16; -+ } s; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn30xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn31xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn38xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn38xxp2; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn50xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn52xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn52xxp1; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn56xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn56xxp1; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn58xx; -+ struct cvmx_gmxx_txx_pause_pkt_interval_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_pause_pkt_time { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_pause_pkt_time_s { -+ uint64_t reserved_16_63:48; -+ uint64_t time:16; -+ } s; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn30xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn31xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn38xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn38xxp2; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn50xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn52xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn52xxp1; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn56xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn56xxp1; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn58xx; -+ struct cvmx_gmxx_txx_pause_pkt_time_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_pause_togo { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_pause_togo_s { -+ uint64_t reserved_32_63:32; -+ uint64_t msg_time:16; -+ uint64_t time:16; -+ } s; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx { -+ uint64_t reserved_16_63:48; -+ uint64_t time:16; -+ } cn30xx; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn31xx; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn38xx; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn38xxp2; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn50xx; -+ struct cvmx_gmxx_txx_pause_togo_s cn52xx; -+ struct cvmx_gmxx_txx_pause_togo_s cn52xxp1; -+ struct cvmx_gmxx_txx_pause_togo_s cn56xx; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn56xxp1; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn58xx; -+ struct cvmx_gmxx_txx_pause_togo_cn30xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_pause_zero { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_pause_zero_s { -+ uint64_t reserved_1_63:63; -+ uint64_t send:1; -+ } s; -+ struct cvmx_gmxx_txx_pause_zero_s cn30xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn31xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn38xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn38xxp2; -+ struct cvmx_gmxx_txx_pause_zero_s cn50xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn52xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn52xxp1; -+ struct cvmx_gmxx_txx_pause_zero_s cn56xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn56xxp1; -+ struct cvmx_gmxx_txx_pause_zero_s cn58xx; -+ struct cvmx_gmxx_txx_pause_zero_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_sgmii_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_sgmii_ctl_s { -+ uint64_t reserved_1_63:63; -+ uint64_t align:1; -+ } s; -+ struct cvmx_gmxx_txx_sgmii_ctl_s cn52xx; -+ struct cvmx_gmxx_txx_sgmii_ctl_s cn52xxp1; -+ struct cvmx_gmxx_txx_sgmii_ctl_s cn56xx; -+ struct cvmx_gmxx_txx_sgmii_ctl_s cn56xxp1; -+}; -+ -+union cvmx_gmxx_txx_slot { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_slot_s { -+ uint64_t reserved_10_63:54; -+ uint64_t slot:10; -+ } s; -+ struct cvmx_gmxx_txx_slot_s cn30xx; -+ struct cvmx_gmxx_txx_slot_s cn31xx; -+ struct cvmx_gmxx_txx_slot_s cn38xx; -+ struct cvmx_gmxx_txx_slot_s cn38xxp2; -+ struct cvmx_gmxx_txx_slot_s cn50xx; -+ struct cvmx_gmxx_txx_slot_s cn52xx; -+ struct cvmx_gmxx_txx_slot_s cn52xxp1; -+ struct cvmx_gmxx_txx_slot_s cn56xx; -+ struct cvmx_gmxx_txx_slot_s cn56xxp1; -+ struct cvmx_gmxx_txx_slot_s cn58xx; -+ struct cvmx_gmxx_txx_slot_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_soft_pause { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_soft_pause_s { -+ uint64_t reserved_16_63:48; -+ uint64_t time:16; -+ } s; -+ struct cvmx_gmxx_txx_soft_pause_s cn30xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn31xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn38xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn38xxp2; -+ struct cvmx_gmxx_txx_soft_pause_s cn50xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn52xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn52xxp1; -+ struct cvmx_gmxx_txx_soft_pause_s cn56xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn56xxp1; -+ struct cvmx_gmxx_txx_soft_pause_s cn58xx; -+ struct cvmx_gmxx_txx_soft_pause_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat0 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat0_s { -+ uint64_t xsdef:32; -+ uint64_t xscol:32; -+ } s; -+ struct cvmx_gmxx_txx_stat0_s cn30xx; -+ struct cvmx_gmxx_txx_stat0_s cn31xx; -+ struct cvmx_gmxx_txx_stat0_s cn38xx; -+ struct cvmx_gmxx_txx_stat0_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat0_s cn50xx; -+ struct cvmx_gmxx_txx_stat0_s cn52xx; -+ struct cvmx_gmxx_txx_stat0_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat0_s cn56xx; -+ struct cvmx_gmxx_txx_stat0_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat0_s cn58xx; -+ struct cvmx_gmxx_txx_stat0_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat1 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat1_s { -+ uint64_t scol:32; -+ uint64_t mcol:32; -+ } s; -+ struct cvmx_gmxx_txx_stat1_s cn30xx; -+ struct cvmx_gmxx_txx_stat1_s cn31xx; -+ struct cvmx_gmxx_txx_stat1_s cn38xx; -+ struct cvmx_gmxx_txx_stat1_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat1_s cn50xx; -+ struct cvmx_gmxx_txx_stat1_s cn52xx; -+ struct cvmx_gmxx_txx_stat1_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat1_s cn56xx; -+ struct cvmx_gmxx_txx_stat1_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat1_s cn58xx; -+ struct cvmx_gmxx_txx_stat1_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat2 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat2_s { -+ uint64_t reserved_48_63:16; -+ uint64_t octs:48; -+ } s; -+ struct cvmx_gmxx_txx_stat2_s cn30xx; -+ struct cvmx_gmxx_txx_stat2_s cn31xx; -+ struct cvmx_gmxx_txx_stat2_s cn38xx; -+ struct cvmx_gmxx_txx_stat2_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat2_s cn50xx; -+ struct cvmx_gmxx_txx_stat2_s cn52xx; -+ struct cvmx_gmxx_txx_stat2_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat2_s cn56xx; -+ struct cvmx_gmxx_txx_stat2_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat2_s cn58xx; -+ struct cvmx_gmxx_txx_stat2_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat3 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat3_s { -+ uint64_t reserved_32_63:32; -+ uint64_t pkts:32; -+ } s; -+ struct cvmx_gmxx_txx_stat3_s cn30xx; -+ struct cvmx_gmxx_txx_stat3_s cn31xx; -+ struct cvmx_gmxx_txx_stat3_s cn38xx; -+ struct cvmx_gmxx_txx_stat3_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat3_s cn50xx; -+ struct cvmx_gmxx_txx_stat3_s cn52xx; -+ struct cvmx_gmxx_txx_stat3_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat3_s cn56xx; -+ struct cvmx_gmxx_txx_stat3_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat3_s cn58xx; -+ struct cvmx_gmxx_txx_stat3_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat4 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat4_s { -+ uint64_t hist1:32; -+ uint64_t hist0:32; -+ } s; -+ struct cvmx_gmxx_txx_stat4_s cn30xx; -+ struct cvmx_gmxx_txx_stat4_s cn31xx; -+ struct cvmx_gmxx_txx_stat4_s cn38xx; -+ struct cvmx_gmxx_txx_stat4_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat4_s cn50xx; -+ struct cvmx_gmxx_txx_stat4_s cn52xx; -+ struct cvmx_gmxx_txx_stat4_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat4_s cn56xx; -+ struct cvmx_gmxx_txx_stat4_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat4_s cn58xx; -+ struct cvmx_gmxx_txx_stat4_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat5 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat5_s { -+ uint64_t hist3:32; -+ uint64_t hist2:32; -+ } s; -+ struct cvmx_gmxx_txx_stat5_s cn30xx; -+ struct cvmx_gmxx_txx_stat5_s cn31xx; -+ struct cvmx_gmxx_txx_stat5_s cn38xx; -+ struct cvmx_gmxx_txx_stat5_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat5_s cn50xx; -+ struct cvmx_gmxx_txx_stat5_s cn52xx; -+ struct cvmx_gmxx_txx_stat5_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat5_s cn56xx; -+ struct cvmx_gmxx_txx_stat5_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat5_s cn58xx; -+ struct cvmx_gmxx_txx_stat5_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat6 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat6_s { -+ uint64_t hist5:32; -+ uint64_t hist4:32; -+ } s; -+ struct cvmx_gmxx_txx_stat6_s cn30xx; -+ struct cvmx_gmxx_txx_stat6_s cn31xx; -+ struct cvmx_gmxx_txx_stat6_s cn38xx; -+ struct cvmx_gmxx_txx_stat6_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat6_s cn50xx; -+ struct cvmx_gmxx_txx_stat6_s cn52xx; -+ struct cvmx_gmxx_txx_stat6_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat6_s cn56xx; -+ struct cvmx_gmxx_txx_stat6_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat6_s cn58xx; -+ struct cvmx_gmxx_txx_stat6_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat7 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat7_s { -+ uint64_t hist7:32; -+ uint64_t hist6:32; -+ } s; -+ struct cvmx_gmxx_txx_stat7_s cn30xx; -+ struct cvmx_gmxx_txx_stat7_s cn31xx; -+ struct cvmx_gmxx_txx_stat7_s cn38xx; -+ struct cvmx_gmxx_txx_stat7_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat7_s cn50xx; -+ struct cvmx_gmxx_txx_stat7_s cn52xx; -+ struct cvmx_gmxx_txx_stat7_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat7_s cn56xx; -+ struct cvmx_gmxx_txx_stat7_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat7_s cn58xx; -+ struct cvmx_gmxx_txx_stat7_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat8 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat8_s { -+ uint64_t mcst:32; -+ uint64_t bcst:32; -+ } s; -+ struct cvmx_gmxx_txx_stat8_s cn30xx; -+ struct cvmx_gmxx_txx_stat8_s cn31xx; -+ struct cvmx_gmxx_txx_stat8_s cn38xx; -+ struct cvmx_gmxx_txx_stat8_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat8_s cn50xx; -+ struct cvmx_gmxx_txx_stat8_s cn52xx; -+ struct cvmx_gmxx_txx_stat8_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat8_s cn56xx; -+ struct cvmx_gmxx_txx_stat8_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat8_s cn58xx; -+ struct cvmx_gmxx_txx_stat8_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stat9 { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stat9_s { -+ uint64_t undflw:32; -+ uint64_t ctl:32; -+ } s; -+ struct cvmx_gmxx_txx_stat9_s cn30xx; -+ struct cvmx_gmxx_txx_stat9_s cn31xx; -+ struct cvmx_gmxx_txx_stat9_s cn38xx; -+ struct cvmx_gmxx_txx_stat9_s cn38xxp2; -+ struct cvmx_gmxx_txx_stat9_s cn50xx; -+ struct cvmx_gmxx_txx_stat9_s cn52xx; -+ struct cvmx_gmxx_txx_stat9_s cn52xxp1; -+ struct cvmx_gmxx_txx_stat9_s cn56xx; -+ struct cvmx_gmxx_txx_stat9_s cn56xxp1; -+ struct cvmx_gmxx_txx_stat9_s cn58xx; -+ struct cvmx_gmxx_txx_stat9_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_stats_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_stats_ctl_s { -+ uint64_t reserved_1_63:63; -+ uint64_t rd_clr:1; -+ } s; -+ struct cvmx_gmxx_txx_stats_ctl_s cn30xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn31xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn38xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn38xxp2; -+ struct cvmx_gmxx_txx_stats_ctl_s cn50xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn52xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn52xxp1; -+ struct cvmx_gmxx_txx_stats_ctl_s cn56xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn56xxp1; -+ struct cvmx_gmxx_txx_stats_ctl_s cn58xx; -+ struct cvmx_gmxx_txx_stats_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_txx_thresh { -+ uint64_t u64; -+ struct cvmx_gmxx_txx_thresh_s { -+ uint64_t reserved_9_63:55; -+ uint64_t cnt:9; -+ } s; -+ struct cvmx_gmxx_txx_thresh_cn30xx { -+ uint64_t reserved_7_63:57; -+ uint64_t cnt:7; -+ } cn30xx; -+ struct cvmx_gmxx_txx_thresh_cn30xx cn31xx; -+ struct cvmx_gmxx_txx_thresh_s cn38xx; -+ struct cvmx_gmxx_txx_thresh_s cn38xxp2; -+ struct cvmx_gmxx_txx_thresh_cn30xx cn50xx; -+ struct cvmx_gmxx_txx_thresh_s cn52xx; -+ struct cvmx_gmxx_txx_thresh_s cn52xxp1; -+ struct cvmx_gmxx_txx_thresh_s cn56xx; -+ struct cvmx_gmxx_txx_thresh_s cn56xxp1; -+ struct cvmx_gmxx_txx_thresh_s cn58xx; -+ struct cvmx_gmxx_txx_thresh_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_bp { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_bp_s { -+ uint64_t reserved_4_63:60; -+ uint64_t bp:4; -+ } s; -+ struct cvmx_gmxx_tx_bp_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t bp:3; -+ } cn30xx; -+ struct cvmx_gmxx_tx_bp_cn30xx cn31xx; -+ struct cvmx_gmxx_tx_bp_s cn38xx; -+ struct cvmx_gmxx_tx_bp_s cn38xxp2; -+ struct cvmx_gmxx_tx_bp_cn30xx cn50xx; -+ struct cvmx_gmxx_tx_bp_s cn52xx; -+ struct cvmx_gmxx_tx_bp_s cn52xxp1; -+ struct cvmx_gmxx_tx_bp_s cn56xx; -+ struct cvmx_gmxx_tx_bp_s cn56xxp1; -+ struct cvmx_gmxx_tx_bp_s cn58xx; -+ struct cvmx_gmxx_tx_bp_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_clk_mskx { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_clk_mskx_s { -+ uint64_t reserved_1_63:63; -+ uint64_t msk:1; -+ } s; -+ struct cvmx_gmxx_tx_clk_mskx_s cn30xx; -+ struct cvmx_gmxx_tx_clk_mskx_s cn50xx; -+}; -+ -+union cvmx_gmxx_tx_col_attempt { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_col_attempt_s { -+ uint64_t reserved_5_63:59; -+ uint64_t limit:5; -+ } s; -+ struct cvmx_gmxx_tx_col_attempt_s cn30xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn31xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn38xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn38xxp2; -+ struct cvmx_gmxx_tx_col_attempt_s cn50xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn52xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn52xxp1; -+ struct cvmx_gmxx_tx_col_attempt_s cn56xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn56xxp1; -+ struct cvmx_gmxx_tx_col_attempt_s cn58xx; -+ struct cvmx_gmxx_tx_col_attempt_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_corrupt { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_corrupt_s { -+ uint64_t reserved_4_63:60; -+ uint64_t corrupt:4; -+ } s; -+ struct cvmx_gmxx_tx_corrupt_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t corrupt:3; -+ } cn30xx; -+ struct cvmx_gmxx_tx_corrupt_cn30xx cn31xx; -+ struct cvmx_gmxx_tx_corrupt_s cn38xx; -+ struct cvmx_gmxx_tx_corrupt_s cn38xxp2; -+ struct cvmx_gmxx_tx_corrupt_cn30xx cn50xx; -+ struct cvmx_gmxx_tx_corrupt_s cn52xx; -+ struct cvmx_gmxx_tx_corrupt_s cn52xxp1; -+ struct cvmx_gmxx_tx_corrupt_s cn56xx; -+ struct cvmx_gmxx_tx_corrupt_s cn56xxp1; -+ struct cvmx_gmxx_tx_corrupt_s cn58xx; -+ struct cvmx_gmxx_tx_corrupt_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_hg2_reg1 { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_hg2_reg1_s { -+ uint64_t reserved_16_63:48; -+ uint64_t tx_xof:16; -+ } s; -+ struct cvmx_gmxx_tx_hg2_reg1_s cn52xx; -+ struct cvmx_gmxx_tx_hg2_reg1_s cn52xxp1; -+ struct cvmx_gmxx_tx_hg2_reg1_s cn56xx; -+}; -+ -+union cvmx_gmxx_tx_hg2_reg2 { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_hg2_reg2_s { -+ uint64_t reserved_16_63:48; -+ uint64_t tx_xon:16; -+ } s; -+ struct cvmx_gmxx_tx_hg2_reg2_s cn52xx; -+ struct cvmx_gmxx_tx_hg2_reg2_s cn52xxp1; -+ struct cvmx_gmxx_tx_hg2_reg2_s cn56xx; -+}; -+ -+union cvmx_gmxx_tx_ifg { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_ifg_s { -+ uint64_t reserved_8_63:56; -+ uint64_t ifg2:4; -+ uint64_t ifg1:4; -+ } s; -+ struct cvmx_gmxx_tx_ifg_s cn30xx; -+ struct cvmx_gmxx_tx_ifg_s cn31xx; -+ struct cvmx_gmxx_tx_ifg_s cn38xx; -+ struct cvmx_gmxx_tx_ifg_s cn38xxp2; -+ struct cvmx_gmxx_tx_ifg_s cn50xx; -+ struct cvmx_gmxx_tx_ifg_s cn52xx; -+ struct cvmx_gmxx_tx_ifg_s cn52xxp1; -+ struct cvmx_gmxx_tx_ifg_s cn56xx; -+ struct cvmx_gmxx_tx_ifg_s cn56xxp1; -+ struct cvmx_gmxx_tx_ifg_s cn58xx; -+ struct cvmx_gmxx_tx_ifg_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_int_en { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_int_en_s { -+ uint64_t reserved_20_63:44; -+ uint64_t late_col:4; -+ uint64_t xsdef:4; -+ uint64_t xscol:4; -+ uint64_t reserved_6_7:2; -+ uint64_t undflw:4; -+ uint64_t ncb_nxa:1; -+ uint64_t pko_nxa:1; -+ } s; -+ struct cvmx_gmxx_tx_int_en_cn30xx { -+ uint64_t reserved_19_63:45; -+ uint64_t late_col:3; -+ uint64_t reserved_15_15:1; -+ uint64_t xsdef:3; -+ uint64_t reserved_11_11:1; -+ uint64_t xscol:3; -+ uint64_t reserved_5_7:3; -+ uint64_t undflw:3; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn30xx; -+ struct cvmx_gmxx_tx_int_en_cn31xx { -+ uint64_t reserved_15_63:49; -+ uint64_t xsdef:3; -+ uint64_t reserved_11_11:1; -+ uint64_t xscol:3; -+ uint64_t reserved_5_7:3; -+ uint64_t undflw:3; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn31xx; -+ struct cvmx_gmxx_tx_int_en_s cn38xx; -+ struct cvmx_gmxx_tx_int_en_cn38xxp2 { -+ uint64_t reserved_16_63:48; -+ uint64_t xsdef:4; -+ uint64_t xscol:4; -+ uint64_t reserved_6_7:2; -+ uint64_t undflw:4; -+ uint64_t ncb_nxa:1; -+ uint64_t pko_nxa:1; -+ } cn38xxp2; -+ struct cvmx_gmxx_tx_int_en_cn30xx cn50xx; -+ struct cvmx_gmxx_tx_int_en_cn52xx { -+ uint64_t reserved_20_63:44; -+ uint64_t late_col:4; -+ uint64_t xsdef:4; -+ uint64_t xscol:4; -+ uint64_t reserved_6_7:2; -+ uint64_t undflw:4; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn52xx; -+ struct cvmx_gmxx_tx_int_en_cn52xx cn52xxp1; -+ struct cvmx_gmxx_tx_int_en_cn52xx cn56xx; -+ struct cvmx_gmxx_tx_int_en_cn52xx cn56xxp1; -+ struct cvmx_gmxx_tx_int_en_s cn58xx; -+ struct cvmx_gmxx_tx_int_en_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_int_reg { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_int_reg_s { -+ uint64_t reserved_20_63:44; -+ uint64_t late_col:4; -+ uint64_t xsdef:4; -+ uint64_t xscol:4; -+ uint64_t reserved_6_7:2; -+ uint64_t undflw:4; -+ uint64_t ncb_nxa:1; -+ uint64_t pko_nxa:1; -+ } s; -+ struct cvmx_gmxx_tx_int_reg_cn30xx { -+ uint64_t reserved_19_63:45; -+ uint64_t late_col:3; -+ uint64_t reserved_15_15:1; -+ uint64_t xsdef:3; -+ uint64_t reserved_11_11:1; -+ uint64_t xscol:3; -+ uint64_t reserved_5_7:3; -+ uint64_t undflw:3; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn30xx; -+ struct cvmx_gmxx_tx_int_reg_cn31xx { -+ uint64_t reserved_15_63:49; -+ uint64_t xsdef:3; -+ uint64_t reserved_11_11:1; -+ uint64_t xscol:3; -+ uint64_t reserved_5_7:3; -+ uint64_t undflw:3; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn31xx; -+ struct cvmx_gmxx_tx_int_reg_s cn38xx; -+ struct cvmx_gmxx_tx_int_reg_cn38xxp2 { -+ uint64_t reserved_16_63:48; -+ uint64_t xsdef:4; -+ uint64_t xscol:4; -+ uint64_t reserved_6_7:2; -+ uint64_t undflw:4; -+ uint64_t ncb_nxa:1; -+ uint64_t pko_nxa:1; -+ } cn38xxp2; -+ struct cvmx_gmxx_tx_int_reg_cn30xx cn50xx; -+ struct cvmx_gmxx_tx_int_reg_cn52xx { -+ uint64_t reserved_20_63:44; -+ uint64_t late_col:4; -+ uint64_t xsdef:4; -+ uint64_t xscol:4; -+ uint64_t reserved_6_7:2; -+ uint64_t undflw:4; -+ uint64_t reserved_1_1:1; -+ uint64_t pko_nxa:1; -+ } cn52xx; -+ struct cvmx_gmxx_tx_int_reg_cn52xx cn52xxp1; -+ struct cvmx_gmxx_tx_int_reg_cn52xx cn56xx; -+ struct cvmx_gmxx_tx_int_reg_cn52xx cn56xxp1; -+ struct cvmx_gmxx_tx_int_reg_s cn58xx; -+ struct cvmx_gmxx_tx_int_reg_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_jam { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_jam_s { -+ uint64_t reserved_8_63:56; -+ uint64_t jam:8; -+ } s; -+ struct cvmx_gmxx_tx_jam_s cn30xx; -+ struct cvmx_gmxx_tx_jam_s cn31xx; -+ struct cvmx_gmxx_tx_jam_s cn38xx; -+ struct cvmx_gmxx_tx_jam_s cn38xxp2; -+ struct cvmx_gmxx_tx_jam_s cn50xx; -+ struct cvmx_gmxx_tx_jam_s cn52xx; -+ struct cvmx_gmxx_tx_jam_s cn52xxp1; -+ struct cvmx_gmxx_tx_jam_s cn56xx; -+ struct cvmx_gmxx_tx_jam_s cn56xxp1; -+ struct cvmx_gmxx_tx_jam_s cn58xx; -+ struct cvmx_gmxx_tx_jam_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_lfsr { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_lfsr_s { -+ uint64_t reserved_16_63:48; -+ uint64_t lfsr:16; -+ } s; -+ struct cvmx_gmxx_tx_lfsr_s cn30xx; -+ struct cvmx_gmxx_tx_lfsr_s cn31xx; -+ struct cvmx_gmxx_tx_lfsr_s cn38xx; -+ struct cvmx_gmxx_tx_lfsr_s cn38xxp2; -+ struct cvmx_gmxx_tx_lfsr_s cn50xx; -+ struct cvmx_gmxx_tx_lfsr_s cn52xx; -+ struct cvmx_gmxx_tx_lfsr_s cn52xxp1; -+ struct cvmx_gmxx_tx_lfsr_s cn56xx; -+ struct cvmx_gmxx_tx_lfsr_s cn56xxp1; -+ struct cvmx_gmxx_tx_lfsr_s cn58xx; -+ struct cvmx_gmxx_tx_lfsr_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_ovr_bp { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_ovr_bp_s { -+ uint64_t reserved_48_63:16; -+ uint64_t tx_prt_bp:16; -+ uint64_t reserved_12_31:20; -+ uint64_t en:4; -+ uint64_t bp:4; -+ uint64_t ign_full:4; -+ } s; -+ struct cvmx_gmxx_tx_ovr_bp_cn30xx { -+ uint64_t reserved_11_63:53; -+ uint64_t en:3; -+ uint64_t reserved_7_7:1; -+ uint64_t bp:3; -+ uint64_t reserved_3_3:1; -+ uint64_t ign_full:3; -+ } cn30xx; -+ struct cvmx_gmxx_tx_ovr_bp_cn30xx cn31xx; -+ struct cvmx_gmxx_tx_ovr_bp_cn38xx { -+ uint64_t reserved_12_63:52; -+ uint64_t en:4; -+ uint64_t bp:4; -+ uint64_t ign_full:4; -+ } cn38xx; -+ struct cvmx_gmxx_tx_ovr_bp_cn38xx cn38xxp2; -+ struct cvmx_gmxx_tx_ovr_bp_cn30xx cn50xx; -+ struct cvmx_gmxx_tx_ovr_bp_s cn52xx; -+ struct cvmx_gmxx_tx_ovr_bp_s cn52xxp1; -+ struct cvmx_gmxx_tx_ovr_bp_s cn56xx; -+ struct cvmx_gmxx_tx_ovr_bp_s cn56xxp1; -+ struct cvmx_gmxx_tx_ovr_bp_cn38xx cn58xx; -+ struct cvmx_gmxx_tx_ovr_bp_cn38xx cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_pause_pkt_dmac { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s { -+ uint64_t reserved_48_63:16; -+ uint64_t dmac:48; -+ } s; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn30xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn31xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn38xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn38xxp2; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn50xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn52xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn52xxp1; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn56xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn56xxp1; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn58xx; -+ struct cvmx_gmxx_tx_pause_pkt_dmac_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_pause_pkt_type { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_pause_pkt_type_s { -+ uint64_t reserved_16_63:48; -+ uint64_t type:16; -+ } s; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn30xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn31xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn38xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn38xxp2; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn50xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn52xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn52xxp1; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn56xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn56xxp1; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn58xx; -+ struct cvmx_gmxx_tx_pause_pkt_type_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_prts { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_prts_s { -+ uint64_t reserved_5_63:59; -+ uint64_t prts:5; -+ } s; -+ struct cvmx_gmxx_tx_prts_s cn30xx; -+ struct cvmx_gmxx_tx_prts_s cn31xx; -+ struct cvmx_gmxx_tx_prts_s cn38xx; -+ struct cvmx_gmxx_tx_prts_s cn38xxp2; -+ struct cvmx_gmxx_tx_prts_s cn50xx; -+ struct cvmx_gmxx_tx_prts_s cn52xx; -+ struct cvmx_gmxx_tx_prts_s cn52xxp1; -+ struct cvmx_gmxx_tx_prts_s cn56xx; -+ struct cvmx_gmxx_tx_prts_s cn56xxp1; -+ struct cvmx_gmxx_tx_prts_s cn58xx; -+ struct cvmx_gmxx_tx_prts_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_spi_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_spi_ctl_s { -+ uint64_t reserved_2_63:62; -+ uint64_t tpa_clr:1; -+ uint64_t cont_pkt:1; -+ } s; -+ struct cvmx_gmxx_tx_spi_ctl_s cn38xx; -+ struct cvmx_gmxx_tx_spi_ctl_s cn38xxp2; -+ struct cvmx_gmxx_tx_spi_ctl_s cn58xx; -+ struct cvmx_gmxx_tx_spi_ctl_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_spi_drain { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_spi_drain_s { -+ uint64_t reserved_16_63:48; -+ uint64_t drain:16; -+ } s; -+ struct cvmx_gmxx_tx_spi_drain_s cn38xx; -+ struct cvmx_gmxx_tx_spi_drain_s cn58xx; -+ struct cvmx_gmxx_tx_spi_drain_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_spi_max { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_spi_max_s { -+ uint64_t reserved_23_63:41; -+ uint64_t slice:7; -+ uint64_t max2:8; -+ uint64_t max1:8; -+ } s; -+ struct cvmx_gmxx_tx_spi_max_cn38xx { -+ uint64_t reserved_16_63:48; -+ uint64_t max2:8; -+ uint64_t max1:8; -+ } cn38xx; -+ struct cvmx_gmxx_tx_spi_max_cn38xx cn38xxp2; -+ struct cvmx_gmxx_tx_spi_max_s cn58xx; -+ struct cvmx_gmxx_tx_spi_max_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_spi_roundx { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_spi_roundx_s { -+ uint64_t reserved_16_63:48; -+ uint64_t round:16; -+ } s; -+ struct cvmx_gmxx_tx_spi_roundx_s cn58xx; -+ struct cvmx_gmxx_tx_spi_roundx_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_spi_thresh { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_spi_thresh_s { -+ uint64_t reserved_6_63:58; -+ uint64_t thresh:6; -+ } s; -+ struct cvmx_gmxx_tx_spi_thresh_s cn38xx; -+ struct cvmx_gmxx_tx_spi_thresh_s cn38xxp2; -+ struct cvmx_gmxx_tx_spi_thresh_s cn58xx; -+ struct cvmx_gmxx_tx_spi_thresh_s cn58xxp1; -+}; -+ -+union cvmx_gmxx_tx_xaui_ctl { -+ uint64_t u64; -+ struct cvmx_gmxx_tx_xaui_ctl_s { -+ uint64_t reserved_11_63:53; -+ uint64_t hg_pause_hgi:2; -+ uint64_t hg_en:1; -+ uint64_t reserved_7_7:1; -+ uint64_t ls_byp:1; -+ uint64_t ls:2; -+ uint64_t reserved_2_3:2; -+ uint64_t uni_en:1; -+ uint64_t dic_en:1; -+ } s; -+ struct cvmx_gmxx_tx_xaui_ctl_s cn52xx; -+ struct cvmx_gmxx_tx_xaui_ctl_s cn52xxp1; -+ struct cvmx_gmxx_tx_xaui_ctl_s cn56xx; -+ struct cvmx_gmxx_tx_xaui_ctl_s cn56xxp1; -+}; -+ -+union cvmx_gmxx_xaui_ext_loopback { -+ uint64_t u64; -+ struct cvmx_gmxx_xaui_ext_loopback_s { -+ uint64_t reserved_5_63:59; -+ uint64_t en:1; -+ uint64_t thresh:4; -+ } s; -+ struct cvmx_gmxx_xaui_ext_loopback_s cn52xx; -+ struct cvmx_gmxx_xaui_ext_loopback_s cn52xxp1; -+ struct cvmx_gmxx_xaui_ext_loopback_s cn56xx; -+ struct cvmx_gmxx_xaui_ext_loopback_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-board.c -@@ -0,0 +1,706 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Helper functions to abstract board specific data about -+ * network ports from the rest of the cvmx-helper files. -+ */ -+ -+#include -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-mdio.h" -+ -+#include "cvmx-helper.h" -+#include "cvmx-helper-util.h" -+#include "cvmx-helper-board.h" -+ -+#include "cvmx-gmxx-defs.h" -+#include "cvmx-asxx-defs.h" -+ -+/** -+ * cvmx_override_board_link_get(int ipd_port) is a function -+ * pointer. It is meant to allow customization of the process of -+ * talking to a PHY to determine link speed. It is called every -+ * time a PHY must be polled for link status. Users should set -+ * this pointer to a function before calling any cvmx-helper -+ * operations. -+ */ -+cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port) = -+ NULL; -+ -+/** -+ * Return the MII PHY address associated with the given IPD -+ * port. A result of -1 means there isn't a MII capable PHY -+ * connected to this port. On chips supporting multiple MII -+ * busses the bus number is encoded in bits <15:8>. -+ * -+ * This function must be modified for every new Octeon board. -+ * Internally it uses switch statements based on the cvmx_sysinfo -+ * data to determine board types and revisions. It replies on the -+ * fact that every Octeon board receives a unique board type -+ * enumeration from the bootloader. -+ * -+ * @ipd_port: Octeon IPD port to get the MII address for. -+ * -+ * Returns MII PHY address and bus number or -1. -+ */ -+int cvmx_helper_board_get_mii_address(int ipd_port) -+{ -+ switch (cvmx_sysinfo_get()->board_type) { -+ case CVMX_BOARD_TYPE_SIM: -+ /* Simulator doesn't have MII */ -+ return -1; -+ case CVMX_BOARD_TYPE_EBT3000: -+ case CVMX_BOARD_TYPE_EBT5800: -+ case CVMX_BOARD_TYPE_THUNDER: -+ case CVMX_BOARD_TYPE_NICPRO2: -+ /* Interface 0 is SPI4, interface 1 is RGMII */ -+ if ((ipd_port >= 16) && (ipd_port < 20)) -+ return ipd_port - 16; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_KODAMA: -+ case CVMX_BOARD_TYPE_EBH3100: -+ case CVMX_BOARD_TYPE_HIKARI: -+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: -+ case CVMX_BOARD_TYPE_CN3020_EVB_HS5: -+ /* -+ * Port 0 is WAN connected to a PHY, Port 1 is GMII -+ * connected to a switch -+ */ -+ if (ipd_port == 0) -+ return 4; -+ else if (ipd_port == 1) -+ return 9; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_NAC38: -+ /* Board has 8 RGMII ports PHYs are 0-7 */ -+ if ((ipd_port >= 0) && (ipd_port < 4)) -+ return ipd_port; -+ else if ((ipd_port >= 16) && (ipd_port < 20)) -+ return ipd_port - 16 + 4; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_EBH3000: -+ /* Board has dual SPI4 and no PHYs */ -+ return -1; -+ case CVMX_BOARD_TYPE_EBH5200: -+ case CVMX_BOARD_TYPE_EBH5201: -+ case CVMX_BOARD_TYPE_EBT5200: -+ /* -+ * Board has 4 SGMII ports. The PHYs start right after the MII -+ * ports MII0 = 0, MII1 = 1, SGMII = 2-5. -+ */ -+ if ((ipd_port >= 0) && (ipd_port < 4)) -+ return ipd_port + 2; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_EBH5600: -+ case CVMX_BOARD_TYPE_EBH5601: -+ case CVMX_BOARD_TYPE_EBH5610: -+ /* -+ * Board has 8 SGMII ports. 4 connect out, two connect -+ * to a switch, and 2 loop to each other -+ */ -+ if ((ipd_port >= 0) && (ipd_port < 4)) -+ return ipd_port + 1; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_CUST_NB5: -+ if (ipd_port == 2) -+ return 4; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_NIC_XLE_4G: -+ /* Board has 4 SGMII ports. connected QLM3(interface 1) */ -+ if ((ipd_port >= 16) && (ipd_port < 20)) -+ return ipd_port - 16 + 1; -+ else -+ return -1; -+ case CVMX_BOARD_TYPE_BBGW_REF: -+ /* -+ * No PHYs are connected to Octeon, everything is -+ * through switch. -+ */ -+ return -1; -+ } -+ -+ /* Some unknown board. Somebody forgot to update this function... */ -+ cvmx_dprintf -+ ("cvmx_helper_board_get_mii_address: Unknown board type %d\n", -+ cvmx_sysinfo_get()->board_type); -+ return -1; -+} -+ -+/** -+ * This function is the board specific method of determining an -+ * ethernet ports link speed. Most Octeon boards have Marvell PHYs -+ * and are handled by the fall through case. This function must be -+ * updated for boards that don't have the normal Marvell PHYs. -+ * -+ * This function must be modified for every new Octeon board. -+ * Internally it uses switch statements based on the cvmx_sysinfo -+ * data to determine board types and revisions. It relies on the -+ * fact that every Octeon board receives a unique board type -+ * enumeration from the bootloader. -+ * -+ * @ipd_port: IPD input port associated with the port we want to get link -+ * status for. -+ * -+ * Returns The ports link status. If the link isn't fully resolved, this must -+ * return zero. -+ */ -+cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) -+{ -+ cvmx_helper_link_info_t result; -+ int phy_addr; -+ int is_broadcom_phy = 0; -+ -+ /* Give the user a chance to override the processing of this function */ -+ if (cvmx_override_board_link_get) -+ return cvmx_override_board_link_get(ipd_port); -+ -+ /* Unless we fix it later, all links are defaulted to down */ -+ result.u64 = 0; -+ -+ /* -+ * This switch statement should handle all ports that either don't use -+ * Marvell PHYS, or don't support in-band status. -+ */ -+ switch (cvmx_sysinfo_get()->board_type) { -+ case CVMX_BOARD_TYPE_SIM: -+ /* The simulator gives you a simulated 1Gbps full duplex link */ -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ return result; -+ case CVMX_BOARD_TYPE_EBH3100: -+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: -+ case CVMX_BOARD_TYPE_CN3020_EVB_HS5: -+ /* Port 1 on these boards is always Gigabit */ -+ if (ipd_port == 1) { -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ return result; -+ } -+ /* Fall through to the generic code below */ -+ break; -+ case CVMX_BOARD_TYPE_CUST_NB5: -+ /* Port 1 on these boards is always Gigabit */ -+ if (ipd_port == 1) { -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ return result; -+ } else /* The other port uses a broadcom PHY */ -+ is_broadcom_phy = 1; -+ break; -+ case CVMX_BOARD_TYPE_BBGW_REF: -+ /* Port 1 on these boards is always Gigabit */ -+ if (ipd_port == 2) { -+ /* Port 2 is not hooked up */ -+ result.u64 = 0; -+ return result; -+ } else { -+ /* Ports 0 and 1 connect to the switch */ -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ return result; -+ } -+ break; -+ } -+ -+ phy_addr = cvmx_helper_board_get_mii_address(ipd_port); -+ if (phy_addr != -1) { -+ if (is_broadcom_phy) { -+ /* -+ * Below we are going to read SMI/MDIO -+ * register 0x19 which works on Broadcom -+ * parts -+ */ -+ int phy_status = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ 0x19); -+ switch ((phy_status >> 8) & 0x7) { -+ case 0: -+ result.u64 = 0; -+ break; -+ case 1: -+ result.s.link_up = 1; -+ result.s.full_duplex = 0; -+ result.s.speed = 10; -+ break; -+ case 2: -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 10; -+ break; -+ case 3: -+ result.s.link_up = 1; -+ result.s.full_duplex = 0; -+ result.s.speed = 100; -+ break; -+ case 4: -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 100; -+ break; -+ case 5: -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 100; -+ break; -+ case 6: -+ result.s.link_up = 1; -+ result.s.full_duplex = 0; -+ result.s.speed = 1000; -+ break; -+ case 7: -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ break; -+ } -+ } else { -+ /* -+ * This code assumes we are using a Marvell -+ * Gigabit PHY. All the speed information can -+ * be read from register 17 in one -+ * go. Somebody using a different PHY will -+ * need to handle it above in the board -+ * specific area. -+ */ -+ int phy_status = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); -+ -+ /* -+ * If the resolve bit 11 isn't set, see if -+ * autoneg is turned off (bit 12, reg 0). The -+ * resolve bit doesn't get set properly when -+ * autoneg is off, so force it. -+ */ -+ if ((phy_status & (1 << 11)) == 0) { -+ int auto_status = -+ cvmx_mdio_read(phy_addr >> 8, -+ phy_addr & 0xff, 0); -+ if ((auto_status & (1 << 12)) == 0) -+ phy_status |= 1 << 11; -+ } -+ -+ /* -+ * Only return a link if the PHY has finished -+ * auto negotiation and set the resolved bit -+ * (bit 11) -+ */ -+ if (phy_status & (1 << 11)) { -+ result.s.link_up = 1; -+ result.s.full_duplex = ((phy_status >> 13) & 1); -+ switch ((phy_status >> 14) & 3) { -+ case 0: /* 10 Mbps */ -+ result.s.speed = 10; -+ break; -+ case 1: /* 100 Mbps */ -+ result.s.speed = 100; -+ break; -+ case 2: /* 1 Gbps */ -+ result.s.speed = 1000; -+ break; -+ case 3: /* Illegal */ -+ result.u64 = 0; -+ break; -+ } -+ } -+ } -+ } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ /* -+ * We don't have a PHY address, so attempt to use -+ * in-band status. It is really important that boards -+ * not supporting in-band status never get -+ * here. Reading broken in-band status tends to do bad -+ * things -+ */ -+ union cvmx_gmxx_rxx_rx_inbnd inband_status; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ inband_status.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); -+ -+ result.s.link_up = inband_status.s.status; -+ result.s.full_duplex = inband_status.s.duplex; -+ switch (inband_status.s.speed) { -+ case 0: /* 10 Mbps */ -+ result.s.speed = 10; -+ break; -+ case 1: /* 100 Mbps */ -+ result.s.speed = 100; -+ break; -+ case 2: /* 1 Gbps */ -+ result.s.speed = 1000; -+ break; -+ case 3: /* Illegal */ -+ result.u64 = 0; -+ break; -+ } -+ } else { -+ /* -+ * We don't have a PHY address and we don't have -+ * in-band status. There is no way to determine the -+ * link speed. Return down assuming this port isn't -+ * wired -+ */ -+ result.u64 = 0; -+ } -+ -+ /* If link is down, return all fields as zero. */ -+ if (!result.s.link_up) -+ result.u64 = 0; -+ -+ return result; -+} -+ -+/** -+ * This function as a board specific method of changing the PHY -+ * speed, duplex, and auto-negotiation. This programs the PHY and -+ * not Octeon. This can be used to force Octeon's links to -+ * specific settings. -+ * -+ * @phy_addr: The address of the PHY to program -+ * @enable_autoneg: -+ * Non zero if you want to enable auto-negotiation. -+ * @link_info: Link speed to program. If the speed is zero and auto-negotiation -+ * is enabled, all possible negotiation speeds are advertised. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_helper_board_link_set_phy(int phy_addr, -+ cvmx_helper_board_set_phy_link_flags_types_t -+ link_flags, -+ cvmx_helper_link_info_t link_info) -+{ -+ -+ /* Set the flow control settings based on link_flags */ -+ if ((link_flags & set_phy_link_flags_flow_control_mask) != -+ set_phy_link_flags_flow_control_dont_touch) { -+ cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; -+ reg_autoneg_adver.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_AUTONEG_ADVER); -+ reg_autoneg_adver.s.asymmetric_pause = -+ (link_flags & set_phy_link_flags_flow_control_mask) == -+ set_phy_link_flags_flow_control_enable; -+ reg_autoneg_adver.s.pause = -+ (link_flags & set_phy_link_flags_flow_control_mask) == -+ set_phy_link_flags_flow_control_enable; -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_AUTONEG_ADVER, -+ reg_autoneg_adver.u16); -+ } -+ -+ /* If speed isn't set and autoneg is on advertise all supported modes */ -+ if ((link_flags & set_phy_link_flags_autoneg) -+ && (link_info.s.speed == 0)) { -+ cvmx_mdio_phy_reg_control_t reg_control; -+ cvmx_mdio_phy_reg_status_t reg_status; -+ cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; -+ cvmx_mdio_phy_reg_extended_status_t reg_extended_status; -+ cvmx_mdio_phy_reg_control_1000_t reg_control_1000; -+ -+ reg_status.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_STATUS); -+ reg_autoneg_adver.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_AUTONEG_ADVER); -+ reg_autoneg_adver.s.advert_100base_t4 = -+ reg_status.s.capable_100base_t4; -+ reg_autoneg_adver.s.advert_10base_tx_full = -+ reg_status.s.capable_10_full; -+ reg_autoneg_adver.s.advert_10base_tx_half = -+ reg_status.s.capable_10_half; -+ reg_autoneg_adver.s.advert_100base_tx_full = -+ reg_status.s.capable_100base_x_full; -+ reg_autoneg_adver.s.advert_100base_tx_half = -+ reg_status.s.capable_100base_x_half; -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_AUTONEG_ADVER, -+ reg_autoneg_adver.u16); -+ if (reg_status.s.capable_extended_status) { -+ reg_extended_status.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_EXTENDED_STATUS); -+ reg_control_1000.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL_1000); -+ reg_control_1000.s.advert_1000base_t_full = -+ reg_extended_status.s.capable_1000base_t_full; -+ reg_control_1000.s.advert_1000base_t_half = -+ reg_extended_status.s.capable_1000base_t_half; -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL_1000, -+ reg_control_1000.u16); -+ } -+ reg_control.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL); -+ reg_control.s.autoneg_enable = 1; -+ reg_control.s.restart_autoneg = 1; -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); -+ } else if ((link_flags & set_phy_link_flags_autoneg)) { -+ cvmx_mdio_phy_reg_control_t reg_control; -+ cvmx_mdio_phy_reg_status_t reg_status; -+ cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; -+ cvmx_mdio_phy_reg_extended_status_t reg_extended_status; -+ cvmx_mdio_phy_reg_control_1000_t reg_control_1000; -+ -+ reg_status.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_STATUS); -+ reg_autoneg_adver.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_AUTONEG_ADVER); -+ reg_autoneg_adver.s.advert_100base_t4 = 0; -+ reg_autoneg_adver.s.advert_10base_tx_full = 0; -+ reg_autoneg_adver.s.advert_10base_tx_half = 0; -+ reg_autoneg_adver.s.advert_100base_tx_full = 0; -+ reg_autoneg_adver.s.advert_100base_tx_half = 0; -+ if (reg_status.s.capable_extended_status) { -+ reg_extended_status.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_EXTENDED_STATUS); -+ reg_control_1000.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL_1000); -+ reg_control_1000.s.advert_1000base_t_full = 0; -+ reg_control_1000.s.advert_1000base_t_half = 0; -+ } -+ switch (link_info.s.speed) { -+ case 10: -+ reg_autoneg_adver.s.advert_10base_tx_full = -+ link_info.s.full_duplex; -+ reg_autoneg_adver.s.advert_10base_tx_half = -+ !link_info.s.full_duplex; -+ break; -+ case 100: -+ reg_autoneg_adver.s.advert_100base_tx_full = -+ link_info.s.full_duplex; -+ reg_autoneg_adver.s.advert_100base_tx_half = -+ !link_info.s.full_duplex; -+ break; -+ case 1000: -+ reg_control_1000.s.advert_1000base_t_full = -+ link_info.s.full_duplex; -+ reg_control_1000.s.advert_1000base_t_half = -+ !link_info.s.full_duplex; -+ break; -+ } -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_AUTONEG_ADVER, -+ reg_autoneg_adver.u16); -+ if (reg_status.s.capable_extended_status) -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL_1000, -+ reg_control_1000.u16); -+ reg_control.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL); -+ reg_control.s.autoneg_enable = 1; -+ reg_control.s.restart_autoneg = 1; -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); -+ } else { -+ cvmx_mdio_phy_reg_control_t reg_control; -+ reg_control.u16 = -+ cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL); -+ reg_control.s.autoneg_enable = 0; -+ reg_control.s.restart_autoneg = 1; -+ reg_control.s.duplex = link_info.s.full_duplex; -+ if (link_info.s.speed == 1000) { -+ reg_control.s.speed_msb = 1; -+ reg_control.s.speed_lsb = 0; -+ } else if (link_info.s.speed == 100) { -+ reg_control.s.speed_msb = 0; -+ reg_control.s.speed_lsb = 1; -+ } else if (link_info.s.speed == 10) { -+ reg_control.s.speed_msb = 0; -+ reg_control.s.speed_lsb = 0; -+ } -+ cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, -+ CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); -+ } -+ return 0; -+} -+ -+/** -+ * This function is called by cvmx_helper_interface_probe() after it -+ * determines the number of ports Octeon can support on a specific -+ * interface. This function is the per board location to override -+ * this value. It is called with the number of ports Octeon might -+ * support and should return the number of actual ports on the -+ * board. -+ * -+ * This function must be modifed for every new Octeon board. -+ * Internally it uses switch statements based on the cvmx_sysinfo -+ * data to determine board types and revisions. It relys on the -+ * fact that every Octeon board receives a unique board type -+ * enumeration from the bootloader. -+ * -+ * @interface: Interface to probe -+ * @supported_ports: -+ * Number of ports Octeon supports. -+ * -+ * Returns Number of ports the actual board supports. Many times this will -+ * simple be "support_ports". -+ */ -+int __cvmx_helper_board_interface_probe(int interface, int supported_ports) -+{ -+ switch (cvmx_sysinfo_get()->board_type) { -+ case CVMX_BOARD_TYPE_CN3005_EVB_HS5: -+ if (interface == 0) -+ return 2; -+ break; -+ case CVMX_BOARD_TYPE_BBGW_REF: -+ if (interface == 0) -+ return 2; -+ break; -+ case CVMX_BOARD_TYPE_NIC_XLE_4G: -+ if (interface == 0) -+ return 0; -+ break; -+ /* The 2nd interface on the EBH5600 is connected to the Marvel switch, -+ which we don't support. Disable ports connected to it */ -+ case CVMX_BOARD_TYPE_EBH5600: -+ if (interface == 1) -+ return 0; -+ break; -+ } -+ return supported_ports; -+} -+ -+/** -+ * Enable packet input/output from the hardware. This function is -+ * called after by cvmx_helper_packet_hardware_enable() to -+ * perform board specific initialization. For most boards -+ * nothing is needed. -+ * -+ * @interface: Interface to enable -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_board_hardware_enable(int interface) -+{ -+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) { -+ if (interface == 0) { -+ /* Different config for switch port */ -+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); -+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); -+ /* -+ * Boards with gigabit WAN ports need a -+ * different setting that is compatible with -+ * 100 Mbit settings -+ */ -+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), -+ 0xc); -+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), -+ 0xc); -+ } -+ } else if (cvmx_sysinfo_get()->board_type == -+ CVMX_BOARD_TYPE_CN3010_EVB_HS5) { -+ /* -+ * Broadcom PHYs require differnet ASX -+ * clocks. Unfortunately many boards don't define a -+ * new board Id and simply mangle the -+ * CN3010_EVB_HS5 -+ */ -+ if (interface == 0) { -+ /* -+ * Some boards use a hacked up bootloader that -+ * identifies them as CN3010_EVB_HS5 -+ * evaluation boards. This leads to all kinds -+ * of configuration problems. Detect one -+ * case, and print warning, while trying to do -+ * the right thing. -+ */ -+ int phy_addr = cvmx_helper_board_get_mii_address(0); -+ if (phy_addr != -1) { -+ int phy_identifier = -+ cvmx_mdio_read(phy_addr >> 8, -+ phy_addr & 0xff, 0x2); -+ /* Is it a Broadcom PHY? */ -+ if (phy_identifier == 0x0143) { -+ cvmx_dprintf("\n"); -+ cvmx_dprintf("ERROR:\n"); -+ cvmx_dprintf -+ ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); -+ cvmx_dprintf -+ ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); -+ cvmx_dprintf -+ ("ERROR: All boards require a unique board type to identify them.\n"); -+ cvmx_dprintf("ERROR:\n"); -+ cvmx_dprintf("\n"); -+ cvmx_wait(1000000000); -+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX -+ (0, interface), 5); -+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX -+ (0, interface), 5); -+ } -+ } -+ } -+ } -+ return 0; -+} -+ -+cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) -+{ -+ switch (cvmx_sysinfo_get()->board_type) { -+ case CVMX_BOARD_TYPE_BBGW_REF: -+ return USB_CLOCK_TYPE_CRYSTAL_12; -+ } -+ return USB_CLOCK_TYPE_REF_48; -+} -+ -+int __cvmx_helper_board_usb_get_num_ports(int supported_ports) -+{ -+ switch (cvmx_sysinfo_get()->board_type) { -+ case CVMX_BOARD_TYPE_NIC_XLE_4G: -+ return 0; -+ } -+ -+ return supported_ports; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-board.h -@@ -0,0 +1,180 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Helper functions to abstract board specific data about -+ * network ports from the rest of the cvmx-helper files. -+ * -+ */ -+#ifndef __CVMX_HELPER_BOARD_H__ -+#define __CVMX_HELPER_BOARD_H__ -+ -+#include "cvmx-helper.h" -+ -+typedef enum { -+ USB_CLOCK_TYPE_REF_12, -+ USB_CLOCK_TYPE_REF_24, -+ USB_CLOCK_TYPE_REF_48, -+ USB_CLOCK_TYPE_CRYSTAL_12, -+} cvmx_helper_board_usb_clock_types_t; -+ -+typedef enum { -+ set_phy_link_flags_autoneg = 0x1, -+ set_phy_link_flags_flow_control_dont_touch = 0x0 << 1, -+ set_phy_link_flags_flow_control_enable = 0x1 << 1, -+ set_phy_link_flags_flow_control_disable = 0x2 << 1, -+ set_phy_link_flags_flow_control_mask = 0x3 << 1, /* Mask for 2 bit wide flow control field */ -+} cvmx_helper_board_set_phy_link_flags_types_t; -+ -+/** -+ * cvmx_override_board_link_get(int ipd_port) is a function -+ * pointer. It is meant to allow customization of the process of -+ * talking to a PHY to determine link speed. It is called every -+ * time a PHY must be polled for link status. Users should set -+ * this pointer to a function before calling any cvmx-helper -+ * operations. -+ */ -+extern cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port); -+ -+/** -+ * Return the MII PHY address associated with the given IPD -+ * port. A result of -1 means there isn't a MII capable PHY -+ * connected to this port. On chips supporting multiple MII -+ * busses the bus number is encoded in bits <15:8>. -+ * -+ * This function must be modifed for every new Octeon board. -+ * Internally it uses switch statements based on the cvmx_sysinfo -+ * data to determine board types and revisions. It relys on the -+ * fact that every Octeon board receives a unique board type -+ * enumeration from the bootloader. -+ * -+ * @ipd_port: Octeon IPD port to get the MII address for. -+ * -+ * Returns MII PHY address and bus number or -1. -+ */ -+extern int cvmx_helper_board_get_mii_address(int ipd_port); -+ -+/** -+ * This function as a board specific method of changing the PHY -+ * speed, duplex, and autonegotiation. This programs the PHY and -+ * not Octeon. This can be used to force Octeon's links to -+ * specific settings. -+ * -+ * @phy_addr: The address of the PHY to program -+ * @link_flags: -+ * Flags to control autonegotiation. Bit 0 is autonegotiation -+ * enable/disable to maintain backware compatability. -+ * @link_info: Link speed to program. If the speed is zero and autonegotiation -+ * is enabled, all possible negotiation speeds are advertised. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_helper_board_link_set_phy(int phy_addr, -+ cvmx_helper_board_set_phy_link_flags_types_t -+ link_flags, -+ cvmx_helper_link_info_t link_info); -+ -+/** -+ * This function is the board specific method of determining an -+ * ethernet ports link speed. Most Octeon boards have Marvell PHYs -+ * and are handled by the fall through case. This function must be -+ * updated for boards that don't have the normal Marvell PHYs. -+ * -+ * This function must be modifed for every new Octeon board. -+ * Internally it uses switch statements based on the cvmx_sysinfo -+ * data to determine board types and revisions. It relys on the -+ * fact that every Octeon board receives a unique board type -+ * enumeration from the bootloader. -+ * -+ * @ipd_port: IPD input port associated with the port we want to get link -+ * status for. -+ * -+ * Returns The ports link status. If the link isn't fully resolved, this must -+ * return zero. -+ */ -+extern cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port); -+ -+/** -+ * This function is called by cvmx_helper_interface_probe() after it -+ * determines the number of ports Octeon can support on a specific -+ * interface. This function is the per board location to override -+ * this value. It is called with the number of ports Octeon might -+ * support and should return the number of actual ports on the -+ * board. -+ * -+ * This function must be modifed for every new Octeon board. -+ * Internally it uses switch statements based on the cvmx_sysinfo -+ * data to determine board types and revisions. It relys on the -+ * fact that every Octeon board receives a unique board type -+ * enumeration from the bootloader. -+ * -+ * @interface: Interface to probe -+ * @supported_ports: -+ * Number of ports Octeon supports. -+ * -+ * Returns Number of ports the actual board supports. Many times this will -+ * simple be "support_ports". -+ */ -+extern int __cvmx_helper_board_interface_probe(int interface, -+ int supported_ports); -+ -+/** -+ * Enable packet input/output from the hardware. This function is -+ * called after by cvmx_helper_packet_hardware_enable() to -+ * perform board specific initialization. For most boards -+ * nothing is needed. -+ * -+ * @interface: Interface to enable -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_board_hardware_enable(int interface); -+ -+/** -+ * Gets the clock type used for the USB block based on board type. -+ * Used by the USB code for auto configuration of clock type. -+ * -+ * Returns USB clock type enumeration -+ */ -+cvmx_helper_board_usb_clock_types_t -+__cvmx_helper_board_usb_get_clock_type(void); -+ -+/** -+ * Adjusts the number of available USB ports on Octeon based on board -+ * specifics. -+ * -+ * @supported_ports: expected number of ports based on chip type; -+ * -+ * -+ * Returns number of available usb ports, based on board specifics. -+ * Return value is supported_ports if function does not -+ * override. -+ */ -+int __cvmx_helper_board_usb_get_num_ports(int supported_ports); -+ -+#endif /* __CVMX_HELPER_BOARD_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-fpa.c -@@ -0,0 +1,243 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Helper functions for FPA setup. -+ * -+ */ -+#include "executive-config.h" -+#include "cvmx-config.h" -+#include "cvmx.h" -+#include "cvmx-bootmem.h" -+#include "cvmx-fpa.h" -+#include "cvmx-helper-fpa.h" -+ -+/** -+ * Allocate memory for and initialize a single FPA pool. -+ * -+ * @pool: Pool to initialize -+ * @buffer_size: Size of buffers to allocate in bytes -+ * @buffers: Number of buffers to put in the pool. Zero is allowed -+ * @name: String name of the pool for debugging purposes -+ * Returns Zero on success, non-zero on failure -+ */ -+static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size, -+ uint64_t buffers, const char *name) -+{ -+ uint64_t current_num; -+ void *memory; -+ uint64_t align = CVMX_CACHE_LINE_SIZE; -+ -+ /* -+ * Align the allocation so that power of 2 size buffers are -+ * naturally aligned. -+ */ -+ while (align < buffer_size) -+ align = align << 1; -+ -+ if (buffers == 0) -+ return 0; -+ -+ current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool)); -+ if (current_num) { -+ cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. " -+ "Skipping setup.\n", -+ pool, name, (unsigned long long)current_num); -+ return 0; -+ } -+ -+ memory = cvmx_bootmem_alloc(buffer_size * buffers, align); -+ if (memory == NULL) { -+ cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n", -+ pool, name); -+ return -1; -+ } -+ cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers); -+ return 0; -+} -+ -+/** -+ * Allocate memory and initialize the FPA pools using memory -+ * from cvmx-bootmem. Specifying zero for the number of -+ * buffers will cause that FPA pool to not be setup. This is -+ * useful if you aren't using some of the hardware and want -+ * to save memory. Use cvmx_helper_initialize_fpa instead of -+ * this function directly. -+ * -+ * @pip_pool: Should always be CVMX_FPA_PACKET_POOL -+ * @pip_size: Should always be CVMX_FPA_PACKET_POOL_SIZE -+ * @pip_buffers: -+ * Number of packet buffers. -+ * @wqe_pool: Should always be CVMX_FPA_WQE_POOL -+ * @wqe_size: Should always be CVMX_FPA_WQE_POOL_SIZE -+ * @wqe_entries: -+ * Number of work queue entries -+ * @pko_pool: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL -+ * @pko_size: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE -+ * @pko_buffers: -+ * PKO Command buffers. You should at minimum have two per -+ * each PKO queue. -+ * @tim_pool: Should always be CVMX_FPA_TIMER_POOL -+ * @tim_size: Should always be CVMX_FPA_TIMER_POOL_SIZE -+ * @tim_buffers: -+ * TIM ring buffer command queues. At least two per timer bucket -+ * is recommened. -+ * @dfa_pool: Should always be CVMX_FPA_DFA_POOL -+ * @dfa_size: Should always be CVMX_FPA_DFA_POOL_SIZE -+ * @dfa_buffers: -+ * DFA command buffer. A relatively small (32 for example) -+ * number should work. -+ * Returns Zero on success, non-zero if out of memory -+ */ -+static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size, -+ int pip_buffers, int wqe_pool, -+ int wqe_size, int wqe_entries, -+ int pko_pool, int pko_size, -+ int pko_buffers, int tim_pool, -+ int tim_size, int tim_buffers, -+ int dfa_pool, int dfa_size, -+ int dfa_buffers) -+{ -+ int status; -+ -+ cvmx_fpa_enable(); -+ -+ if ((pip_buffers > 0) && (pip_buffers <= 64)) -+ cvmx_dprintf -+ ("Warning: %d packet buffers may not be enough for hardware" -+ " prefetch. 65 or more is recommended.\n", pip_buffers); -+ -+ if (pip_pool >= 0) { -+ status = -+ __cvmx_helper_initialize_fpa_pool(pip_pool, pip_size, -+ pip_buffers, -+ "Packet Buffers"); -+ if (status) -+ return status; -+ } -+ -+ if (wqe_pool >= 0) { -+ status = -+ __cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size, -+ wqe_entries, -+ "Work Queue Entries"); -+ if (status) -+ return status; -+ } -+ -+ if (pko_pool >= 0) { -+ status = -+ __cvmx_helper_initialize_fpa_pool(pko_pool, pko_size, -+ pko_buffers, -+ "PKO Command Buffers"); -+ if (status) -+ return status; -+ } -+ -+ if (tim_pool >= 0) { -+ status = -+ __cvmx_helper_initialize_fpa_pool(tim_pool, tim_size, -+ tim_buffers, -+ "TIM Command Buffers"); -+ if (status) -+ return status; -+ } -+ -+ if (dfa_pool >= 0) { -+ status = -+ __cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size, -+ dfa_buffers, -+ "DFA Command Buffers"); -+ if (status) -+ return status; -+ } -+ -+ return 0; -+} -+ -+/** -+ * Allocate memory and initialize the FPA pools using memory -+ * from cvmx-bootmem. Sizes of each element in the pools is -+ * controlled by the cvmx-config.h header file. Specifying -+ * zero for any parameter will cause that FPA pool to not be -+ * setup. This is useful if you aren't using some of the -+ * hardware and want to save memory. -+ * -+ * @packet_buffers: -+ * Number of packet buffers to allocate -+ * @work_queue_entries: -+ * Number of work queue entries -+ * @pko_buffers: -+ * PKO Command buffers. You should at minimum have two per -+ * each PKO queue. -+ * @tim_buffers: -+ * TIM ring buffer command queues. At least two per timer bucket -+ * is recommened. -+ * @dfa_buffers: -+ * DFA command buffer. A relatively small (32 for example) -+ * number should work. -+ * Returns Zero on success, non-zero if out of memory -+ */ -+int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries, -+ int pko_buffers, int tim_buffers, -+ int dfa_buffers) -+{ -+#ifndef CVMX_FPA_PACKET_POOL -+#define CVMX_FPA_PACKET_POOL -1 -+#define CVMX_FPA_PACKET_POOL_SIZE 0 -+#endif -+#ifndef CVMX_FPA_WQE_POOL -+#define CVMX_FPA_WQE_POOL -1 -+#define CVMX_FPA_WQE_POOL_SIZE 0 -+#endif -+#ifndef CVMX_FPA_OUTPUT_BUFFER_POOL -+#define CVMX_FPA_OUTPUT_BUFFER_POOL -1 -+#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0 -+#endif -+#ifndef CVMX_FPA_TIMER_POOL -+#define CVMX_FPA_TIMER_POOL -1 -+#define CVMX_FPA_TIMER_POOL_SIZE 0 -+#endif -+#ifndef CVMX_FPA_DFA_POOL -+#define CVMX_FPA_DFA_POOL -1 -+#define CVMX_FPA_DFA_POOL_SIZE 0 -+#endif -+ return __cvmx_helper_initialize_fpa(CVMX_FPA_PACKET_POOL, -+ CVMX_FPA_PACKET_POOL_SIZE, -+ packet_buffers, CVMX_FPA_WQE_POOL, -+ CVMX_FPA_WQE_POOL_SIZE, -+ work_queue_entries, -+ CVMX_FPA_OUTPUT_BUFFER_POOL, -+ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, -+ pko_buffers, CVMX_FPA_TIMER_POOL, -+ CVMX_FPA_TIMER_POOL_SIZE, -+ tim_buffers, CVMX_FPA_DFA_POOL, -+ CVMX_FPA_DFA_POOL_SIZE, -+ dfa_buffers); -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-fpa.h -@@ -0,0 +1,64 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Helper functions for FPA setup. -+ * -+ */ -+#ifndef __CVMX_HELPER_H_FPA__ -+#define __CVMX_HELPER_H_FPA__ -+ -+/** -+ * Allocate memory and initialize the FPA pools using memory -+ * from cvmx-bootmem. Sizes of each element in the pools is -+ * controlled by the cvmx-config.h header file. Specifying -+ * zero for any parameter will cause that FPA pool to not be -+ * setup. This is useful if you aren't using some of the -+ * hardware and want to save memory. -+ * -+ * @packet_buffers: -+ * Number of packet buffers to allocate -+ * @work_queue_entries: -+ * Number of work queue entries -+ * @pko_buffers: -+ * PKO Command buffers. You should at minimum have two per -+ * each PKO queue. -+ * @tim_buffers: -+ * TIM ring buffer command queues. At least two per timer bucket -+ * is recommened. -+ * @dfa_buffers: -+ * DFA command buffer. A relatively small (32 for example) -+ * number should work. -+ * Returns Zero on success, non-zero if out of memory -+ */ -+extern int cvmx_helper_initialize_fpa(int packet_buffers, -+ int work_queue_entries, int pko_buffers, -+ int tim_buffers, int dfa_buffers); -+ -+#endif /* __CVMX_HELPER_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-loop.c -@@ -0,0 +1,85 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Functions for LOOP initialization, configuration, -+ * and monitoring. -+ */ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-helper.h" -+#include "cvmx-pip-defs.h" -+ -+/** -+ * Probe a LOOP interface and determine the number of ports -+ * connected to it. The LOOP interface should still be down -+ * after this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+int __cvmx_helper_loop_probe(int interface) -+{ -+ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; -+ int num_ports = 4; -+ int port; -+ -+ /* We need to disable length checking so packet < 64 bytes and jumbo -+ frames don't get errors */ -+ for (port = 0; port < num_ports; port++) { -+ union cvmx_pip_prt_cfgx port_cfg; -+ int ipd_port = cvmx_helper_get_ipd_port(interface, port); -+ port_cfg.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); -+ port_cfg.s.maxerr_en = 0; -+ port_cfg.s.minerr_en = 0; -+ cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_cfg.u64); -+ } -+ -+ /* Disable FCS stripping for loopback ports */ -+ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); -+ ipd_sub_port_fcs.s.port_bit2 = 0; -+ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); -+ return num_ports; -+} -+ -+/** -+ * Bringup and enable a LOOP interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_loop_enable(int interface) -+{ -+ /* Do nothing. */ -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-loop.h -@@ -0,0 +1,59 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as published by -+ * the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, -+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. -+ * See the GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Functions for LOOP initialization, configuration, -+ * and monitoring. -+ * -+ */ -+#ifndef __CVMX_HELPER_LOOP_H__ -+#define __CVMX_HELPER_LOOP_H__ -+ -+/** -+ * Probe a LOOP interface and determine the number of ports -+ * connected to it. The LOOP interface should still be down after -+ * this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+extern int __cvmx_helper_loop_probe(int interface); -+ -+/** -+ * Bringup and enable a LOOP interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_loop_enable(int interface); -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-npi.c -@@ -0,0 +1,113 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Functions for NPI initialization, configuration, -+ * and monitoring. -+ */ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-helper.h" -+ -+#include "cvmx-pip-defs.h" -+ -+/** -+ * Probe a NPI interface and determine the number of ports -+ * connected to it. The NPI interface should still be down -+ * after this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+int __cvmx_helper_npi_probe(int interface) -+{ -+#if CVMX_PKO_QUEUES_PER_PORT_PCI > 0 -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) -+ return 4; -+ else if (OCTEON_IS_MODEL(OCTEON_CN56XX) -+ && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) -+ /* The packet engines didn't exist before pass 2 */ -+ return 4; -+ else if (OCTEON_IS_MODEL(OCTEON_CN52XX) -+ && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) -+ /* The packet engines didn't exist before pass 2 */ -+ return 4; -+#if 0 -+ /* -+ * Technically CN30XX, CN31XX, and CN50XX contain packet -+ * engines, but nobody ever uses them. Since this is the case, -+ * we disable them here. -+ */ -+ else if (OCTEON_IS_MODEL(OCTEON_CN31XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)) -+ return 2; -+ else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) -+ return 1; -+#endif -+#endif -+ return 0; -+} -+ -+/** -+ * Bringup and enable a NPI interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_npi_enable(int interface) -+{ -+ /* -+ * On CN50XX, CN52XX, and CN56XX we need to disable length -+ * checking so packet < 64 bytes and jumbo frames don't get -+ * errors. -+ */ -+ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && -+ !OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ int num_ports = cvmx_helper_ports_on_interface(interface); -+ int port; -+ for (port = 0; port < num_ports; port++) { -+ union cvmx_pip_prt_cfgx port_cfg; -+ int ipd_port = -+ cvmx_helper_get_ipd_port(interface, port); -+ port_cfg.u64 = -+ cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); -+ port_cfg.s.maxerr_en = 0; -+ port_cfg.s.minerr_en = 0; -+ cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), -+ port_cfg.u64); -+ } -+ } -+ -+ /* Enables are controlled by the remote host, so nothing to do here */ -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-npi.h -@@ -0,0 +1,60 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Functions for NPI initialization, configuration, -+ * and monitoring. -+ * -+ */ -+#ifndef __CVMX_HELPER_NPI_H__ -+#define __CVMX_HELPER_NPI_H__ -+ -+/** -+ * Probe a NPI interface and determine the number of ports -+ * connected to it. The NPI interface should still be down after -+ * this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+extern int __cvmx_helper_npi_probe(int interface); -+ -+/** -+ * Bringup and enable a NPI interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_npi_enable(int interface); -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-rgmii.c -@@ -0,0 +1,525 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Functions for RGMII/GMII/MII initialization, configuration, -+ * and monitoring. -+ */ -+#include -+ -+#include "cvmx-config.h" -+ -+ -+#include "cvmx-mdio.h" -+#include "cvmx-pko.h" -+#include "cvmx-helper.h" -+#include "cvmx-helper-board.h" -+ -+#include -+#include "cvmx-gmxx-defs.h" -+#include "cvmx-asxx-defs.h" -+#include "cvmx-dbg-defs.h" -+ -+void __cvmx_interrupt_gmxx_enable(int interface); -+void __cvmx_interrupt_asxx_enable(int block); -+ -+/** -+ * Probe RGMII ports and determine the number present -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of RGMII/GMII/MII ports (0-4). -+ */ -+int __cvmx_helper_rgmii_probe(int interface) -+{ -+ int num_ports = 0; -+ union cvmx_gmxx_inf_mode mode; -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ -+ if (mode.s.type) { -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ cvmx_dprintf("ERROR: RGMII initialize called in " -+ "SPI interface\n"); -+ } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) -+ || OCTEON_IS_MODEL(OCTEON_CN30XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ /* -+ * On these chips "type" says we're in -+ * GMII/MII mode. This limits us to 2 ports -+ */ -+ num_ports = 2; -+ } else { -+ cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", -+ __func__); -+ } -+ } else { -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ num_ports = 4; -+ } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) -+ || OCTEON_IS_MODEL(OCTEON_CN30XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ num_ports = 3; -+ } else { -+ cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", -+ __func__); -+ } -+ } -+ return num_ports; -+} -+ -+/** -+ * Put an RGMII interface in loopback mode. Internal packets sent -+ * out will be received back again on the same port. Externally -+ * received packets will echo back out. -+ * -+ * @port: IPD port number to loop. -+ */ -+void cvmx_helper_rgmii_internal_loopback(int port) -+{ -+ int interface = (port >> 4) & 1; -+ int index = port & 0xf; -+ uint64_t tmp; -+ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ gmx_cfg.u64 = 0; -+ gmx_cfg.s.duplex = 1; -+ gmx_cfg.s.slottime = 1; -+ gmx_cfg.s.speed = 1; -+ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ tmp = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); -+ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), (1 << index) | tmp); -+ tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface)); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), (1 << index) | tmp); -+ tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), (1 << index) | tmp); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+} -+ -+/** -+ * Workaround ASX setup errata with CN38XX pass1 -+ * -+ * @interface: Interface to setup -+ * @port: Port to setup (0..3) -+ * @cpu_clock_hz: -+ * Chip frequency in Hertz -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_errata_asx_pass1(int interface, int port, -+ int cpu_clock_hz) -+{ -+ /* Set hi water mark as per errata GMX-4 */ -+ if (cpu_clock_hz >= 325000000 && cpu_clock_hz < 375000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 12); -+ else if (cpu_clock_hz >= 375000000 && cpu_clock_hz < 437000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 11); -+ else if (cpu_clock_hz >= 437000000 && cpu_clock_hz < 550000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 10); -+ else if (cpu_clock_hz >= 550000000 && cpu_clock_hz < 687000000) -+ cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 9); -+ else -+ cvmx_dprintf("Illegal clock frequency (%d). " -+ "CVMX_ASXX_TX_HI_WATERX not set\n", cpu_clock_hz); -+ return 0; -+} -+ -+/** -+ * Configure all of the ASX, GMX, and PKO regsiters required -+ * to get RGMII to function on the supplied interface. -+ * -+ * @interface: PKO Interface to configure (0 or 1) -+ * -+ * Returns Zero on success -+ */ -+int __cvmx_helper_rgmii_enable(int interface) -+{ -+ int num_ports = cvmx_helper_ports_on_interface(interface); -+ int port; -+ struct cvmx_sysinfo *sys_info_ptr = cvmx_sysinfo_get(); -+ union cvmx_gmxx_inf_mode mode; -+ union cvmx_asxx_tx_prt_en asx_tx; -+ union cvmx_asxx_rx_prt_en asx_rx; -+ -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ -+ if (mode.s.en == 0) -+ return -1; -+ if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || -+ OCTEON_IS_MODEL(OCTEON_CN58XX)) && mode.s.type == 1) -+ /* Ignore SPI interfaces */ -+ return -1; -+ -+ /* Configure the ASX registers needed to use the RGMII ports */ -+ asx_tx.u64 = 0; -+ asx_tx.s.prt_en = cvmx_build_mask(num_ports); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), asx_tx.u64); -+ -+ asx_rx.u64 = 0; -+ asx_rx.s.prt_en = cvmx_build_mask(num_ports); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), asx_rx.u64); -+ -+ /* Configure the GMX registers needed to use the RGMII ports */ -+ for (port = 0; port < num_ports; port++) { -+ /* Setting of CVMX_GMXX_TXX_THRESH has been moved to -+ __cvmx_helper_setup_gmx() */ -+ -+ if (cvmx_octeon_is_pass1()) -+ __cvmx_helper_errata_asx_pass1(interface, port, -+ sys_info_ptr-> -+ cpu_clock_hz); -+ else { -+ /* -+ * Configure more flexible RGMII preamble -+ * checking. Pass 1 doesn't support this -+ * feature. -+ */ -+ union cvmx_gmxx_rxx_frm_ctl frm_ctl; -+ frm_ctl.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL -+ (port, interface)); -+ /* New field, so must be compile time */ -+ frm_ctl.s.pre_free = 1; -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface), -+ frm_ctl.u64); -+ } -+ -+ /* -+ * Each pause frame transmitted will ask for about 10M -+ * bit times before resume. If buffer space comes -+ * available before that time has expired, an XON -+ * pause frame (0 time) will be transmitted to restart -+ * the flow. -+ */ -+ cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_TIME(port, interface), -+ 20000); -+ cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL -+ (port, interface), 19000); -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), -+ 16); -+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), -+ 16); -+ } else { -+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), -+ 24); -+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), -+ 24); -+ } -+ } -+ -+ __cvmx_helper_setup_gmx(interface, num_ports); -+ -+ /* enable the ports now */ -+ for (port = 0; port < num_ports; port++) { -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port -+ (interface, port)); -+ gmx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(port, interface)); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(port, interface), -+ gmx_cfg.u64); -+ } -+ __cvmx_interrupt_asxx_enable(interface); -+ __cvmx_interrupt_gmxx_enable(interface); -+ -+ return 0; -+} -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+cvmx_helper_link_info_t __cvmx_helper_rgmii_link_get(int ipd_port) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ union cvmx_asxx_prt_loop asxx_prt_loop; -+ -+ asxx_prt_loop.u64 = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); -+ if (asxx_prt_loop.s.int_loop & (1 << index)) { -+ /* Force 1Gbps full duplex on internal loopback */ -+ cvmx_helper_link_info_t result; -+ result.u64 = 0; -+ result.s.full_duplex = 1; -+ result.s.link_up = 1; -+ result.s.speed = 1000; -+ return result; -+ } else -+ return __cvmx_helper_board_link_get(ipd_port); -+} -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_rgmii_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info) -+{ -+ int result = 0; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ union cvmx_gmxx_prtx_cfg original_gmx_cfg; -+ union cvmx_gmxx_prtx_cfg new_gmx_cfg; -+ union cvmx_pko_mem_queue_qos pko_mem_queue_qos; -+ union cvmx_pko_mem_queue_qos pko_mem_queue_qos_save[16]; -+ union cvmx_gmxx_tx_ovr_bp gmx_tx_ovr_bp; -+ union cvmx_gmxx_tx_ovr_bp gmx_tx_ovr_bp_save; -+ int i; -+ -+ /* Ignore speed sets in the simulator */ -+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) -+ return 0; -+ -+ /* Read the current settings so we know the current enable state */ -+ original_gmx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ new_gmx_cfg = original_gmx_cfg; -+ -+ /* Disable the lowest level RX */ -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), -+ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) & -+ ~(1 << index)); -+ -+ /* Disable all queues so that TX should become idle */ -+ for (i = 0; i < cvmx_pko_get_num_queues(ipd_port); i++) { -+ int queue = cvmx_pko_get_base_queue(ipd_port) + i; -+ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue); -+ pko_mem_queue_qos.u64 = cvmx_read_csr(CVMX_PKO_MEM_QUEUE_QOS); -+ pko_mem_queue_qos.s.pid = ipd_port; -+ pko_mem_queue_qos.s.qid = queue; -+ pko_mem_queue_qos_save[i] = pko_mem_queue_qos; -+ pko_mem_queue_qos.s.qos_mask = 0; -+ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, pko_mem_queue_qos.u64); -+ } -+ -+ /* Disable backpressure */ -+ gmx_tx_ovr_bp.u64 = cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface)); -+ gmx_tx_ovr_bp_save = gmx_tx_ovr_bp; -+ gmx_tx_ovr_bp.s.bp &= ~(1 << index); -+ gmx_tx_ovr_bp.s.en |= 1 << index; -+ cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp.u64); -+ cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface)); -+ -+ /* -+ * Poll the GMX state machine waiting for it to become -+ * idle. Preferably we should only change speed when it is -+ * idle. If it doesn't become idle we will still do the speed -+ * change, but there is a slight chance that GMX will -+ * lockup. -+ */ -+ cvmx_write_csr(CVMX_NPI_DBG_SELECT, -+ interface * 0x800 + index * 0x100 + 0x880); -+ CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data, data & 7, -+ ==, 0, 10000); -+ CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data, data & 0xf, -+ ==, 0, 10000); -+ -+ /* Disable the port before we make any changes */ -+ new_gmx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64); -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ -+ /* Set full/half duplex */ -+ if (cvmx_octeon_is_pass1()) -+ /* Half duplex is broken for 38XX Pass 1 */ -+ new_gmx_cfg.s.duplex = 1; -+ else if (!link_info.s.link_up) -+ /* Force full duplex on down links */ -+ new_gmx_cfg.s.duplex = 1; -+ else -+ new_gmx_cfg.s.duplex = link_info.s.full_duplex; -+ -+ /* Set the link speed. Anything unknown is set to 1Gbps */ -+ if (link_info.s.speed == 10) { -+ new_gmx_cfg.s.slottime = 0; -+ new_gmx_cfg.s.speed = 0; -+ } else if (link_info.s.speed == 100) { -+ new_gmx_cfg.s.slottime = 0; -+ new_gmx_cfg.s.speed = 0; -+ } else { -+ new_gmx_cfg.s.slottime = 1; -+ new_gmx_cfg.s.speed = 1; -+ } -+ -+ /* Adjust the clocks */ -+ if (link_info.s.speed == 10) { -+ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 50); -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); -+ } else if (link_info.s.speed == 100) { -+ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 5); -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); -+ } else { -+ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); -+ } -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ if ((link_info.s.speed == 10) || (link_info.s.speed == 100)) { -+ union cvmx_gmxx_inf_mode mode; -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ -+ /* -+ * Port .en .type .p0mii Configuration -+ * ---- --- ----- ------ ----------------------------------------- -+ * X 0 X X All links are disabled. -+ * 0 1 X 0 Port 0 is RGMII -+ * 0 1 X 1 Port 0 is MII -+ * 1 1 0 X Ports 1 and 2 are configured as RGMII ports. -+ * 1 1 1 X Port 1: GMII/MII; Port 2: disabled. GMII or -+ * MII port is selected by GMX_PRT1_CFG[SPEED]. -+ */ -+ -+ /* In MII mode, CLK_CNT = 1. */ -+ if (((index == 0) && (mode.s.p0mii == 1)) -+ || ((index != 0) && (mode.s.type == 1))) { -+ cvmx_write_csr(CVMX_GMXX_TXX_CLK -+ (index, interface), 1); -+ } -+ } -+ } -+ -+ /* Do a read to make sure all setup stuff is complete */ -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ -+ /* Save the new GMX setting without enabling the port */ -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64); -+ -+ /* Enable the lowest level RX */ -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), -+ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) | (1 << -+ index)); -+ -+ /* Re-enable the TX path */ -+ for (i = 0; i < cvmx_pko_get_num_queues(ipd_port); i++) { -+ int queue = cvmx_pko_get_base_queue(ipd_port) + i; -+ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue); -+ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, -+ pko_mem_queue_qos_save[i].u64); -+ } -+ -+ /* Restore backpressure */ -+ cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp_save.u64); -+ -+ /* Restore the GMX enable state. Port config is complete */ -+ new_gmx_cfg.s.en = original_gmx_cfg.s.en; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64); -+ -+ return result; -+} -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+int __cvmx_helper_rgmii_configure_loopback(int ipd_port, int enable_internal, -+ int enable_external) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ int original_enable; -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ union cvmx_asxx_prt_loop asxx_prt_loop; -+ -+ /* Read the current enable state and save it */ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ original_enable = gmx_cfg.s.en; -+ /* Force port to be disabled */ -+ gmx_cfg.s.en = 0; -+ if (enable_internal) { -+ /* Force speed if we're doing internal loopback */ -+ gmx_cfg.s.duplex = 1; -+ gmx_cfg.s.slottime = 1; -+ gmx_cfg.s.speed = 1; -+ cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); -+ } -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ -+ /* Set the loopback bits */ -+ asxx_prt_loop.u64 = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); -+ if (enable_internal) -+ asxx_prt_loop.s.int_loop |= 1 << index; -+ else -+ asxx_prt_loop.s.int_loop &= ~(1 << index); -+ if (enable_external) -+ asxx_prt_loop.s.ext_loop |= 1 << index; -+ else -+ asxx_prt_loop.s.ext_loop &= ~(1 << index); -+ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), asxx_prt_loop.u64); -+ -+ /* Force enables in internal loopback */ -+ if (enable_internal) { -+ uint64_t tmp; -+ tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface)); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), -+ (1 << index) | tmp); -+ tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), -+ (1 << index) | tmp); -+ original_enable = 1; -+ } -+ -+ /* Restore the enable state */ -+ gmx_cfg.s.en = original_enable; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-rgmii.h -@@ -0,0 +1,110 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Functions for RGMII/GMII/MII initialization, configuration, -+ * and monitoring. -+ * -+ */ -+#ifndef __CVMX_HELPER_RGMII_H__ -+#define __CVMX_HELPER_RGMII_H__ -+ -+/** -+ * Probe RGMII ports and determine the number present -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of RGMII/GMII/MII ports (0-4). -+ */ -+extern int __cvmx_helper_rgmii_probe(int interface); -+ -+/** -+ * Put an RGMII interface in loopback mode. Internal packets sent -+ * out will be received back again on the same port. Externally -+ * received packets will echo back out. -+ * -+ * @port: IPD port number to loop. -+ */ -+extern void cvmx_helper_rgmii_internal_loopback(int port); -+ -+/** -+ * Configure all of the ASX, GMX, and PKO regsiters required -+ * to get RGMII to function on the supplied interface. -+ * -+ * @interface: PKO Interface to configure (0 or 1) -+ * -+ * Returns Zero on success -+ */ -+extern int __cvmx_helper_rgmii_enable(int interface); -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+extern cvmx_helper_link_info_t __cvmx_helper_rgmii_link_get(int ipd_port); -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_rgmii_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info); -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+extern int __cvmx_helper_rgmii_configure_loopback(int ipd_port, -+ int enable_internal, -+ int enable_external); -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-sgmii.c -@@ -0,0 +1,550 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Functions for SGMII initialization, configuration, -+ * and monitoring. -+ */ -+ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-mdio.h" -+#include "cvmx-helper.h" -+#include "cvmx-helper-board.h" -+ -+#include "cvmx-gmxx-defs.h" -+#include "cvmx-pcsx-defs.h" -+ -+void __cvmx_interrupt_gmxx_enable(int interface); -+void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block); -+void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index); -+ -+/** -+ * Perform initialization required only once for an SGMII port. -+ * -+ * @interface: Interface to init -+ * @index: Index of prot on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index) -+{ -+ const uint64_t clock_mhz = cvmx_sysinfo_get()->cpu_clock_hz / 1000000; -+ union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg; -+ union cvmx_pcsx_linkx_timer_count_reg pcsx_linkx_timer_count_reg; -+ union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg; -+ -+ /* Disable GMX */ -+ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmxx_prtx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); -+ -+ /* -+ * Write PCS*_LINK*_TIMER_COUNT_REG[COUNT] with the -+ * appropriate value. 1000BASE-X specifies a 10ms -+ * interval. SGMII specifies a 1.6ms interval. -+ */ -+ pcs_misc_ctl_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); -+ pcsx_linkx_timer_count_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface)); -+ if (pcs_misc_ctl_reg.s.mode) { -+ /* 1000BASE-X */ -+ pcsx_linkx_timer_count_reg.s.count = -+ (10000ull * clock_mhz) >> 10; -+ } else { -+ /* SGMII */ -+ pcsx_linkx_timer_count_reg.s.count = -+ (1600ull * clock_mhz) >> 10; -+ } -+ cvmx_write_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface), -+ pcsx_linkx_timer_count_reg.u64); -+ -+ /* -+ * Write the advertisement register to be used as the -+ * tx_Config_Reg of the autonegotiation. In -+ * 1000BASE-X mode, tx_Config_Reg is PCS*_AN*_ADV_REG. -+ * In SGMII PHY mode, tx_Config_Reg is -+ * PCS*_SGM*_AN_ADV_REG. In SGMII MAC mode, -+ * tx_Config_Reg is the fixed value 0x4001, so this -+ * step can be skipped. -+ */ -+ if (pcs_misc_ctl_reg.s.mode) { -+ /* 1000BASE-X */ -+ union cvmx_pcsx_anx_adv_reg pcsx_anx_adv_reg; -+ pcsx_anx_adv_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface)); -+ pcsx_anx_adv_reg.s.rem_flt = 0; -+ pcsx_anx_adv_reg.s.pause = 3; -+ pcsx_anx_adv_reg.s.hfd = 1; -+ pcsx_anx_adv_reg.s.fd = 1; -+ cvmx_write_csr(CVMX_PCSX_ANX_ADV_REG(index, interface), -+ pcsx_anx_adv_reg.u64); -+ } else { -+ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; -+ pcsx_miscx_ctl_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); -+ if (pcsx_miscx_ctl_reg.s.mac_phy) { -+ /* PHY Mode */ -+ union cvmx_pcsx_sgmx_an_adv_reg pcsx_sgmx_an_adv_reg; -+ pcsx_sgmx_an_adv_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_SGMX_AN_ADV_REG -+ (index, interface)); -+ pcsx_sgmx_an_adv_reg.s.link = 1; -+ pcsx_sgmx_an_adv_reg.s.dup = 1; -+ pcsx_sgmx_an_adv_reg.s.speed = 2; -+ cvmx_write_csr(CVMX_PCSX_SGMX_AN_ADV_REG -+ (index, interface), -+ pcsx_sgmx_an_adv_reg.u64); -+ } else { -+ /* MAC Mode - Nothing to do */ -+ } -+ } -+ return 0; -+} -+ -+/** -+ * Initialize the SERTES link for the first time or after a loss -+ * of link. -+ * -+ * @interface: Interface to init -+ * @index: Index of prot on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index) -+{ -+ union cvmx_pcsx_mrx_control_reg control_reg; -+ -+ /* -+ * Take PCS through a reset sequence. -+ * PCS*_MR*_CONTROL_REG[PWR_DN] should be cleared to zero. -+ * Write PCS*_MR*_CONTROL_REG[RESET]=1 (while not changing the -+ * value of the other PCS*_MR*_CONTROL_REG bits). Read -+ * PCS*_MR*_CONTROL_REG[RESET] until it changes value to -+ * zero. -+ */ -+ control_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface)); -+ if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) { -+ control_reg.s.reset = 1; -+ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), -+ control_reg.u64); -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_PCSX_MRX_CONTROL_REG(index, interface), -+ union cvmx_pcsx_mrx_control_reg, reset, ==, 0, 10000)) { -+ cvmx_dprintf("SGMII%d: Timeout waiting for port %d " -+ "to finish reset\n", -+ interface, index); -+ return -1; -+ } -+ } -+ -+ /* -+ * Write PCS*_MR*_CONTROL_REG[RST_AN]=1 to ensure a fresh -+ * sgmii negotiation starts. -+ */ -+ control_reg.s.rst_an = 1; -+ control_reg.s.an_en = 1; -+ control_reg.s.pwr_dn = 0; -+ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), -+ control_reg.u64); -+ -+ /* -+ * Wait for PCS*_MR*_STATUS_REG[AN_CPT] to be set, indicating -+ * that sgmii autonegotiation is complete. In MAC mode this -+ * isn't an ethernet link, but a link between Octeon and the -+ * PHY. -+ */ -+ if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && -+ CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_STATUS_REG(index, interface), -+ union cvmx_pcsx_mrx_status_reg, an_cpt, ==, 1, -+ 10000)) { -+ /* cvmx_dprintf("SGMII%d: Port %d link timeout\n", interface, index); */ -+ return -1; -+ } -+ return 0; -+} -+ -+/** -+ * Configure an SGMII link to the specified speed after the SERTES -+ * link is up. -+ * -+ * @interface: Interface to init -+ * @index: Index of prot on the interface -+ * @link_info: Link state to configure -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_sgmii_hardware_init_link_speed(int interface, -+ int index, -+ cvmx_helper_link_info_t -+ link_info) -+{ -+ int is_enabled; -+ union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg; -+ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; -+ -+ /* Disable GMX before we make any changes. Remember the enable state */ -+ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ is_enabled = gmxx_prtx_cfg.s.en; -+ gmxx_prtx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); -+ -+ /* Wait for GMX to be idle */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_GMXX_PRTX_CFG(index, interface), union cvmx_gmxx_prtx_cfg, -+ rx_idle, ==, 1, 10000) -+ || CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), -+ union cvmx_gmxx_prtx_cfg, tx_idle, ==, 1, -+ 10000)) { -+ cvmx_dprintf -+ ("SGMII%d: Timeout waiting for port %d to be idle\n", -+ interface, index); -+ return -1; -+ } -+ -+ /* Read GMX CFG again to make sure the disable completed */ -+ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ -+ /* -+ * Get the misc control for PCS. We will need to set the -+ * duplication amount. -+ */ -+ pcsx_miscx_ctl_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); -+ -+ /* -+ * Use GMXENO to force the link down if the status we get says -+ * it should be down. -+ */ -+ pcsx_miscx_ctl_reg.s.gmxeno = !link_info.s.link_up; -+ -+ /* Only change the duplex setting if the link is up */ -+ if (link_info.s.link_up) -+ gmxx_prtx_cfg.s.duplex = link_info.s.full_duplex; -+ -+ /* Do speed based setting for GMX */ -+ switch (link_info.s.speed) { -+ case 10: -+ gmxx_prtx_cfg.s.speed = 0; -+ gmxx_prtx_cfg.s.speed_msb = 1; -+ gmxx_prtx_cfg.s.slottime = 0; -+ /* Setting from GMX-603 */ -+ pcsx_miscx_ctl_reg.s.samp_pt = 25; -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); -+ break; -+ case 100: -+ gmxx_prtx_cfg.s.speed = 0; -+ gmxx_prtx_cfg.s.speed_msb = 0; -+ gmxx_prtx_cfg.s.slottime = 0; -+ pcsx_miscx_ctl_reg.s.samp_pt = 0x5; -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0); -+ break; -+ case 1000: -+ gmxx_prtx_cfg.s.speed = 1; -+ gmxx_prtx_cfg.s.speed_msb = 0; -+ gmxx_prtx_cfg.s.slottime = 1; -+ pcsx_miscx_ctl_reg.s.samp_pt = 1; -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 512); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 8192); -+ break; -+ default: -+ break; -+ } -+ -+ /* Write the new misc control for PCS */ -+ cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface), -+ pcsx_miscx_ctl_reg.u64); -+ -+ /* Write the new GMX settings with the port still disabled */ -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); -+ -+ /* Read GMX CFG again to make sure the config completed */ -+ gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ -+ /* Restore the enabled / disabled state */ -+ gmxx_prtx_cfg.s.en = is_enabled; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64); -+ -+ return 0; -+} -+ -+/** -+ * Bring up the SGMII interface to be ready for packet I/O but -+ * leave I/O disabled using the GMX override. This function -+ * follows the bringup documented in 10.6.3 of the manual. -+ * -+ * @interface: Interface to bringup -+ * @num_ports: Number of ports on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports) -+{ -+ int index; -+ -+ __cvmx_helper_setup_gmx(interface, num_ports); -+ -+ for (index = 0; index < num_ports; index++) { -+ int ipd_port = cvmx_helper_get_ipd_port(interface, index); -+ __cvmx_helper_sgmii_hardware_init_one_time(interface, index); -+ __cvmx_helper_sgmii_link_set(ipd_port, -+ __cvmx_helper_sgmii_link_get -+ (ipd_port)); -+ -+ } -+ -+ return 0; -+} -+ -+/** -+ * Probe a SGMII interface and determine the number of ports -+ * connected to it. The SGMII interface should still be down after -+ * this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+int __cvmx_helper_sgmii_probe(int interface) -+{ -+ union cvmx_gmxx_inf_mode mode; -+ -+ /* -+ * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the -+ * interface needs to be enabled before IPD otherwise per port -+ * backpressure may not work properly -+ */ -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ mode.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64); -+ return 4; -+} -+ -+/** -+ * Bringup and enable a SGMII interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_sgmii_enable(int interface) -+{ -+ int num_ports = cvmx_helper_ports_on_interface(interface); -+ int index; -+ -+ __cvmx_helper_sgmii_hardware_init(interface, num_ports); -+ -+ for (index = 0; index < num_ports; index++) { -+ union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg; -+ gmxx_prtx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmxx_prtx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), -+ gmxx_prtx_cfg.u64); -+ __cvmx_interrupt_pcsx_intx_en_reg_enable(index, interface); -+ } -+ __cvmx_interrupt_pcsxx_int_en_reg_enable(interface); -+ __cvmx_interrupt_gmxx_enable(interface); -+ return 0; -+} -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port) -+{ -+ cvmx_helper_link_info_t result; -+ union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg; -+ -+ result.u64 = 0; -+ -+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) { -+ /* The simulator gives you a simulated 1Gbps full duplex link */ -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ return result; -+ } -+ -+ pcsx_mrx_control_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface)); -+ if (pcsx_mrx_control_reg.s.loopbck1) { -+ /* Force 1Gbps full duplex link for internal loopback */ -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 1000; -+ return result; -+ } -+ -+ pcs_misc_ctl_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); -+ if (pcs_misc_ctl_reg.s.mode) { -+ /* 1000BASE-X */ -+ /* FIXME */ -+ } else { -+ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; -+ pcsx_miscx_ctl_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); -+ if (pcsx_miscx_ctl_reg.s.mac_phy) { -+ /* PHY Mode */ -+ union cvmx_pcsx_mrx_status_reg pcsx_mrx_status_reg; -+ union cvmx_pcsx_anx_results_reg pcsx_anx_results_reg; -+ -+ /* -+ * Don't bother continuing if the SERTES low -+ * level link is down -+ */ -+ pcsx_mrx_status_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG -+ (index, interface)); -+ if (pcsx_mrx_status_reg.s.lnk_st == 0) { -+ if (__cvmx_helper_sgmii_hardware_init_link -+ (interface, index) != 0) -+ return result; -+ } -+ -+ /* Read the autoneg results */ -+ pcsx_anx_results_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_ANX_RESULTS_REG -+ (index, interface)); -+ if (pcsx_anx_results_reg.s.an_cpt) { -+ /* -+ * Auto negotiation is complete. Set -+ * status accordingly. -+ */ -+ result.s.full_duplex = -+ pcsx_anx_results_reg.s.dup; -+ result.s.link_up = -+ pcsx_anx_results_reg.s.link_ok; -+ switch (pcsx_anx_results_reg.s.spd) { -+ case 0: -+ result.s.speed = 10; -+ break; -+ case 1: -+ result.s.speed = 100; -+ break; -+ case 2: -+ result.s.speed = 1000; -+ break; -+ default: -+ result.s.speed = 0; -+ result.s.link_up = 0; -+ break; -+ } -+ } else { -+ /* -+ * Auto negotiation isn't -+ * complete. Return link down. -+ */ -+ result.s.speed = 0; -+ result.s.link_up = 0; -+ } -+ } else { /* MAC Mode */ -+ -+ result = __cvmx_helper_board_link_get(ipd_port); -+ } -+ } -+ return result; -+} -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_sgmii_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ __cvmx_helper_sgmii_hardware_init_link(interface, index); -+ return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index, -+ link_info); -+} -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal -+ * loopback causes packets sent by the port to be received by -+ * Octeon. External loopback causes packets received from the wire to -+ * sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+int __cvmx_helper_sgmii_configure_loopback(int ipd_port, int enable_internal, -+ int enable_external) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg; -+ union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg; -+ -+ pcsx_mrx_control_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface)); -+ pcsx_mrx_control_reg.s.loopbck1 = enable_internal; -+ cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface), -+ pcsx_mrx_control_reg.u64); -+ -+ pcsx_miscx_ctl_reg.u64 = -+ cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface)); -+ pcsx_miscx_ctl_reg.s.loopbck2 = enable_external; -+ cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface), -+ pcsx_miscx_ctl_reg.u64); -+ -+ __cvmx_helper_sgmii_hardware_init_link(interface, index); -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-sgmii.h -@@ -0,0 +1,104 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Functions for SGMII initialization, configuration, -+ * and monitoring. -+ * -+ */ -+#ifndef __CVMX_HELPER_SGMII_H__ -+#define __CVMX_HELPER_SGMII_H__ -+ -+/** -+ * Probe a SGMII interface and determine the number of ports -+ * connected to it. The SGMII interface should still be down after -+ * this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+extern int __cvmx_helper_sgmii_probe(int interface); -+ -+/** -+ * Bringup and enable a SGMII interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_sgmii_enable(int interface); -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+extern cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port); -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_sgmii_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info); -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+extern int __cvmx_helper_sgmii_configure_loopback(int ipd_port, -+ int enable_internal, -+ int enable_external); -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-spi.c -@@ -0,0 +1,195 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+void __cvmx_interrupt_gmxx_enable(int interface); -+void __cvmx_interrupt_spxx_int_msk_enable(int index); -+void __cvmx_interrupt_stxx_int_msk_enable(int index); -+ -+/* -+ * Functions for SPI initialization, configuration, -+ * and monitoring. -+ */ -+#include -+ -+#include "cvmx-config.h" -+#include "cvmx-spi.h" -+#include "cvmx-helper.h" -+ -+#include "cvmx-pip-defs.h" -+#include "cvmx-pko-defs.h" -+ -+/* -+ * CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI -+ * initialization routines wait for SPI training. You can override the -+ * value using executive-config.h if necessary. -+ */ -+#ifndef CVMX_HELPER_SPI_TIMEOUT -+#define CVMX_HELPER_SPI_TIMEOUT 10 -+#endif -+ -+/** -+ * Probe a SPI interface and determine the number of ports -+ * connected to it. The SPI interface should still be down after -+ * this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+int __cvmx_helper_spi_probe(int interface) -+{ -+ int num_ports = 0; -+ -+ if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && -+ cvmx_spi4000_is_present(interface)) { -+ num_ports = 10; -+ } else { -+ union cvmx_pko_reg_crc_enable enable; -+ num_ports = 16; -+ /* -+ * Unlike the SPI4000, most SPI devices don't -+ * automatically put on the L2 CRC. For everything -+ * except for the SPI4000 have PKO append the L2 CRC -+ * to the packet. -+ */ -+ enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE); -+ enable.s.enable |= 0xffff << (interface * 16); -+ cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64); -+ } -+ __cvmx_helper_setup_gmx(interface, num_ports); -+ return num_ports; -+} -+ -+/** -+ * Bringup and enable a SPI interface. After this call packet I/O -+ * should be fully functional. This is called with IPD enabled but -+ * PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_spi_enable(int interface) -+{ -+ /* -+ * Normally the ethernet L2 CRC is checked and stripped in the -+ * GMX block. When you are using SPI, this isn' the case and -+ * IPD needs to check the L2 CRC. -+ */ -+ int num_ports = cvmx_helper_ports_on_interface(interface); -+ int ipd_port; -+ for (ipd_port = interface * 16; ipd_port < interface * 16 + num_ports; -+ ipd_port++) { -+ union cvmx_pip_prt_cfgx port_config; -+ port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); -+ port_config.s.crc_en = 1; -+ cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64); -+ } -+ -+ if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) { -+ cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX, -+ CVMX_HELPER_SPI_TIMEOUT, num_ports); -+ if (cvmx_spi4000_is_present(interface)) -+ cvmx_spi4000_initialize(interface); -+ } -+ __cvmx_interrupt_spxx_int_msk_enable(interface); -+ __cvmx_interrupt_stxx_int_msk_enable(interface); -+ __cvmx_interrupt_gmxx_enable(interface); -+ return 0; -+} -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port) -+{ -+ cvmx_helper_link_info_t result; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ result.u64 = 0; -+ -+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) { -+ /* The simulator gives you a simulated full duplex link */ -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 10000; -+ } else if (cvmx_spi4000_is_present(interface)) { -+ union cvmx_gmxx_rxx_rx_inbnd inband = -+ cvmx_spi4000_check_speed(interface, index); -+ result.s.link_up = inband.s.status; -+ result.s.full_duplex = inband.s.duplex; -+ switch (inband.s.speed) { -+ case 0: /* 10 Mbps */ -+ result.s.speed = 10; -+ break; -+ case 1: /* 100 Mbps */ -+ result.s.speed = 100; -+ break; -+ case 2: /* 1 Gbps */ -+ result.s.speed = 1000; -+ break; -+ case 3: /* Illegal */ -+ result.s.speed = 0; -+ result.s.link_up = 0; -+ break; -+ } -+ } else { -+ /* For generic SPI we can't determine the link, just return some -+ sane results */ -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 10000; -+ } -+ return result; -+} -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_spi_link_set(int ipd_port, cvmx_helper_link_info_t link_info) -+{ -+ /* Nothing to do. If we have a SPI4000 then the setup was already performed -+ by cvmx_spi4000_check_speed(). If not then there isn't any link -+ info */ -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-spi.h -@@ -0,0 +1,84 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Functions for SPI initialization, configuration, -+ * and monitoring. -+ */ -+#ifndef __CVMX_HELPER_SPI_H__ -+#define __CVMX_HELPER_SPI_H__ -+ -+/** -+ * Probe a SPI interface and determine the number of ports -+ * connected to it. The SPI interface should still be down after -+ * this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+extern int __cvmx_helper_spi_probe(int interface); -+ -+/** -+ * Bringup and enable a SPI interface. After this call packet I/O -+ * should be fully functional. This is called with IPD enabled but -+ * PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_spi_enable(int interface); -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+extern cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port); -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_spi_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info); -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-util.c -@@ -0,0 +1,433 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Small helper utilities. -+ */ -+#include -+ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-fpa.h" -+#include "cvmx-pip.h" -+#include "cvmx-pko.h" -+#include "cvmx-ipd.h" -+#include "cvmx-spi.h" -+ -+#include "cvmx-helper.h" -+#include "cvmx-helper-util.h" -+ -+#include -+ -+/** -+ * Convert a interface mode into a human readable string -+ * -+ * @mode: Mode to convert -+ * -+ * Returns String -+ */ -+const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t -+ mode) -+{ -+ switch (mode) { -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ return "DISABLED"; -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ return "RGMII"; -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ return "GMII"; -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ return "SPI"; -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ return "PCIE"; -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ return "XAUI"; -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ return "SGMII"; -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ return "PICMG"; -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ return "NPI"; -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ return "LOOP"; -+ } -+ return "UNKNOWN"; -+} -+ -+/** -+ * Debug routine to dump the packet structure to the console -+ * -+ * @work: Work queue entry containing the packet to dump -+ * Returns -+ */ -+int cvmx_helper_dump_packet(cvmx_wqe_t *work) -+{ -+ uint64_t count; -+ uint64_t remaining_bytes; -+ union cvmx_buf_ptr buffer_ptr; -+ uint64_t start_of_buffer; -+ uint8_t *data_address; -+ uint8_t *end_of_data; -+ -+ cvmx_dprintf("Packet Length: %u\n", work->len); -+ cvmx_dprintf(" Input Port: %u\n", work->ipprt); -+ cvmx_dprintf(" QoS: %u\n", work->qos); -+ cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs); -+ -+ if (work->word2.s.bufs == 0) { -+ union cvmx_ipd_wqe_fpa_queue wqe_pool; -+ wqe_pool.u64 = cvmx_read_csr(CVMX_IPD_WQE_FPA_QUEUE); -+ buffer_ptr.u64 = 0; -+ buffer_ptr.s.pool = wqe_pool.s.wqe_pool; -+ buffer_ptr.s.size = 128; -+ buffer_ptr.s.addr = cvmx_ptr_to_phys(work->packet_data); -+ if (likely(!work->word2.s.not_IP)) { -+ union cvmx_pip_ip_offset pip_ip_offset; -+ pip_ip_offset.u64 = cvmx_read_csr(CVMX_PIP_IP_OFFSET); -+ buffer_ptr.s.addr += -+ (pip_ip_offset.s.offset << 3) - -+ work->word2.s.ip_offset; -+ buffer_ptr.s.addr += (work->word2.s.is_v6 ^ 1) << 2; -+ } else { -+ /* -+ * WARNING: This code assumes that the packet -+ * is not RAW. If it was, we would use -+ * PIP_GBL_CFG[RAW_SHF] instead of -+ * PIP_GBL_CFG[NIP_SHF]. -+ */ -+ union cvmx_pip_gbl_cfg pip_gbl_cfg; -+ pip_gbl_cfg.u64 = cvmx_read_csr(CVMX_PIP_GBL_CFG); -+ buffer_ptr.s.addr += pip_gbl_cfg.s.nip_shf; -+ } -+ } else -+ buffer_ptr = work->packet_ptr; -+ remaining_bytes = work->len; -+ -+ while (remaining_bytes) { -+ start_of_buffer = -+ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; -+ cvmx_dprintf(" Buffer Start:%llx\n", -+ (unsigned long long)start_of_buffer); -+ cvmx_dprintf(" Buffer I : %u\n", buffer_ptr.s.i); -+ cvmx_dprintf(" Buffer Back: %u\n", buffer_ptr.s.back); -+ cvmx_dprintf(" Buffer Pool: %u\n", buffer_ptr.s.pool); -+ cvmx_dprintf(" Buffer Data: %llx\n", -+ (unsigned long long)buffer_ptr.s.addr); -+ cvmx_dprintf(" Buffer Size: %u\n", buffer_ptr.s.size); -+ -+ cvmx_dprintf("\t\t"); -+ data_address = (uint8_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr); -+ end_of_data = data_address + buffer_ptr.s.size; -+ count = 0; -+ while (data_address < end_of_data) { -+ if (remaining_bytes == 0) -+ break; -+ else -+ remaining_bytes--; -+ cvmx_dprintf("%02x", (unsigned int)*data_address); -+ data_address++; -+ if (remaining_bytes && (count == 7)) { -+ cvmx_dprintf("\n\t\t"); -+ count = 0; -+ } else -+ count++; -+ } -+ cvmx_dprintf("\n"); -+ -+ if (remaining_bytes) -+ buffer_ptr = *(union cvmx_buf_ptr *) -+ cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); -+ } -+ return 0; -+} -+ -+/** -+ * Setup Random Early Drop on a specific input queue -+ * -+ * @queue: Input queue to setup RED on (0-7) -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh) -+{ -+ union cvmx_ipd_qosx_red_marks red_marks; -+ union cvmx_ipd_red_quex_param red_param; -+ -+ /* Set RED to begin dropping packets when there are pass_thresh buffers -+ left. It will linearly drop more packets until reaching drop_thresh -+ buffers */ -+ red_marks.u64 = 0; -+ red_marks.s.drop = drop_thresh; -+ red_marks.s.pass = pass_thresh; -+ cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64); -+ -+ /* Use the actual queue 0 counter, not the average */ -+ red_param.u64 = 0; -+ red_param.s.prb_con = -+ (255ul << 24) / (red_marks.s.pass - red_marks.s.drop); -+ red_param.s.avg_con = 1; -+ red_param.s.new_con = 255; -+ red_param.s.use_pcnt = 1; -+ cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64); -+ return 0; -+} -+ -+/** -+ * Setup Random Early Drop to automatically begin dropping packets. -+ * -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) -+{ -+ union cvmx_ipd_portx_bp_page_cnt page_cnt; -+ union cvmx_ipd_bp_prt_red_end ipd_bp_prt_red_end; -+ union cvmx_ipd_red_port_enable red_port_enable; -+ int queue; -+ int interface; -+ int port; -+ -+ /* Disable backpressure based on queued buffers. It needs SW support */ -+ page_cnt.u64 = 0; -+ page_cnt.s.bp_enb = 0; -+ page_cnt.s.page_cnt = 100; -+ for (interface = 0; interface < 2; interface++) { -+ for (port = cvmx_helper_get_first_ipd_port(interface); -+ port < cvmx_helper_get_last_ipd_port(interface); port++) -+ cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port), -+ page_cnt.u64); -+ } -+ -+ for (queue = 0; queue < 8; queue++) -+ cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh); -+ -+ /* Shutoff the dropping based on the per port page count. SW isn't -+ decrementing it right now */ -+ ipd_bp_prt_red_end.u64 = 0; -+ ipd_bp_prt_red_end.s.prt_enb = 0; -+ cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64); -+ -+ red_port_enable.u64 = 0; -+ red_port_enable.s.prt_enb = 0xfffffffffull; -+ red_port_enable.s.avg_dly = 10000; -+ red_port_enable.s.prb_dly = 10000; -+ cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64); -+ -+ return 0; -+} -+ -+/** -+ * Setup the common GMX settings that determine the number of -+ * ports. These setting apply to almost all configurations of all -+ * chips. -+ * -+ * @interface: Interface to configure -+ * @num_ports: Number of ports on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_setup_gmx(int interface, int num_ports) -+{ -+ union cvmx_gmxx_tx_prts gmx_tx_prts; -+ union cvmx_gmxx_rx_prts gmx_rx_prts; -+ union cvmx_pko_reg_gmx_port_mode pko_mode; -+ union cvmx_gmxx_txx_thresh gmx_tx_thresh; -+ int index; -+ -+ /* Tell GMX the number of TX ports on this interface */ -+ gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface)); -+ gmx_tx_prts.s.prts = num_ports; -+ cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64); -+ -+ /* Tell GMX the number of RX ports on this interface. This only -+ ** applies to *GMII and XAUI ports */ -+ if (cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_RGMII -+ || cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_SGMII -+ || cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_GMII -+ || cvmx_helper_interface_get_mode(interface) == -+ CVMX_HELPER_INTERFACE_MODE_XAUI) { -+ if (num_ports > 4) { -+ cvmx_dprintf("__cvmx_helper_setup_gmx: Illegal " -+ "num_ports\n"); -+ return -1; -+ } -+ -+ gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface)); -+ gmx_rx_prts.s.prts = num_ports; -+ cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64); -+ } -+ -+ /* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, and 50XX */ -+ if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX) -+ && !OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ /* Tell PKO the number of ports on this interface */ -+ pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE); -+ if (interface == 0) { -+ if (num_ports == 1) -+ pko_mode.s.mode0 = 4; -+ else if (num_ports == 2) -+ pko_mode.s.mode0 = 3; -+ else if (num_ports <= 4) -+ pko_mode.s.mode0 = 2; -+ else if (num_ports <= 8) -+ pko_mode.s.mode0 = 1; -+ else -+ pko_mode.s.mode0 = 0; -+ } else { -+ if (num_ports == 1) -+ pko_mode.s.mode1 = 4; -+ else if (num_ports == 2) -+ pko_mode.s.mode1 = 3; -+ else if (num_ports <= 4) -+ pko_mode.s.mode1 = 2; -+ else if (num_ports <= 8) -+ pko_mode.s.mode1 = 1; -+ else -+ pko_mode.s.mode1 = 0; -+ } -+ cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64); -+ } -+ -+ /* -+ * Set GMX to buffer as much data as possible before starting -+ * transmit. This reduces the chances that we have a TX under -+ * run due to memory contention. Any packet that fits entirely -+ * in the GMX FIFO can never have an under run regardless of -+ * memory load. -+ */ -+ gmx_tx_thresh.u64 = cvmx_read_csr(CVMX_GMXX_TXX_THRESH(0, interface)); -+ if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ /* These chips have a fixed max threshold of 0x40 */ -+ gmx_tx_thresh.s.cnt = 0x40; -+ } else { -+ /* Choose the max value for the number of ports */ -+ if (num_ports <= 1) -+ gmx_tx_thresh.s.cnt = 0x100 / 1; -+ else if (num_ports == 2) -+ gmx_tx_thresh.s.cnt = 0x100 / 2; -+ else -+ gmx_tx_thresh.s.cnt = 0x100 / 4; -+ } -+ /* -+ * SPI and XAUI can have lots of ports but the GMX hardware -+ * only ever has a max of 4. -+ */ -+ if (num_ports > 4) -+ num_ports = 4; -+ for (index = 0; index < num_ports; index++) -+ cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface), -+ gmx_tx_thresh.u64); -+ -+ return 0; -+} -+ -+/** -+ * Returns the IPD/PKO port number for a port on teh given -+ * interface. -+ * -+ * @interface: Interface to use -+ * @port: Port on the interface -+ * -+ * Returns IPD/PKO port number -+ */ -+int cvmx_helper_get_ipd_port(int interface, int port) -+{ -+ switch (interface) { -+ case 0: -+ return port; -+ case 1: -+ return port + 16; -+ case 2: -+ return port + 32; -+ case 3: -+ return port + 36; -+ } -+ return -1; -+} -+ -+/** -+ * Returns the interface number for an IPD/PKO port number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface number -+ */ -+int cvmx_helper_get_interface_num(int ipd_port) -+{ -+ if (ipd_port < 16) -+ return 0; -+ else if (ipd_port < 32) -+ return 1; -+ else if (ipd_port < 36) -+ return 2; -+ else if (ipd_port < 40) -+ return 3; -+ else -+ cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD " -+ "port number\n"); -+ -+ return -1; -+} -+ -+/** -+ * Returns the interface index number for an IPD/PKO port -+ * number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface index number -+ */ -+int cvmx_helper_get_interface_index_num(int ipd_port) -+{ -+ if (ipd_port < 32) -+ return ipd_port & 15; -+ else if (ipd_port < 36) -+ return ipd_port & 3; -+ else if (ipd_port < 40) -+ return ipd_port & 3; -+ else -+ cvmx_dprintf("cvmx_helper_get_interface_index_num: " -+ "Illegal IPD port number\n"); -+ -+ return -1; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-util.h -@@ -0,0 +1,215 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Small helper utilities. -+ * -+ */ -+ -+#ifndef __CVMX_HELPER_UTIL_H__ -+#define __CVMX_HELPER_UTIL_H__ -+ -+/** -+ * Convert a interface mode into a human readable string -+ * -+ * @mode: Mode to convert -+ * -+ * Returns String -+ */ -+extern const char -+ *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode); -+ -+/** -+ * Debug routine to dump the packet structure to the console -+ * -+ * @work: Work queue entry containing the packet to dump -+ * Returns -+ */ -+extern int cvmx_helper_dump_packet(cvmx_wqe_t *work); -+ -+/** -+ * Setup Random Early Drop on a specific input queue -+ * -+ * @queue: Input queue to setup RED on (0-7) -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+extern int cvmx_helper_setup_red_queue(int queue, int pass_thresh, -+ int drop_thresh); -+ -+/** -+ * Setup Random Early Drop to automatically begin dropping packets. -+ * -+ * @pass_thresh: -+ * Packets will begin slowly dropping when there are less than -+ * this many packet buffers free in FPA 0. -+ * @drop_thresh: -+ * All incomming packets will be dropped when there are less -+ * than this many free packet buffers in FPA 0. -+ * Returns Zero on success. Negative on failure -+ */ -+extern int cvmx_helper_setup_red(int pass_thresh, int drop_thresh); -+ -+/** -+ * Get the version of the CVMX libraries. -+ * -+ * Returns Version string. Note this buffer is allocated statically -+ * and will be shared by all callers. -+ */ -+extern const char *cvmx_helper_get_version(void); -+ -+/** -+ * Setup the common GMX settings that determine the number of -+ * ports. These setting apply to almost all configurations of all -+ * chips. -+ * -+ * @interface: Interface to configure -+ * @num_ports: Number of ports on the interface -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_setup_gmx(int interface, int num_ports); -+ -+/** -+ * Returns the IPD/PKO port number for a port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * @port: Port on the interface -+ * -+ * Returns IPD/PKO port number -+ */ -+extern int cvmx_helper_get_ipd_port(int interface, int port); -+ -+/** -+ * Returns the IPD/PKO port number for the first port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * -+ * Returns IPD/PKO port number -+ */ -+static inline int cvmx_helper_get_first_ipd_port(int interface) -+{ -+ return cvmx_helper_get_ipd_port(interface, 0); -+} -+ -+/** -+ * Returns the IPD/PKO port number for the last port on the given -+ * interface. -+ * -+ * @interface: Interface to use -+ * -+ * Returns IPD/PKO port number -+ */ -+static inline int cvmx_helper_get_last_ipd_port(int interface) -+{ -+ extern int cvmx_helper_ports_on_interface(int interface); -+ -+ return cvmx_helper_get_first_ipd_port(interface) + -+ cvmx_helper_ports_on_interface(interface) - 1; -+} -+ -+/** -+ * Free the packet buffers contained in a work queue entry. -+ * The work queue entry is not freed. -+ * -+ * @work: Work queue entry with packet to free -+ */ -+static inline void cvmx_helper_free_packet_data(cvmx_wqe_t *work) -+{ -+ uint64_t number_buffers; -+ union cvmx_buf_ptr buffer_ptr; -+ union cvmx_buf_ptr next_buffer_ptr; -+ uint64_t start_of_buffer; -+ -+ number_buffers = work->word2.s.bufs; -+ if (number_buffers == 0) -+ return; -+ buffer_ptr = work->packet_ptr; -+ -+ /* -+ * Since the number of buffers is not zero, we know this is -+ * not a dynamic short packet. We need to check if it is a -+ * packet received with IPD_CTL_STATUS[NO_WPTR]. If this is -+ * true, we need to free all buffers except for the first -+ * one. The caller doesn't expect their WQE pointer to be -+ * freed -+ */ -+ start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; -+ if (cvmx_ptr_to_phys(work) == start_of_buffer) { -+ next_buffer_ptr = -+ *(union cvmx_buf_ptr *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); -+ buffer_ptr = next_buffer_ptr; -+ number_buffers--; -+ } -+ -+ while (number_buffers--) { -+ /* -+ * Remember the back pointer is in cache lines, not -+ * 64bit words -+ */ -+ start_of_buffer = -+ ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7; -+ /* -+ * Read pointer to next buffer before we free the -+ * current buffer. -+ */ -+ next_buffer_ptr = -+ *(union cvmx_buf_ptr *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8); -+ cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer), -+ buffer_ptr.s.pool, 0); -+ buffer_ptr = next_buffer_ptr; -+ } -+} -+ -+/** -+ * Returns the interface number for an IPD/PKO port number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface number -+ */ -+extern int cvmx_helper_get_interface_num(int ipd_port); -+ -+/** -+ * Returns the interface index number for an IPD/PKO port -+ * number. -+ * -+ * @ipd_port: IPD/PKO port number -+ * -+ * Returns Interface index number -+ */ -+extern int cvmx_helper_get_interface_index_num(int ipd_port); -+ -+#endif /* __CVMX_HELPER_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-xaui.c -@@ -0,0 +1,348 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Functions for XAUI initialization, configuration, -+ * and monitoring. -+ * -+ */ -+ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-helper.h" -+ -+#include "cvmx-pko-defs.h" -+#include "cvmx-gmxx-defs.h" -+#include "cvmx-pcsxx-defs.h" -+ -+void __cvmx_interrupt_gmxx_enable(int interface); -+void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block); -+void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index); -+/** -+ * Probe a XAUI interface and determine the number of ports -+ * connected to it. The XAUI interface should still be down -+ * after this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+int __cvmx_helper_xaui_probe(int interface) -+{ -+ int i; -+ union cvmx_gmxx_hg2_control gmx_hg2_control; -+ union cvmx_gmxx_inf_mode mode; -+ -+ /* -+ * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the -+ * interface needs to be enabled before IPD otherwise per port -+ * backpressure may not work properly. -+ */ -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ mode.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64); -+ -+ __cvmx_helper_setup_gmx(interface, 1); -+ -+ /* -+ * Setup PKO to support 16 ports for HiGig2 virtual -+ * ports. We're pointing all of the PKO packet ports for this -+ * interface to the XAUI. This allows us to use HiGig2 -+ * backpressure per port. -+ */ -+ for (i = 0; i < 16; i++) { -+ union cvmx_pko_mem_port_ptrs pko_mem_port_ptrs; -+ pko_mem_port_ptrs.u64 = 0; -+ /* -+ * We set each PKO port to have equal priority in a -+ * round robin fashion. -+ */ -+ pko_mem_port_ptrs.s.static_p = 0; -+ pko_mem_port_ptrs.s.qos_mask = 0xff; -+ /* All PKO ports map to the same XAUI hardware port */ -+ pko_mem_port_ptrs.s.eid = interface * 4; -+ pko_mem_port_ptrs.s.pid = interface * 16 + i; -+ cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64); -+ } -+ -+ /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */ -+ gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface)); -+ if (gmx_hg2_control.s.hg2tx_en) -+ return 16; -+ else -+ return 1; -+} -+ -+/** -+ * Bringup and enable a XAUI interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_xaui_enable(int interface) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ union cvmx_pcsxx_control1_reg xauiCtl; -+ union cvmx_pcsxx_misc_ctl_reg xauiMiscCtl; -+ union cvmx_gmxx_tx_xaui_ctl gmxXauiTxCtl; -+ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; -+ union cvmx_gmxx_tx_int_en gmx_tx_int_en; -+ union cvmx_pcsxx_int_en_reg pcsx_int_en_reg; -+ -+ /* (1) Interface has already been enabled. */ -+ -+ /* (2) Disable GMX. */ -+ xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface)); -+ xauiMiscCtl.s.gmxeno = 1; -+ cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); -+ -+ /* (3) Disable GMX and PCSX interrupts. */ -+ gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0, interface)); -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0); -+ gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface)); -+ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0); -+ pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface)); -+ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0); -+ -+ /* (4) Bring up the PCSX and GMX reconciliation layer. */ -+ /* (4)a Set polarity and lane swapping. */ -+ /* (4)b */ -+ gmxXauiTxCtl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); -+ /* Enable better IFG packing and improves performance */ -+ gmxXauiTxCtl.s.dic_en = 1; -+ gmxXauiTxCtl.s.uni_en = 0; -+ cvmx_write_csr(CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64); -+ -+ /* (4)c Aply reset sequence */ -+ xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); -+ xauiCtl.s.lo_pwr = 0; -+ xauiCtl.s.reset = 1; -+ cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64); -+ -+ /* Wait for PCS to come out of reset */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_PCSXX_CONTROL1_REG(interface), union cvmx_pcsxx_control1_reg, -+ reset, ==, 0, 10000)) -+ return -1; -+ /* Wait for PCS to be aligned */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_PCSXX_10GBX_STATUS_REG(interface), -+ union cvmx_pcsxx_10gbx_status_reg, alignd, ==, 1, 10000)) -+ return -1; -+ /* Wait for RX to be ready */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_GMXX_RX_XAUI_CTL(interface), union cvmx_gmxx_rx_xaui_ctl, -+ status, ==, 0, 10000)) -+ return -1; -+ -+ /* (6) Configure GMX */ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); -+ gmx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); -+ -+ /* Wait for GMX RX to be idle */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg, -+ rx_idle, ==, 1, 10000)) -+ return -1; -+ /* Wait for GMX TX to be idle */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg, -+ tx_idle, ==, 1, 10000)) -+ return -1; -+ -+ /* GMX configure */ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); -+ gmx_cfg.s.speed = 1; -+ gmx_cfg.s.speed_msb = 0; -+ gmx_cfg.s.slottime = 1; -+ cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1); -+ cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512); -+ cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192); -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); -+ -+ /* (7) Clear out any error state */ -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0, interface), -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0, interface))); -+ cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface), -+ cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface))); -+ cvmx_write_csr(CVMX_PCSXX_INT_REG(interface), -+ cvmx_read_csr(CVMX_PCSXX_INT_REG(interface))); -+ -+ /* Wait for receive link */ -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_PCSXX_STATUS1_REG(interface), union cvmx_pcsxx_status1_reg, -+ rcv_lnk, ==, 1, 10000)) -+ return -1; -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg, -+ xmtflt, ==, 0, 10000)) -+ return -1; -+ if (CVMX_WAIT_FOR_FIELD64 -+ (CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg, -+ rcvflt, ==, 0, 10000)) -+ return -1; -+ -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), gmx_rx_int_en.u64); -+ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64); -+ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64); -+ -+ cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0)); -+ -+ /* (8) Enable packet reception */ -+ xauiMiscCtl.s.gmxeno = 0; -+ cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); -+ -+ __cvmx_interrupt_pcsx_intx_en_reg_enable(0, interface); -+ __cvmx_interrupt_pcsx_intx_en_reg_enable(1, interface); -+ __cvmx_interrupt_pcsx_intx_en_reg_enable(2, interface); -+ __cvmx_interrupt_pcsx_intx_en_reg_enable(3, interface); -+ __cvmx_interrupt_pcsxx_int_en_reg_enable(interface); -+ __cvmx_interrupt_gmxx_enable(interface); -+ -+ return 0; -+} -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ union cvmx_gmxx_tx_xaui_ctl gmxx_tx_xaui_ctl; -+ union cvmx_gmxx_rx_xaui_ctl gmxx_rx_xaui_ctl; -+ union cvmx_pcsxx_status1_reg pcsxx_status1_reg; -+ cvmx_helper_link_info_t result; -+ -+ gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); -+ gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); -+ pcsxx_status1_reg.u64 = -+ cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface)); -+ result.u64 = 0; -+ -+ /* Only return a link if both RX and TX are happy */ -+ if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) && -+ (pcsxx_status1_reg.s.rcv_lnk == 1)) { -+ result.s.link_up = 1; -+ result.s.full_duplex = 1; -+ result.s.speed = 10000; -+ } else { -+ /* Disable GMX and PCSX interrupts. */ -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0); -+ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0); -+ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0); -+ } -+ return result; -+} -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ union cvmx_gmxx_tx_xaui_ctl gmxx_tx_xaui_ctl; -+ union cvmx_gmxx_rx_xaui_ctl gmxx_rx_xaui_ctl; -+ -+ gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); -+ gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); -+ -+ /* If the link shouldn't be up, then just return */ -+ if (!link_info.s.link_up) -+ return 0; -+ -+ /* Do nothing if both RX and TX are happy */ -+ if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0)) -+ return 0; -+ -+ /* Bring the link up */ -+ return __cvmx_helper_xaui_enable(interface); -+} -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, -+ int enable_internal, -+ int enable_external) -+{ -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ union cvmx_pcsxx_control1_reg pcsxx_control1_reg; -+ union cvmx_gmxx_xaui_ext_loopback gmxx_xaui_ext_loopback; -+ -+ /* Set the internal loop */ -+ pcsxx_control1_reg.u64 = -+ cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); -+ pcsxx_control1_reg.s.loopbck1 = enable_internal; -+ cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), -+ pcsxx_control1_reg.u64); -+ -+ /* Set the external loop */ -+ gmxx_xaui_ext_loopback.u64 = -+ cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface)); -+ gmxx_xaui_ext_loopback.s.en = enable_external; -+ cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), -+ gmxx_xaui_ext_loopback.u64); -+ -+ /* Take the link through a reset */ -+ return __cvmx_helper_xaui_enable(interface); -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper-xaui.h -@@ -0,0 +1,103 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * @file -+ * -+ * Functions for XAUI initialization, configuration, -+ * and monitoring. -+ * -+ */ -+#ifndef __CVMX_HELPER_XAUI_H__ -+#define __CVMX_HELPER_XAUI_H__ -+ -+/** -+ * Probe a XAUI interface and determine the number of ports -+ * connected to it. The XAUI interface should still be down -+ * after this call. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Number of ports on the interface. Zero to disable. -+ */ -+extern int __cvmx_helper_xaui_probe(int interface); -+ -+/** -+ * Bringup and enable a XAUI interface. After this call packet -+ * I/O should be fully functional. This is called with IPD -+ * enabled but PKO disabled. -+ * -+ * @interface: Interface to bring up -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_xaui_enable(int interface); -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+extern cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port); -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int __cvmx_helper_xaui_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info); -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, -+ int enable_internal, -+ int enable_external); -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper.c -@@ -0,0 +1,1058 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Helper functions for common, but complicated tasks. -+ * -+ */ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-fpa.h" -+#include "cvmx-pip.h" -+#include "cvmx-pko.h" -+#include "cvmx-ipd.h" -+#include "cvmx-spi.h" -+#include "cvmx-helper.h" -+#include "cvmx-helper-board.h" -+ -+#include "cvmx-pip-defs.h" -+#include "cvmx-smix-defs.h" -+#include "cvmx-asxx-defs.h" -+ -+/** -+ * cvmx_override_pko_queue_priority(int ipd_port, uint64_t -+ * priorities[16]) is a function pointer. It is meant to allow -+ * customization of the PKO queue priorities based on the port -+ * number. Users should set this pointer to a function before -+ * calling any cvmx-helper operations. -+ */ -+void (*cvmx_override_pko_queue_priority) (int pko_port, -+ uint64_t priorities[16]); -+ -+/** -+ * cvmx_override_ipd_port_setup(int ipd_port) is a function -+ * pointer. It is meant to allow customization of the IPD port -+ * setup before packet input/output comes online. It is called -+ * after cvmx-helper does the default IPD configuration, but -+ * before IPD is enabled. Users should set this pointer to a -+ * function before calling any cvmx-helper operations. -+ */ -+void (*cvmx_override_ipd_port_setup) (int ipd_port); -+ -+/* Port count per interface */ -+static int interface_port_count[4] = { 0, 0, 0, 0 }; -+ -+/* Port last configured link info index by IPD/PKO port */ -+static cvmx_helper_link_info_t -+ port_link_info[CVMX_PIP_NUM_INPUT_PORTS]; -+ -+/** -+ * Return the number of interfaces the chip has. Each interface -+ * may have multiple ports. Most chips support two interfaces, -+ * but the CNX0XX and CNX1XX are exceptions. These only support -+ * one interface. -+ * -+ * Returns Number of interfaces on chip -+ */ -+int cvmx_helper_get_number_of_interfaces(void) -+{ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ return 4; -+ else -+ return 3; -+} -+ -+/** -+ * Return the number of ports on an interface. Depending on the -+ * chip and configuration, this can be 1-16. A value of 0 -+ * specifies that the interface doesn't exist or isn't usable. -+ * -+ * @interface: Interface to get the port count for -+ * -+ * Returns Number of ports on interface. Can be Zero. -+ */ -+int cvmx_helper_ports_on_interface(int interface) -+{ -+ return interface_port_count[interface]; -+} -+ -+/** -+ * Get the operating mode of an interface. Depending on the Octeon -+ * chip and configuration, this function returns an enumeration -+ * of the type of packet I/O supported by an interface. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Mode of the interface. Unknown or unsupported interfaces return -+ * DISABLED. -+ */ -+cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) -+{ -+ union cvmx_gmxx_inf_mode mode; -+ if (interface == 2) -+ return CVMX_HELPER_INTERFACE_MODE_NPI; -+ -+ if (interface == 3) { -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX) -+ || OCTEON_IS_MODEL(OCTEON_CN52XX)) -+ return CVMX_HELPER_INTERFACE_MODE_LOOP; -+ else -+ return CVMX_HELPER_INTERFACE_MODE_DISABLED; -+ } -+ -+ if (interface == 0 -+ && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 -+ && cvmx_sysinfo_get()->board_rev_major == 1) { -+ /* -+ * Lie about interface type of CN3005 board. This -+ * board has a switch on port 1 like the other -+ * evaluation boards, but it is connected over RGMII -+ * instead of GMII. Report GMII mode so that the -+ * speed is forced to 1 Gbit full duplex. Other than -+ * some initial configuration (which does not use the -+ * output of this function) there is no difference in -+ * setup between GMII and RGMII modes. -+ */ -+ return CVMX_HELPER_INTERFACE_MODE_GMII; -+ } -+ -+ /* Interface 1 is always disabled on CN31XX and CN30XX */ -+ if ((interface == 1) -+ && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) -+ || OCTEON_IS_MODEL(OCTEON_CN50XX) -+ || OCTEON_IS_MODEL(OCTEON_CN52XX))) -+ return CVMX_HELPER_INTERFACE_MODE_DISABLED; -+ -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ switch (mode.cn56xx.mode) { -+ case 0: -+ return CVMX_HELPER_INTERFACE_MODE_DISABLED; -+ case 1: -+ return CVMX_HELPER_INTERFACE_MODE_XAUI; -+ case 2: -+ return CVMX_HELPER_INTERFACE_MODE_SGMII; -+ case 3: -+ return CVMX_HELPER_INTERFACE_MODE_PICMG; -+ default: -+ return CVMX_HELPER_INTERFACE_MODE_DISABLED; -+ } -+ } else { -+ if (!mode.s.en) -+ return CVMX_HELPER_INTERFACE_MODE_DISABLED; -+ -+ if (mode.s.type) { -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX)) -+ return CVMX_HELPER_INTERFACE_MODE_SPI; -+ else -+ return CVMX_HELPER_INTERFACE_MODE_GMII; -+ } else -+ return CVMX_HELPER_INTERFACE_MODE_RGMII; -+ } -+} -+ -+/** -+ * Configure the IPD/PIP tagging and QoS options for a specific -+ * port. This function determines the POW work queue entry -+ * contents for a port. The setup performed here is controlled by -+ * the defines in executive-config.h. -+ * -+ * @ipd_port: Port to configure. This follows the IPD numbering, not the -+ * per interface numbering -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_port_setup_ipd(int ipd_port) -+{ -+ union cvmx_pip_prt_cfgx port_config; -+ union cvmx_pip_prt_tagx tag_config; -+ -+ port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); -+ tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); -+ -+ /* Have each port go to a different POW queue */ -+ port_config.s.qos = ipd_port & 0x7; -+ -+ /* Process the headers and place the IP header in the work queue */ -+ port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; -+ -+ tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; -+ tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; -+ tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; -+ tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; -+ tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; -+ tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; -+ tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; -+ tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; -+ tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; -+ tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; -+ tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; -+ tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; -+ tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; -+ tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; -+ tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; -+ tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; -+ /* Put all packets in group 0. Other groups can be used by the app */ -+ tag_config.s.grp = 0; -+ -+ cvmx_pip_config_port(ipd_port, port_config, tag_config); -+ -+ /* Give the user a chance to override our setting for each port */ -+ if (cvmx_override_ipd_port_setup) -+ cvmx_override_ipd_port_setup(ipd_port); -+ -+ return 0; -+} -+ -+/** -+ * This function probes an interface to determine the actual -+ * number of hardware ports connected to it. It doesn't setup the -+ * ports or enable them. The main goal here is to set the global -+ * interface_port_count[interface] correctly. Hardware setup of the -+ * ports will be performed later. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_helper_interface_probe(int interface) -+{ -+ /* At this stage in the game we don't want packets to be moving yet. -+ The following probe calls should perform hardware setup -+ needed to determine port counts. Receive must still be disabled */ -+ switch (cvmx_helper_interface_get_mode(interface)) { -+ /* These types don't support ports to IPD/PKO */ -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ interface_port_count[interface] = 0; -+ break; -+ /* XAUI is a single high speed port */ -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ interface_port_count[interface] = -+ __cvmx_helper_xaui_probe(interface); -+ break; -+ /* -+ * RGMII/GMII/MII are all treated about the same. Most -+ * functions refer to these ports as RGMII. -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ interface_port_count[interface] = -+ __cvmx_helper_rgmii_probe(interface); -+ break; -+ /* -+ * SPI4 can have 1-16 ports depending on the device at -+ * the other end. -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ interface_port_count[interface] = -+ __cvmx_helper_spi_probe(interface); -+ break; -+ /* -+ * SGMII can have 1-4 ports depending on how many are -+ * hooked up. -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ interface_port_count[interface] = -+ __cvmx_helper_sgmii_probe(interface); -+ break; -+ /* PCI target Network Packet Interface */ -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ interface_port_count[interface] = -+ __cvmx_helper_npi_probe(interface); -+ break; -+ /* -+ * Special loopback only ports. These are not the same -+ * as other ports in loopback mode. -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ interface_port_count[interface] = -+ __cvmx_helper_loop_probe(interface); -+ break; -+ } -+ -+ interface_port_count[interface] = -+ __cvmx_helper_board_interface_probe(interface, -+ interface_port_count -+ [interface]); -+ -+ /* Make sure all global variables propagate to other cores */ -+ CVMX_SYNCWS; -+ -+ return 0; -+} -+ -+/** -+ * Setup the IPD/PIP for the ports on an interface. Packet -+ * classification and tagging are set for every port on the -+ * interface. The number of ports on the interface must already -+ * have been probed. -+ * -+ * @interface: Interface to setup IPD/PIP for -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_interface_setup_ipd(int interface) -+{ -+ int ipd_port = cvmx_helper_get_ipd_port(interface, 0); -+ int num_ports = interface_port_count[interface]; -+ -+ while (num_ports--) { -+ __cvmx_helper_port_setup_ipd(ipd_port); -+ ipd_port++; -+ } -+ return 0; -+} -+ -+/** -+ * Setup global setting for IPD/PIP not related to a specific -+ * interface or port. This must be called before IPD is enabled. -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+static int __cvmx_helper_global_setup_ipd(void) -+{ -+ /* Setup the global packet input options */ -+ cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8, -+ CVMX_HELPER_FIRST_MBUFF_SKIP / 8, -+ CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8, -+ /* The +8 is to account for the next ptr */ -+ (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128, -+ /* The +8 is to account for the next ptr */ -+ (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128, -+ CVMX_FPA_WQE_POOL, -+ CVMX_IPD_OPC_MODE_STT, -+ CVMX_HELPER_ENABLE_BACK_PRESSURE); -+ return 0; -+} -+ -+/** -+ * Setup the PKO for the ports on an interface. The number of -+ * queues per port and the priority of each PKO output queue -+ * is set here. PKO must be disabled when this function is called. -+ * -+ * @interface: Interface to setup PKO for -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_interface_setup_pko(int interface) -+{ -+ /* -+ * Each packet output queue has an associated priority. The -+ * higher the priority, the more often it can send a packet. A -+ * priority of 8 means it can send in all 8 rounds of -+ * contention. We're going to make each queue one less than -+ * the last. The vector of priorities has been extended to -+ * support CN5xxx CPUs, where up to 16 queues can be -+ * associated to a port. To keep backward compatibility we -+ * don't change the initial 8 priorities and replicate them in -+ * the second half. With per-core PKO queues (PKO lockless -+ * operation) all queues have the same priority. -+ */ -+ uint64_t priorities[16] = -+ { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 }; -+ -+ /* -+ * Setup the IPD/PIP and PKO for the ports discovered -+ * above. Here packet classification, tagging and output -+ * priorities are set. -+ */ -+ int ipd_port = cvmx_helper_get_ipd_port(interface, 0); -+ int num_ports = interface_port_count[interface]; -+ while (num_ports--) { -+ /* -+ * Give the user a chance to override the per queue -+ * priorities. -+ */ -+ if (cvmx_override_pko_queue_priority) -+ cvmx_override_pko_queue_priority(ipd_port, priorities); -+ -+ cvmx_pko_config_port(ipd_port, -+ cvmx_pko_get_base_queue_per_core(ipd_port, -+ 0), -+ cvmx_pko_get_num_queues(ipd_port), -+ priorities); -+ ipd_port++; -+ } -+ return 0; -+} -+ -+/** -+ * Setup global setting for PKO not related to a specific -+ * interface or port. This must be called before PKO is enabled. -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+static int __cvmx_helper_global_setup_pko(void) -+{ -+ /* -+ * Disable tagwait FAU timeout. This needs to be done before -+ * anyone might start packet output using tags. -+ */ -+ union cvmx_iob_fau_timeout fau_to; -+ fau_to.u64 = 0; -+ fau_to.s.tout_val = 0xfff; -+ fau_to.s.tout_enb = 0; -+ cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); -+ return 0; -+} -+ -+/** -+ * Setup global backpressure setting. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_global_setup_backpressure(void) -+{ -+#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE -+ /* Disable backpressure if configured to do so */ -+ /* Disable backpressure (pause frame) generation */ -+ int num_interfaces = cvmx_helper_get_number_of_interfaces(); -+ int interface; -+ for (interface = 0; interface < num_interfaces; interface++) { -+ switch (cvmx_helper_interface_get_mode(interface)) { -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ cvmx_gmx_set_backpressure_override(interface, 0xf); -+ break; -+ } -+ } -+#endif -+ -+ return 0; -+} -+ -+/** -+ * Enable packet input/output from the hardware. This function is -+ * called after all internal setup is complete and IPD is enabled. -+ * After this function completes, packets will be accepted from the -+ * hardware ports. PKO should still be disabled to make sure packets -+ * aren't sent out partially setup hardware. -+ * -+ * @interface: Interface to enable -+ * -+ * Returns Zero on success, negative on failure -+ */ -+static int __cvmx_helper_packet_hardware_enable(int interface) -+{ -+ int result = 0; -+ switch (cvmx_helper_interface_get_mode(interface)) { -+ /* These types don't support ports to IPD/PKO */ -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ /* Nothing to do */ -+ break; -+ /* XAUI is a single high speed port */ -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ result = __cvmx_helper_xaui_enable(interface); -+ break; -+ /* -+ * RGMII/GMII/MII are all treated about the same. Most -+ * functions refer to these ports as RGMII -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ result = __cvmx_helper_rgmii_enable(interface); -+ break; -+ /* -+ * SPI4 can have 1-16 ports depending on the device at -+ * the other end -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ result = __cvmx_helper_spi_enable(interface); -+ break; -+ /* -+ * SGMII can have 1-4 ports depending on how many are -+ * hooked up -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ result = __cvmx_helper_sgmii_enable(interface); -+ break; -+ /* PCI target Network Packet Interface */ -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ result = __cvmx_helper_npi_enable(interface); -+ break; -+ /* -+ * Special loopback only ports. These are not the same -+ * as other ports in loopback mode -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ result = __cvmx_helper_loop_enable(interface); -+ break; -+ } -+ result |= __cvmx_helper_board_hardware_enable(interface); -+ return result; -+} -+ -+/** -+ * Function to adjust internal IPD pointer alignments -+ * -+ * Returns 0 on success -+ * !0 on failure -+ */ -+int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) -+{ -+#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \ -+ (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP) -+#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \ -+ (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP) -+#define FIX_IPD_OUTPORT 0 -+ /* Ports 0-15 are interface 0, 16-31 are interface 1 */ -+#define INTERFACE(port) (port >> 4) -+#define INDEX(port) (port & 0xf) -+ uint64_t *p64; -+ cvmx_pko_command_word0_t pko_command; -+ union cvmx_buf_ptr g_buffer, pkt_buffer; -+ cvmx_wqe_t *work; -+ int size, num_segs = 0, wqe_pcnt, pkt_pcnt; -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ int retry_cnt; -+ int retry_loop_cnt; -+ int mtu; -+ int i; -+ cvmx_helper_link_info_t link_info; -+ -+ /* Save values for restore at end */ -+ uint64_t prtx_cfg = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t tx_ptr_en = -+ cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t rx_ptr_en = -+ cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t rxx_jabber = -+ cvmx_read_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); -+ uint64_t frame_max = -+ cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); -+ -+ /* Configure port to gig FDX as required for loopback mode */ -+ cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT); -+ -+ /* -+ * Disable reception on all ports so if traffic is present it -+ * will not interfere. -+ */ -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0); -+ -+ cvmx_wait(100000000ull); -+ -+ for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) { -+ retry_cnt = 100000; -+ wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT); -+ pkt_pcnt = (wqe_pcnt >> 7) & 0x7f; -+ wqe_pcnt &= 0x7f; -+ -+ num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3; -+ -+ if (num_segs == 0) -+ goto fix_ipd_exit; -+ -+ num_segs += 1; -+ -+ size = -+ FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES + -+ ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) - -+ (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2); -+ -+ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), -+ 1 << INDEX(FIX_IPD_OUTPORT)); -+ CVMX_SYNC; -+ -+ g_buffer.u64 = 0; -+ g_buffer.s.addr = -+ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL)); -+ if (g_buffer.s.addr == 0) { -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " -+ "buffer allocation failure.\n"); -+ goto fix_ipd_exit; -+ } -+ -+ g_buffer.s.pool = CVMX_FPA_WQE_POOL; -+ g_buffer.s.size = num_segs; -+ -+ pkt_buffer.u64 = 0; -+ pkt_buffer.s.addr = -+ cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL)); -+ if (pkt_buffer.s.addr == 0) { -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " -+ "buffer allocation failure.\n"); -+ goto fix_ipd_exit; -+ } -+ pkt_buffer.s.i = 1; -+ pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL; -+ pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES; -+ -+ p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr); -+ p64[0] = 0xffffffffffff0000ull; -+ p64[1] = 0x08004510ull; -+ p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull; -+ p64[3] = 0x3a5fc0a81073c0a8ull; -+ -+ for (i = 0; i < num_segs; i++) { -+ if (i > 0) -+ pkt_buffer.s.size = -+ FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES; -+ -+ if (i == (num_segs - 1)) -+ pkt_buffer.s.i = 0; -+ -+ *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr + -+ 8 * i) = pkt_buffer.u64; -+ } -+ -+ /* Build the PKO command */ -+ pko_command.u64 = 0; -+ pko_command.s.segs = num_segs; -+ pko_command.s.total_bytes = size; -+ pko_command.s.dontfree = 0; -+ pko_command.s.gather = 1; -+ -+ gmx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ 1 << INDEX(FIX_IPD_OUTPORT)); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ 1 << INDEX(FIX_IPD_OUTPORT)); -+ -+ mtu = -+ cvmx_read_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT))); -+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX -+ (INDEX(FIX_IPD_OUTPORT), -+ INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); -+ -+ cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, -+ cvmx_pko_get_base_queue -+ (FIX_IPD_OUTPORT), -+ CVMX_PKO_LOCK_CMD_QUEUE); -+ cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, -+ cvmx_pko_get_base_queue -+ (FIX_IPD_OUTPORT), pko_command, -+ g_buffer, CVMX_PKO_LOCK_CMD_QUEUE); -+ -+ CVMX_SYNC; -+ -+ do { -+ work = cvmx_pow_work_request_sync(CVMX_POW_WAIT); -+ retry_cnt--; -+ } while ((work == NULL) && (retry_cnt > 0)); -+ -+ if (!retry_cnt) -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " -+ "get_work() timeout occured.\n"); -+ -+ /* Free packet */ -+ if (work) -+ cvmx_helper_free_packet_data(work); -+ } -+ -+fix_ipd_exit: -+ -+ /* Return CSR configs to saved values */ -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), -+ prtx_cfg); -+ cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ tx_ptr_en); -+ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), -+ rx_ptr_en); -+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), -+ rxx_jabber); -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX -+ (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), -+ frame_max); -+ cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0); -+ /* Set link to down so autonegotiation will set it up again */ -+ link_info.u64 = 0; -+ cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info); -+ -+ /* -+ * Bring the link back up as autonegotiation is not done in -+ * user applications. -+ */ -+ cvmx_helper_link_autoconf(FIX_IPD_OUTPORT); -+ -+ CVMX_SYNC; -+ if (num_segs) -+ cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n"); -+ -+ return !!num_segs; -+ -+} -+ -+/** -+ * Called after all internal packet IO paths are setup. This -+ * function enables IPD/PIP and begins packet input and output. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_helper_ipd_and_packet_input_enable(void) -+{ -+ int num_interfaces; -+ int interface; -+ -+ /* Enable IPD */ -+ cvmx_ipd_enable(); -+ -+ /* -+ * Time to enable hardware ports packet input and output. Note -+ * that at this point IPD/PIP must be fully functional and PKO -+ * must be disabled -+ */ -+ num_interfaces = cvmx_helper_get_number_of_interfaces(); -+ for (interface = 0; interface < num_interfaces; interface++) { -+ if (cvmx_helper_ports_on_interface(interface) > 0) -+ __cvmx_helper_packet_hardware_enable(interface); -+ } -+ -+ /* Finally enable PKO now that the entire path is up and running */ -+ cvmx_pko_enable(); -+ -+ if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) -+ || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) -+ && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) -+ __cvmx_helper_errata_fix_ipd_ptr_alignment(); -+ return 0; -+} -+ -+/** -+ * Initialize the PIP, IPD, and PKO hardware to support -+ * simple priority based queues for the ethernet ports. Each -+ * port is configured with a number of priority queues based -+ * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower -+ * priority than the previous. -+ * -+ * Returns Zero on success, non-zero on failure -+ */ -+int cvmx_helper_initialize_packet_io_global(void) -+{ -+ int result = 0; -+ int interface; -+ union cvmx_l2c_cfg l2c_cfg; -+ union cvmx_smix_en smix_en; -+ const int num_interfaces = cvmx_helper_get_number_of_interfaces(); -+ -+ /* -+ * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to -+ * be disabled. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) -+ __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); -+ -+ /* -+ * Tell L2 to give the IOB statically higher priority compared -+ * to the cores. This avoids conditions where IO blocks might -+ * be starved under very high L2 loads. -+ */ -+ l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); -+ l2c_cfg.s.lrf_arb_mode = 0; -+ l2c_cfg.s.rfb_arb_mode = 0; -+ cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); -+ -+ /* Make sure SMI/MDIO is enabled so we can query PHYs */ -+ smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0)); -+ if (!smix_en.s.en) { -+ smix_en.s.en = 1; -+ cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64); -+ } -+ -+ /* Newer chips actually have two SMI/MDIO interfaces */ -+ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && -+ !OCTEON_IS_MODEL(OCTEON_CN58XX) && -+ !OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1)); -+ if (!smix_en.s.en) { -+ smix_en.s.en = 1; -+ cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64); -+ } -+ } -+ -+ cvmx_pko_initialize_global(); -+ for (interface = 0; interface < num_interfaces; interface++) { -+ result |= cvmx_helper_interface_probe(interface); -+ if (cvmx_helper_ports_on_interface(interface) > 0) -+ cvmx_dprintf("Interface %d has %d ports (%s)\n", -+ interface, -+ cvmx_helper_ports_on_interface(interface), -+ cvmx_helper_interface_mode_to_string -+ (cvmx_helper_interface_get_mode -+ (interface))); -+ result |= __cvmx_helper_interface_setup_ipd(interface); -+ result |= __cvmx_helper_interface_setup_pko(interface); -+ } -+ -+ result |= __cvmx_helper_global_setup_ipd(); -+ result |= __cvmx_helper_global_setup_pko(); -+ -+ /* Enable any flow control and backpressure */ -+ result |= __cvmx_helper_global_setup_backpressure(); -+ -+#if CVMX_HELPER_ENABLE_IPD -+ result |= cvmx_helper_ipd_and_packet_input_enable(); -+#endif -+ return result; -+} -+ -+/** -+ * Does core local initialization for packet io -+ * -+ * Returns Zero on success, non-zero on failure -+ */ -+int cvmx_helper_initialize_packet_io_local(void) -+{ -+ return cvmx_pko_initialize_local(); -+} -+ -+/** -+ * Auto configure an IPD/PKO port link state and speed. This -+ * function basically does the equivalent of: -+ * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); -+ * -+ * @ipd_port: IPD/PKO port to auto configure -+ * -+ * Returns Link state after configure -+ */ -+cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) -+{ -+ cvmx_helper_link_info_t link_info; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ -+ if (index >= cvmx_helper_ports_on_interface(interface)) { -+ link_info.u64 = 0; -+ return link_info; -+ } -+ -+ link_info = cvmx_helper_link_get(ipd_port); -+ if (link_info.u64 == port_link_info[ipd_port].u64) -+ return link_info; -+ -+ /* If we fail to set the link speed, port_link_info will not change */ -+ cvmx_helper_link_set(ipd_port, link_info); -+ -+ /* -+ * port_link_info should be the current value, which will be -+ * different than expect if cvmx_helper_link_set() failed. -+ */ -+ return port_link_info[ipd_port]; -+} -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) -+{ -+ cvmx_helper_link_info_t result; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ -+ /* The default result will be a down link unless the code below -+ changes it */ -+ result.u64 = 0; -+ -+ if (index >= cvmx_helper_ports_on_interface(interface)) -+ return result; -+ -+ switch (cvmx_helper_interface_get_mode(interface)) { -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ /* Network links are not supported */ -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ result = __cvmx_helper_xaui_link_get(ipd_port); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ if (index == 0) -+ result = __cvmx_helper_rgmii_link_get(ipd_port); -+ else { -+ result.s.full_duplex = 1; -+ result.s.link_up = 1; -+ result.s.speed = 1000; -+ } -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ result = __cvmx_helper_rgmii_link_get(ipd_port); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ result = __cvmx_helper_spi_link_get(ipd_port); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ result = __cvmx_helper_sgmii_link_get(ipd_port); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ /* Network links are not supported */ -+ break; -+ } -+ return result; -+} -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) -+{ -+ int result = -1; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ -+ if (index >= cvmx_helper_ports_on_interface(interface)) -+ return -1; -+ -+ switch (cvmx_helper_interface_get_mode(interface)) { -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ result = __cvmx_helper_xaui_link_set(ipd_port, link_info); -+ break; -+ /* -+ * RGMII/GMII/MII are all treated about the same. Most -+ * functions refer to these ports as RGMII. -+ */ -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ result = __cvmx_helper_spi_link_set(ipd_port, link_info); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ break; -+ } -+ /* Set the port_link_info here so that the link status is updated -+ no matter how cvmx_helper_link_set is called. We don't change -+ the value if link_set failed */ -+ if (result == 0) -+ port_link_info[ipd_port].u64 = link_info.u64; -+ return result; -+} -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, -+ int enable_external) -+{ -+ int result = -1; -+ int interface = cvmx_helper_get_interface_num(ipd_port); -+ int index = cvmx_helper_get_interface_index_num(ipd_port); -+ -+ if (index >= cvmx_helper_ports_on_interface(interface)) -+ return -1; -+ -+ switch (cvmx_helper_interface_get_mode(interface)) { -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ result = -+ __cvmx_helper_xaui_configure_loopback(ipd_port, -+ enable_internal, -+ enable_external); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ result = -+ __cvmx_helper_rgmii_configure_loopback(ipd_port, -+ enable_internal, -+ enable_external); -+ break; -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ result = -+ __cvmx_helper_sgmii_configure_loopback(ipd_port, -+ enable_internal, -+ enable_external); -+ break; -+ } -+ return result; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-helper.h -@@ -0,0 +1,227 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Helper functions for common, but complicated tasks. -+ * -+ */ -+ -+#ifndef __CVMX_HELPER_H__ -+#define __CVMX_HELPER_H__ -+ -+#include "cvmx-config.h" -+#include "cvmx-fpa.h" -+#include "cvmx-wqe.h" -+ -+typedef enum { -+ CVMX_HELPER_INTERFACE_MODE_DISABLED, -+ CVMX_HELPER_INTERFACE_MODE_RGMII, -+ CVMX_HELPER_INTERFACE_MODE_GMII, -+ CVMX_HELPER_INTERFACE_MODE_SPI, -+ CVMX_HELPER_INTERFACE_MODE_PCIE, -+ CVMX_HELPER_INTERFACE_MODE_XAUI, -+ CVMX_HELPER_INTERFACE_MODE_SGMII, -+ CVMX_HELPER_INTERFACE_MODE_PICMG, -+ CVMX_HELPER_INTERFACE_MODE_NPI, -+ CVMX_HELPER_INTERFACE_MODE_LOOP, -+} cvmx_helper_interface_mode_t; -+ -+typedef union { -+ uint64_t u64; -+ struct { -+ uint64_t reserved_20_63:44; -+ uint64_t link_up:1; /**< Is the physical link up? */ -+ uint64_t full_duplex:1; /**< 1 if the link is full duplex */ -+ uint64_t speed:18; /**< Speed of the link in Mbps */ -+ } s; -+} cvmx_helper_link_info_t; -+ -+#include "cvmx-helper-fpa.h" -+ -+#include -+#include "cvmx-helper-loop.h" -+#include "cvmx-helper-npi.h" -+#include "cvmx-helper-rgmii.h" -+#include "cvmx-helper-sgmii.h" -+#include "cvmx-helper-spi.h" -+#include "cvmx-helper-util.h" -+#include "cvmx-helper-xaui.h" -+ -+/** -+ * cvmx_override_pko_queue_priority(int ipd_port, uint64_t -+ * priorities[16]) is a function pointer. It is meant to allow -+ * customization of the PKO queue priorities based on the port -+ * number. Users should set this pointer to a function before -+ * calling any cvmx-helper operations. -+ */ -+extern void (*cvmx_override_pko_queue_priority) (int pko_port, -+ uint64_t priorities[16]); -+ -+/** -+ * cvmx_override_ipd_port_setup(int ipd_port) is a function -+ * pointer. It is meant to allow customization of the IPD port -+ * setup before packet input/output comes online. It is called -+ * after cvmx-helper does the default IPD configuration, but -+ * before IPD is enabled. Users should set this pointer to a -+ * function before calling any cvmx-helper operations. -+ */ -+extern void (*cvmx_override_ipd_port_setup) (int ipd_port); -+ -+/** -+ * This function enables the IPD and also enables the packet interfaces. -+ * The packet interfaces (RGMII and SPI) must be enabled after the -+ * IPD. This should be called by the user program after any additional -+ * IPD configuration changes are made if CVMX_HELPER_ENABLE_IPD -+ * is not set in the executive-config.h file. -+ * -+ * Returns 0 on success -+ * -1 on failure -+ */ -+extern int cvmx_helper_ipd_and_packet_input_enable(void); -+ -+/** -+ * Initialize the PIP, IPD, and PKO hardware to support -+ * simple priority based queues for the ethernet ports. Each -+ * port is configured with a number of priority queues based -+ * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower -+ * priority than the previous. -+ * -+ * Returns Zero on success, non-zero on failure -+ */ -+extern int cvmx_helper_initialize_packet_io_global(void); -+ -+/** -+ * Does core local initialization for packet io -+ * -+ * Returns Zero on success, non-zero on failure -+ */ -+extern int cvmx_helper_initialize_packet_io_local(void); -+ -+/** -+ * Returns the number of ports on the given interface. -+ * The interface must be initialized before the port count -+ * can be returned. -+ * -+ * @interface: Which interface to return port count for. -+ * -+ * Returns Port count for interface -+ * -1 for uninitialized interface -+ */ -+extern int cvmx_helper_ports_on_interface(int interface); -+ -+/** -+ * Return the number of interfaces the chip has. Each interface -+ * may have multiple ports. Most chips support two interfaces, -+ * but the CNX0XX and CNX1XX are exceptions. These only support -+ * one interface. -+ * -+ * Returns Number of interfaces on chip -+ */ -+extern int cvmx_helper_get_number_of_interfaces(void); -+ -+/** -+ * Get the operating mode of an interface. Depending on the Octeon -+ * chip and configuration, this function returns an enumeration -+ * of the type of packet I/O supported by an interface. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Mode of the interface. Unknown or unsupported interfaces return -+ * DISABLED. -+ */ -+extern cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int -+ interface); -+ -+/** -+ * Auto configure an IPD/PKO port link state and speed. This -+ * function basically does the equivalent of: -+ * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); -+ * -+ * @ipd_port: IPD/PKO port to auto configure -+ * -+ * Returns Link state after configure -+ */ -+extern cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port); -+ -+/** -+ * Return the link state of an IPD/PKO port as returned by -+ * auto negotiation. The result of this function may not match -+ * Octeon's link config if auto negotiation has changed since -+ * the last call to cvmx_helper_link_set(). -+ * -+ * @ipd_port: IPD/PKO port to query -+ * -+ * Returns Link state -+ */ -+extern cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port); -+ -+/** -+ * Configure an IPD/PKO port for the specified link state. This -+ * function does not influence auto negotiation at the PHY level. -+ * The passed link state must always match the link state returned -+ * by cvmx_helper_link_get(). It is normally best to use -+ * cvmx_helper_link_autoconf() instead. -+ * -+ * @ipd_port: IPD/PKO port to configure -+ * @link_info: The new link state -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int cvmx_helper_link_set(int ipd_port, -+ cvmx_helper_link_info_t link_info); -+ -+/** -+ * This function probes an interface to determine the actual -+ * number of hardware ports connected to it. It doesn't setup the -+ * ports or enable them. The main goal here is to set the global -+ * interface_port_count[interface] correctly. Hardware setup of the -+ * ports will be performed later. -+ * -+ * @interface: Interface to probe -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int cvmx_helper_interface_probe(int interface); -+ -+/** -+ * Configure a port for internal and/or external loopback. Internal loopback -+ * causes packets sent by the port to be received by Octeon. External loopback -+ * causes packets received from the wire to sent out again. -+ * -+ * @ipd_port: IPD/PKO port to loopback. -+ * @enable_internal: -+ * Non zero if you want internal loopback -+ * @enable_external: -+ * Non zero if you want external loopback -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+extern int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, -+ int enable_external); -+ -+#endif /* __CVMX_HELPER_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-interrupt-decodes.c -@@ -0,0 +1,371 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2009 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Automatically generated functions useful for enabling -+ * and decoding RSL_INT_BLOCKS interrupts. -+ * -+ */ -+ -+#include -+ -+#include "cvmx-gmxx-defs.h" -+#include "cvmx-pcsx-defs.h" -+#include "cvmx-pcsxx-defs.h" -+#include "cvmx-spxx-defs.h" -+#include "cvmx-stxx-defs.h" -+ -+#ifndef PRINT_ERROR -+#define PRINT_ERROR(format, ...) -+#endif -+ -+ -+/** -+ * __cvmx_interrupt_gmxx_rxx_int_en_enable enables all interrupt bits in cvmx_gmxx_rxx_int_en_t -+ */ -+void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block) -+{ -+ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, block), -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, block))); -+ gmx_rx_int_en.u64 = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_29_63 */ -+ gmx_rx_int_en.s.hg2cc = 1; -+ gmx_rx_int_en.s.hg2fld = 1; -+ gmx_rx_int_en.s.undat = 1; -+ gmx_rx_int_en.s.uneop = 1; -+ gmx_rx_int_en.s.unsop = 1; -+ gmx_rx_int_en.s.bad_term = 1; -+ gmx_rx_int_en.s.bad_seq = 1; -+ gmx_rx_int_en.s.rem_fault = 1; -+ gmx_rx_int_en.s.loc_fault = 1; -+ gmx_rx_int_en.s.pause_drp = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_16_18 */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_9_9 */ -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_5_6 */ -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_2_2 */ -+ gmx_rx_int_en.s.carext = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_0_0 */ -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN30XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_19_63 */ -+ /*gmx_rx_int_en.s.phy_dupx = 1; */ -+ /*gmx_rx_int_en.s.phy_spd = 1; */ -+ /*gmx_rx_int_en.s.phy_link = 1; */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ gmx_rx_int_en.s.niberr = 1; -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ -+ gmx_rx_int_en.s.alnerr = 1; -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ gmx_rx_int_en.s.maxerr = 1; -+ gmx_rx_int_en.s.carext = 1; -+ gmx_rx_int_en.s.minerr = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN50XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_20_63 */ -+ gmx_rx_int_en.s.pause_drp = 1; -+ /*gmx_rx_int_en.s.phy_dupx = 1; */ -+ /*gmx_rx_int_en.s.phy_spd = 1; */ -+ /*gmx_rx_int_en.s.phy_link = 1; */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ gmx_rx_int_en.s.niberr = 1; -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_6_6 */ -+ gmx_rx_int_en.s.alnerr = 1; -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_2_2 */ -+ gmx_rx_int_en.s.carext = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_0_0 */ -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_19_63 */ -+ /*gmx_rx_int_en.s.phy_dupx = 1; */ -+ /*gmx_rx_int_en.s.phy_spd = 1; */ -+ /*gmx_rx_int_en.s.phy_link = 1; */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ gmx_rx_int_en.s.niberr = 1; -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ -+ gmx_rx_int_en.s.alnerr = 1; -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ gmx_rx_int_en.s.maxerr = 1; -+ gmx_rx_int_en.s.carext = 1; -+ gmx_rx_int_en.s.minerr = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN31XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_19_63 */ -+ /*gmx_rx_int_en.s.phy_dupx = 1; */ -+ /*gmx_rx_int_en.s.phy_spd = 1; */ -+ /*gmx_rx_int_en.s.phy_link = 1; */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ gmx_rx_int_en.s.niberr = 1; -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ -+ gmx_rx_int_en.s.alnerr = 1; -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ gmx_rx_int_en.s.maxerr = 1; -+ gmx_rx_int_en.s.carext = 1; -+ gmx_rx_int_en.s.minerr = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_20_63 */ -+ gmx_rx_int_en.s.pause_drp = 1; -+ /*gmx_rx_int_en.s.phy_dupx = 1; */ -+ /*gmx_rx_int_en.s.phy_spd = 1; */ -+ /*gmx_rx_int_en.s.phy_link = 1; */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ gmx_rx_int_en.s.niberr = 1; -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */ -+ gmx_rx_int_en.s.alnerr = 1; -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ gmx_rx_int_en.s.maxerr = 1; -+ gmx_rx_int_en.s.carext = 1; -+ gmx_rx_int_en.s.minerr = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ /* Skipping gmx_rx_int_en.s.reserved_29_63 */ -+ gmx_rx_int_en.s.hg2cc = 1; -+ gmx_rx_int_en.s.hg2fld = 1; -+ gmx_rx_int_en.s.undat = 1; -+ gmx_rx_int_en.s.uneop = 1; -+ gmx_rx_int_en.s.unsop = 1; -+ gmx_rx_int_en.s.bad_term = 1; -+ gmx_rx_int_en.s.bad_seq = 0; -+ gmx_rx_int_en.s.rem_fault = 1; -+ gmx_rx_int_en.s.loc_fault = 0; -+ gmx_rx_int_en.s.pause_drp = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_16_18 */ -+ /*gmx_rx_int_en.s.ifgerr = 1; */ -+ /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */ -+ /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */ -+ /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */ -+ /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */ -+ gmx_rx_int_en.s.ovrerr = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_9_9 */ -+ gmx_rx_int_en.s.skperr = 1; -+ gmx_rx_int_en.s.rcverr = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_5_6 */ -+ /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */ -+ gmx_rx_int_en.s.jabber = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_2_2 */ -+ gmx_rx_int_en.s.carext = 1; -+ /* Skipping gmx_rx_int_en.s.reserved_0_0 */ -+ } -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, block), gmx_rx_int_en.u64); -+} -+/** -+ * __cvmx_interrupt_pcsx_intx_en_reg_enable enables all interrupt bits in cvmx_pcsx_intx_en_reg_t -+ */ -+void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block) -+{ -+ union cvmx_pcsx_intx_en_reg pcs_int_en_reg; -+ cvmx_write_csr(CVMX_PCSX_INTX_REG(index, block), -+ cvmx_read_csr(CVMX_PCSX_INTX_REG(index, block))); -+ pcs_int_en_reg.u64 = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) { -+ /* Skipping pcs_int_en_reg.s.reserved_12_63 */ -+ /*pcs_int_en_reg.s.dup = 1; // This happens during normal operation */ -+ pcs_int_en_reg.s.sync_bad_en = 1; -+ pcs_int_en_reg.s.an_bad_en = 1; -+ pcs_int_en_reg.s.rxlock_en = 1; -+ pcs_int_en_reg.s.rxbad_en = 1; -+ /*pcs_int_en_reg.s.rxerr_en = 1; // This happens during normal operation */ -+ pcs_int_en_reg.s.txbad_en = 1; -+ pcs_int_en_reg.s.txfifo_en = 1; -+ pcs_int_en_reg.s.txfifu_en = 1; -+ pcs_int_en_reg.s.an_err_en = 1; -+ /*pcs_int_en_reg.s.xmit_en = 1; // This happens during normal operation */ -+ /*pcs_int_en_reg.s.lnkspd_en = 1; // This happens during normal operation */ -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ /* Skipping pcs_int_en_reg.s.reserved_12_63 */ -+ /*pcs_int_en_reg.s.dup = 1; // This happens during normal operation */ -+ pcs_int_en_reg.s.sync_bad_en = 1; -+ pcs_int_en_reg.s.an_bad_en = 1; -+ pcs_int_en_reg.s.rxlock_en = 1; -+ pcs_int_en_reg.s.rxbad_en = 1; -+ /*pcs_int_en_reg.s.rxerr_en = 1; // This happens during normal operation */ -+ pcs_int_en_reg.s.txbad_en = 1; -+ pcs_int_en_reg.s.txfifo_en = 1; -+ pcs_int_en_reg.s.txfifu_en = 1; -+ pcs_int_en_reg.s.an_err_en = 1; -+ /*pcs_int_en_reg.s.xmit_en = 1; // This happens during normal operation */ -+ /*pcs_int_en_reg.s.lnkspd_en = 1; // This happens during normal operation */ -+ } -+ cvmx_write_csr(CVMX_PCSX_INTX_EN_REG(index, block), pcs_int_en_reg.u64); -+} -+/** -+ * __cvmx_interrupt_pcsxx_int_en_reg_enable enables all interrupt bits in cvmx_pcsxx_int_en_reg_t -+ */ -+void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index) -+{ -+ union cvmx_pcsxx_int_en_reg pcsx_int_en_reg; -+ cvmx_write_csr(CVMX_PCSXX_INT_REG(index), -+ cvmx_read_csr(CVMX_PCSXX_INT_REG(index))); -+ pcsx_int_en_reg.u64 = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX)) { -+ /* Skipping pcsx_int_en_reg.s.reserved_6_63 */ -+ pcsx_int_en_reg.s.algnlos_en = 1; -+ pcsx_int_en_reg.s.synlos_en = 1; -+ pcsx_int_en_reg.s.bitlckls_en = 1; -+ pcsx_int_en_reg.s.rxsynbad_en = 1; -+ pcsx_int_en_reg.s.rxbad_en = 1; -+ pcsx_int_en_reg.s.txflt_en = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ /* Skipping pcsx_int_en_reg.s.reserved_6_63 */ -+ pcsx_int_en_reg.s.algnlos_en = 1; -+ pcsx_int_en_reg.s.synlos_en = 1; -+ pcsx_int_en_reg.s.bitlckls_en = 0; /* Happens if XAUI module is not installed */ -+ pcsx_int_en_reg.s.rxsynbad_en = 1; -+ pcsx_int_en_reg.s.rxbad_en = 1; -+ pcsx_int_en_reg.s.txflt_en = 1; -+ } -+ cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(index), pcsx_int_en_reg.u64); -+} -+ -+/** -+ * __cvmx_interrupt_spxx_int_msk_enable enables all interrupt bits in cvmx_spxx_int_msk_t -+ */ -+void __cvmx_interrupt_spxx_int_msk_enable(int index) -+{ -+ union cvmx_spxx_int_msk spx_int_msk; -+ cvmx_write_csr(CVMX_SPXX_INT_REG(index), -+ cvmx_read_csr(CVMX_SPXX_INT_REG(index))); -+ spx_int_msk.u64 = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { -+ /* Skipping spx_int_msk.s.reserved_12_63 */ -+ spx_int_msk.s.calerr = 1; -+ spx_int_msk.s.syncerr = 1; -+ spx_int_msk.s.diperr = 1; -+ spx_int_msk.s.tpaovr = 1; -+ spx_int_msk.s.rsverr = 1; -+ spx_int_msk.s.drwnng = 1; -+ spx_int_msk.s.clserr = 1; -+ spx_int_msk.s.spiovr = 1; -+ /* Skipping spx_int_msk.s.reserved_2_3 */ -+ spx_int_msk.s.abnorm = 1; -+ spx_int_msk.s.prtnxa = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ /* Skipping spx_int_msk.s.reserved_12_63 */ -+ spx_int_msk.s.calerr = 1; -+ spx_int_msk.s.syncerr = 1; -+ spx_int_msk.s.diperr = 1; -+ spx_int_msk.s.tpaovr = 1; -+ spx_int_msk.s.rsverr = 1; -+ spx_int_msk.s.drwnng = 1; -+ spx_int_msk.s.clserr = 1; -+ spx_int_msk.s.spiovr = 1; -+ /* Skipping spx_int_msk.s.reserved_2_3 */ -+ spx_int_msk.s.abnorm = 1; -+ spx_int_msk.s.prtnxa = 1; -+ } -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(index), spx_int_msk.u64); -+} -+/** -+ * __cvmx_interrupt_stxx_int_msk_enable enables all interrupt bits in cvmx_stxx_int_msk_t -+ */ -+void __cvmx_interrupt_stxx_int_msk_enable(int index) -+{ -+ union cvmx_stxx_int_msk stx_int_msk; -+ cvmx_write_csr(CVMX_STXX_INT_REG(index), -+ cvmx_read_csr(CVMX_STXX_INT_REG(index))); -+ stx_int_msk.u64 = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { -+ /* Skipping stx_int_msk.s.reserved_8_63 */ -+ stx_int_msk.s.frmerr = 1; -+ stx_int_msk.s.unxfrm = 1; -+ stx_int_msk.s.nosync = 1; -+ stx_int_msk.s.diperr = 1; -+ stx_int_msk.s.datovr = 1; -+ stx_int_msk.s.ovrbst = 1; -+ stx_int_msk.s.calpar1 = 1; -+ stx_int_msk.s.calpar0 = 1; -+ } -+ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ /* Skipping stx_int_msk.s.reserved_8_63 */ -+ stx_int_msk.s.frmerr = 1; -+ stx_int_msk.s.unxfrm = 1; -+ stx_int_msk.s.nosync = 1; -+ stx_int_msk.s.diperr = 1; -+ stx_int_msk.s.datovr = 1; -+ stx_int_msk.s.ovrbst = 1; -+ stx_int_msk.s.calpar1 = 1; -+ stx_int_msk.s.calpar0 = 1; -+ } -+ cvmx_write_csr(CVMX_STXX_INT_MSK(index), stx_int_msk.u64); -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-interrupt-rsl.c -@@ -0,0 +1,140 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Utility functions to decode Octeon's RSL_INT_BLOCKS -+ * interrupts into error messages. -+ */ -+ -+#include -+ -+#include "cvmx-asxx-defs.h" -+#include "cvmx-gmxx-defs.h" -+ -+#ifndef PRINT_ERROR -+#define PRINT_ERROR(format, ...) -+#endif -+ -+void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block); -+ -+/** -+ * Enable ASX error interrupts that exist on CN3XXX, CN50XX, and -+ * CN58XX. -+ * -+ * @block: Interface to enable 0-1 -+ */ -+void __cvmx_interrupt_asxx_enable(int block) -+{ -+ int mask; -+ union cvmx_asxx_int_en csr; -+ /* -+ * CN38XX and CN58XX have two interfaces with 4 ports per -+ * interface. All other chips have a max of 3 ports on -+ * interface 0 -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) -+ mask = 0xf; /* Set enables for 4 ports */ -+ else -+ mask = 0x7; /* Set enables for 3 ports */ -+ -+ /* Enable interface interrupts */ -+ csr.u64 = cvmx_read_csr(CVMX_ASXX_INT_EN(block)); -+ csr.s.txpsh = mask; -+ csr.s.txpop = mask; -+ csr.s.ovrflw = mask; -+ cvmx_write_csr(CVMX_ASXX_INT_EN(block), csr.u64); -+} -+/** -+ * Enable GMX error reporting for the supplied interface -+ * -+ * @interface: Interface to enable -+ */ -+void __cvmx_interrupt_gmxx_enable(int interface) -+{ -+ union cvmx_gmxx_inf_mode mode; -+ union cvmx_gmxx_tx_int_en gmx_tx_int_en; -+ int num_ports; -+ int index; -+ -+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ if (mode.s.en) { -+ switch (mode.cn56xx.mode) { -+ case 1: /* XAUI */ -+ num_ports = 1; -+ break; -+ case 2: /* SGMII */ -+ case 3: /* PICMG */ -+ num_ports = 4; -+ break; -+ default: /* Disabled */ -+ num_ports = 0; -+ break; -+ } -+ } else -+ num_ports = 0; -+ } else { -+ if (mode.s.en) { -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ /* -+ * SPI on CN38XX and CN58XX report all -+ * errors through port 0. RGMII needs -+ * to check all 4 ports -+ */ -+ if (mode.s.type) -+ num_ports = 1; -+ else -+ num_ports = 4; -+ } else { -+ /* -+ * CN30XX, CN31XX, and CN50XX have two -+ * or three ports. GMII and MII has 2, -+ * RGMII has three -+ */ -+ if (mode.s.type) -+ num_ports = 2; -+ else -+ num_ports = 3; -+ } -+ } else -+ num_ports = 0; -+ } -+ -+ gmx_tx_int_en.u64 = 0; -+ if (num_ports) { -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX)) -+ gmx_tx_int_en.s.ncb_nxa = 1; -+ gmx_tx_int_en.s.pko_nxa = 1; -+ } -+ gmx_tx_int_en.s.undflw = (1 << num_ports) - 1; -+ cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64); -+ for (index = 0; index < num_ports; index++) -+ __cvmx_interrupt_gmxx_rxx_int_en_enable(index, interface); -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-ipd.h -@@ -0,0 +1,338 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Interface to the hardware Input Packet Data unit. -+ */ -+ -+#ifndef __CVMX_IPD_H__ -+#define __CVMX_IPD_H__ -+ -+#include -+ -+#include -+ -+enum cvmx_ipd_mode { -+ CVMX_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */ -+ CVMX_IPD_OPC_MODE_STF = 1LL, /* All bloccks into L2 */ -+ CVMX_IPD_OPC_MODE_STF1_STT = 2LL, /* 1st block L2, rest DRAM */ -+ CVMX_IPD_OPC_MODE_STF2_STT = 3LL /* 1st, 2nd blocks L2, rest DRAM */ -+}; -+ -+#ifndef CVMX_ENABLE_LEN_M8_FIX -+#define CVMX_ENABLE_LEN_M8_FIX 0 -+#endif -+ -+/* CSR typedefs have been moved to cvmx-csr-*.h */ -+typedef union cvmx_ipd_1st_mbuff_skip cvmx_ipd_mbuff_first_skip_t; -+typedef union cvmx_ipd_1st_next_ptr_back cvmx_ipd_first_next_ptr_back_t; -+ -+typedef cvmx_ipd_mbuff_first_skip_t cvmx_ipd_mbuff_not_first_skip_t; -+typedef cvmx_ipd_first_next_ptr_back_t cvmx_ipd_second_next_ptr_back_t; -+ -+/** -+ * Configure IPD -+ * -+ * @mbuff_size: Packets buffer size in 8 byte words -+ * @first_mbuff_skip: -+ * Number of 8 byte words to skip in the first buffer -+ * @not_first_mbuff_skip: -+ * Number of 8 byte words to skip in each following buffer -+ * @first_back: Must be same as first_mbuff_skip / 128 -+ * @second_back: -+ * Must be same as not_first_mbuff_skip / 128 -+ * @wqe_fpa_pool: -+ * FPA pool to get work entries from -+ * @cache_mode: -+ * @back_pres_enable_flag: -+ * Enable or disable port back pressure -+ */ -+static inline void cvmx_ipd_config(uint64_t mbuff_size, -+ uint64_t first_mbuff_skip, -+ uint64_t not_first_mbuff_skip, -+ uint64_t first_back, -+ uint64_t second_back, -+ uint64_t wqe_fpa_pool, -+ enum cvmx_ipd_mode cache_mode, -+ uint64_t back_pres_enable_flag) -+{ -+ cvmx_ipd_mbuff_first_skip_t first_skip; -+ cvmx_ipd_mbuff_not_first_skip_t not_first_skip; -+ union cvmx_ipd_packet_mbuff_size size; -+ cvmx_ipd_first_next_ptr_back_t first_back_struct; -+ cvmx_ipd_second_next_ptr_back_t second_back_struct; -+ union cvmx_ipd_wqe_fpa_queue wqe_pool; -+ union cvmx_ipd_ctl_status ipd_ctl_reg; -+ -+ first_skip.u64 = 0; -+ first_skip.s.skip_sz = first_mbuff_skip; -+ cvmx_write_csr(CVMX_IPD_1ST_MBUFF_SKIP, first_skip.u64); -+ -+ not_first_skip.u64 = 0; -+ not_first_skip.s.skip_sz = not_first_mbuff_skip; -+ cvmx_write_csr(CVMX_IPD_NOT_1ST_MBUFF_SKIP, not_first_skip.u64); -+ -+ size.u64 = 0; -+ size.s.mb_size = mbuff_size; -+ cvmx_write_csr(CVMX_IPD_PACKET_MBUFF_SIZE, size.u64); -+ -+ first_back_struct.u64 = 0; -+ first_back_struct.s.back = first_back; -+ cvmx_write_csr(CVMX_IPD_1st_NEXT_PTR_BACK, first_back_struct.u64); -+ -+ second_back_struct.u64 = 0; -+ second_back_struct.s.back = second_back; -+ cvmx_write_csr(CVMX_IPD_2nd_NEXT_PTR_BACK, second_back_struct.u64); -+ -+ wqe_pool.u64 = 0; -+ wqe_pool.s.wqe_pool = wqe_fpa_pool; -+ cvmx_write_csr(CVMX_IPD_WQE_FPA_QUEUE, wqe_pool.u64); -+ -+ ipd_ctl_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); -+ ipd_ctl_reg.s.opc_mode = cache_mode; -+ ipd_ctl_reg.s.pbp_en = back_pres_enable_flag; -+ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_reg.u64); -+ -+ /* Note: the example RED code that used to be here has been moved to -+ cvmx_helper_setup_red */ -+} -+ -+/** -+ * Enable IPD -+ */ -+static inline void cvmx_ipd_enable(void) -+{ -+ union cvmx_ipd_ctl_status ipd_reg; -+ ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); -+ if (ipd_reg.s.ipd_en) { -+ cvmx_dprintf -+ ("Warning: Enabling IPD when IPD already enabled.\n"); -+ } -+ ipd_reg.s.ipd_en = 1; -+#if CVMX_ENABLE_LEN_M8_FIX -+ if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) -+ ipd_reg.s.len_m8 = TRUE; -+#endif -+ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); -+} -+ -+/** -+ * Disable IPD -+ */ -+static inline void cvmx_ipd_disable(void) -+{ -+ union cvmx_ipd_ctl_status ipd_reg; -+ ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); -+ ipd_reg.s.ipd_en = 0; -+ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); -+} -+ -+/** -+ * Supportive function for cvmx_fpa_shutdown_pool. -+ */ -+static inline void cvmx_ipd_free_ptr(void) -+{ -+ /* Only CN38XXp{1,2} cannot read pointer out of the IPD */ -+ if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1) -+ && !OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) { -+ int no_wptr = 0; -+ union cvmx_ipd_ptr_count ipd_ptr_count; -+ ipd_ptr_count.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); -+ -+ /* Handle Work Queue Entry in cn56xx and cn52xx */ -+ if (octeon_has_feature(OCTEON_FEATURE_NO_WPTR)) { -+ union cvmx_ipd_ctl_status ipd_ctl_status; -+ ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); -+ if (ipd_ctl_status.s.no_wptr) -+ no_wptr = 1; -+ } -+ -+ /* Free the prefetched WQE */ -+ if (ipd_ptr_count.s.wqev_cnt) { -+ union cvmx_ipd_wqe_ptr_valid ipd_wqe_ptr_valid; -+ ipd_wqe_ptr_valid.u64 = -+ cvmx_read_csr(CVMX_IPD_WQE_PTR_VALID); -+ if (no_wptr) -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) ipd_wqe_ptr_valid.s. -+ ptr << 7), CVMX_FPA_PACKET_POOL, -+ 0); -+ else -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) ipd_wqe_ptr_valid.s. -+ ptr << 7), CVMX_FPA_WQE_POOL, 0); -+ } -+ -+ /* Free all WQE in the fifo */ -+ if (ipd_ptr_count.s.wqe_pcnt) { -+ int i; -+ union cvmx_ipd_pwp_ptr_fifo_ctl ipd_pwp_ptr_fifo_ctl; -+ ipd_pwp_ptr_fifo_ctl.u64 = -+ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); -+ for (i = 0; i < ipd_ptr_count.s.wqe_pcnt; i++) { -+ ipd_pwp_ptr_fifo_ctl.s.cena = 0; -+ ipd_pwp_ptr_fifo_ctl.s.raddr = -+ ipd_pwp_ptr_fifo_ctl.s.max_cnts + -+ (ipd_pwp_ptr_fifo_ctl.s.wraddr + -+ i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts; -+ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, -+ ipd_pwp_ptr_fifo_ctl.u64); -+ ipd_pwp_ptr_fifo_ctl.u64 = -+ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); -+ if (no_wptr) -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) -+ ipd_pwp_ptr_fifo_ctl.s. -+ ptr << 7), -+ CVMX_FPA_PACKET_POOL, 0); -+ else -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) -+ ipd_pwp_ptr_fifo_ctl.s. -+ ptr << 7), -+ CVMX_FPA_WQE_POOL, 0); -+ } -+ ipd_pwp_ptr_fifo_ctl.s.cena = 1; -+ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, -+ ipd_pwp_ptr_fifo_ctl.u64); -+ } -+ -+ /* Free the prefetched packet */ -+ if (ipd_ptr_count.s.pktv_cnt) { -+ union cvmx_ipd_pkt_ptr_valid ipd_pkt_ptr_valid; -+ ipd_pkt_ptr_valid.u64 = -+ cvmx_read_csr(CVMX_IPD_PKT_PTR_VALID); -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ (ipd_pkt_ptr_valid.s.ptr << 7), -+ CVMX_FPA_PACKET_POOL, 0); -+ } -+ -+ /* Free the per port prefetched packets */ -+ if (1) { -+ int i; -+ union cvmx_ipd_prc_port_ptr_fifo_ctl -+ ipd_prc_port_ptr_fifo_ctl; -+ ipd_prc_port_ptr_fifo_ctl.u64 = -+ cvmx_read_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL); -+ -+ for (i = 0; i < ipd_prc_port_ptr_fifo_ctl.s.max_pkt; -+ i++) { -+ ipd_prc_port_ptr_fifo_ctl.s.cena = 0; -+ ipd_prc_port_ptr_fifo_ctl.s.raddr = -+ i % ipd_prc_port_ptr_fifo_ctl.s.max_pkt; -+ cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL, -+ ipd_prc_port_ptr_fifo_ctl.u64); -+ ipd_prc_port_ptr_fifo_ctl.u64 = -+ cvmx_read_csr -+ (CVMX_IPD_PRC_PORT_PTR_FIFO_CTL); -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) -+ ipd_prc_port_ptr_fifo_ctl.s. -+ ptr << 7), CVMX_FPA_PACKET_POOL, -+ 0); -+ } -+ ipd_prc_port_ptr_fifo_ctl.s.cena = 1; -+ cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL, -+ ipd_prc_port_ptr_fifo_ctl.u64); -+ } -+ -+ /* Free all packets in the holding fifo */ -+ if (ipd_ptr_count.s.pfif_cnt) { -+ int i; -+ union cvmx_ipd_prc_hold_ptr_fifo_ctl -+ ipd_prc_hold_ptr_fifo_ctl; -+ -+ ipd_prc_hold_ptr_fifo_ctl.u64 = -+ cvmx_read_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL); -+ -+ for (i = 0; i < ipd_ptr_count.s.pfif_cnt; i++) { -+ ipd_prc_hold_ptr_fifo_ctl.s.cena = 0; -+ ipd_prc_hold_ptr_fifo_ctl.s.raddr = -+ (ipd_prc_hold_ptr_fifo_ctl.s.praddr + -+ i) % ipd_prc_hold_ptr_fifo_ctl.s.max_pkt; -+ cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL, -+ ipd_prc_hold_ptr_fifo_ctl.u64); -+ ipd_prc_hold_ptr_fifo_ctl.u64 = -+ cvmx_read_csr -+ (CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL); -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) -+ ipd_prc_hold_ptr_fifo_ctl.s. -+ ptr << 7), CVMX_FPA_PACKET_POOL, -+ 0); -+ } -+ ipd_prc_hold_ptr_fifo_ctl.s.cena = 1; -+ cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL, -+ ipd_prc_hold_ptr_fifo_ctl.u64); -+ } -+ -+ /* Free all packets in the fifo */ -+ if (ipd_ptr_count.s.pkt_pcnt) { -+ int i; -+ union cvmx_ipd_pwp_ptr_fifo_ctl ipd_pwp_ptr_fifo_ctl; -+ ipd_pwp_ptr_fifo_ctl.u64 = -+ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); -+ -+ for (i = 0; i < ipd_ptr_count.s.pkt_pcnt; i++) { -+ ipd_pwp_ptr_fifo_ctl.s.cena = 0; -+ ipd_pwp_ptr_fifo_ctl.s.raddr = -+ (ipd_pwp_ptr_fifo_ctl.s.praddr + -+ i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts; -+ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, -+ ipd_pwp_ptr_fifo_ctl.u64); -+ ipd_pwp_ptr_fifo_ctl.u64 = -+ cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); -+ cvmx_fpa_free(cvmx_phys_to_ptr -+ ((uint64_t) ipd_pwp_ptr_fifo_ctl. -+ s.ptr << 7), -+ CVMX_FPA_PACKET_POOL, 0); -+ } -+ ipd_pwp_ptr_fifo_ctl.s.cena = 1; -+ cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, -+ ipd_pwp_ptr_fifo_ctl.u64); -+ } -+ -+ /* Reset the IPD to get all buffers out of it */ -+ { -+ union cvmx_ipd_ctl_status ipd_ctl_status; -+ ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); -+ ipd_ctl_status.s.reset = 1; -+ cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); -+ } -+ -+ /* Reset the PIP */ -+ { -+ union cvmx_pip_sft_rst pip_sft_rst; -+ pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST); -+ pip_sft_rst.s.rst = 1; -+ cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64); -+ } -+ } -+} -+ -+#endif /* __CVMX_IPD_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-mdio.h -@@ -0,0 +1,506 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3 -+ * clause 22 and clause 45 operations. -+ * -+ */ -+ -+#ifndef __CVMX_MIO_H__ -+#define __CVMX_MIO_H__ -+ -+#include "cvmx-smix-defs.h" -+ -+/** -+ * PHY register 0 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_CONTROL 0 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t reset:1; -+ uint16_t loopback:1; -+ uint16_t speed_lsb:1; -+ uint16_t autoneg_enable:1; -+ uint16_t power_down:1; -+ uint16_t isolate:1; -+ uint16_t restart_autoneg:1; -+ uint16_t duplex:1; -+ uint16_t collision_test:1; -+ uint16_t speed_msb:1; -+ uint16_t unidirectional_enable:1; -+ uint16_t reserved_0_4:5; -+ } s; -+} cvmx_mdio_phy_reg_control_t; -+ -+/** -+ * PHY register 1 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_STATUS 1 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t capable_100base_t4:1; -+ uint16_t capable_100base_x_full:1; -+ uint16_t capable_100base_x_half:1; -+ uint16_t capable_10_full:1; -+ uint16_t capable_10_half:1; -+ uint16_t capable_100base_t2_full:1; -+ uint16_t capable_100base_t2_half:1; -+ uint16_t capable_extended_status:1; -+ uint16_t capable_unidirectional:1; -+ uint16_t capable_mf_preamble_suppression:1; -+ uint16_t autoneg_complete:1; -+ uint16_t remote_fault:1; -+ uint16_t capable_autoneg:1; -+ uint16_t link_status:1; -+ uint16_t jabber_detect:1; -+ uint16_t capable_extended_registers:1; -+ -+ } s; -+} cvmx_mdio_phy_reg_status_t; -+ -+/** -+ * PHY register 2 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_ID1 2 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t oui_bits_3_18; -+ } s; -+} cvmx_mdio_phy_reg_id1_t; -+ -+/** -+ * PHY register 3 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_ID2 3 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t oui_bits_19_24:6; -+ uint16_t model:6; -+ uint16_t revision:4; -+ } s; -+} cvmx_mdio_phy_reg_id2_t; -+ -+/** -+ * PHY register 4 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t next_page:1; -+ uint16_t reserved_14:1; -+ uint16_t remote_fault:1; -+ uint16_t reserved_12:1; -+ uint16_t asymmetric_pause:1; -+ uint16_t pause:1; -+ uint16_t advert_100base_t4:1; -+ uint16_t advert_100base_tx_full:1; -+ uint16_t advert_100base_tx_half:1; -+ uint16_t advert_10base_tx_full:1; -+ uint16_t advert_10base_tx_half:1; -+ uint16_t selector:5; -+ } s; -+} cvmx_mdio_phy_reg_autoneg_adver_t; -+ -+/** -+ * PHY register 5 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t next_page:1; -+ uint16_t ack:1; -+ uint16_t remote_fault:1; -+ uint16_t reserved_12:1; -+ uint16_t asymmetric_pause:1; -+ uint16_t pause:1; -+ uint16_t advert_100base_t4:1; -+ uint16_t advert_100base_tx_full:1; -+ uint16_t advert_100base_tx_half:1; -+ uint16_t advert_10base_tx_full:1; -+ uint16_t advert_10base_tx_half:1; -+ uint16_t selector:5; -+ } s; -+} cvmx_mdio_phy_reg_link_partner_ability_t; -+ -+/** -+ * PHY register 6 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t reserved_5_15:11; -+ uint16_t parallel_detection_fault:1; -+ uint16_t link_partner_next_page_capable:1; -+ uint16_t local_next_page_capable:1; -+ uint16_t page_received:1; -+ uint16_t link_partner_autoneg_capable:1; -+ -+ } s; -+} cvmx_mdio_phy_reg_autoneg_expansion_t; -+ -+/** -+ * PHY register 9 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_CONTROL_1000 9 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t test_mode:3; -+ uint16_t manual_master_slave:1; -+ uint16_t master:1; -+ uint16_t port_type:1; -+ uint16_t advert_1000base_t_full:1; -+ uint16_t advert_1000base_t_half:1; -+ uint16_t reserved_0_7:8; -+ } s; -+} cvmx_mdio_phy_reg_control_1000_t; -+ -+/** -+ * PHY register 10 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_STATUS_1000 10 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t master_slave_fault:1; -+ uint16_t is_master:1; -+ uint16_t local_receiver_ok:1; -+ uint16_t remote_receiver_ok:1; -+ uint16_t remote_capable_1000base_t_full:1; -+ uint16_t remote_capable_1000base_t_half:1; -+ uint16_t reserved_8_9:2; -+ uint16_t idle_error_count:8; -+ } s; -+} cvmx_mdio_phy_reg_status_1000_t; -+ -+/** -+ * PHY register 15 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t capable_1000base_x_full:1; -+ uint16_t capable_1000base_x_half:1; -+ uint16_t capable_1000base_t_full:1; -+ uint16_t capable_1000base_t_half:1; -+ uint16_t reserved_0_11:12; -+ } s; -+} cvmx_mdio_phy_reg_extended_status_t; -+ -+/** -+ * PHY register 13 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t function:2; -+ uint16_t reserved_5_13:9; -+ uint16_t devad:5; -+ } s; -+} cvmx_mdio_phy_reg_mmd_control_t; -+ -+/** -+ * PHY register 14 from the 802.3 spec -+ */ -+#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14 -+typedef union { -+ uint16_t u16; -+ struct { -+ uint16_t address_data:16; -+ } s; -+} cvmx_mdio_phy_reg_mmd_address_data_t; -+ -+/* Operating request encodings. */ -+#define MDIO_CLAUSE_22_WRITE 0 -+#define MDIO_CLAUSE_22_READ 1 -+ -+#define MDIO_CLAUSE_45_ADDRESS 0 -+#define MDIO_CLAUSE_45_WRITE 1 -+#define MDIO_CLAUSE_45_READ_INC 2 -+#define MDIO_CLAUSE_45_READ 3 -+ -+/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */ -+#define CVMX_MMD_DEVICE_PMA_PMD 1 -+#define CVMX_MMD_DEVICE_WIS 2 -+#define CVMX_MMD_DEVICE_PCS 3 -+#define CVMX_MMD_DEVICE_PHY_XS 4 -+#define CVMX_MMD_DEVICE_DTS_XS 5 -+#define CVMX_MMD_DEVICE_TC 6 -+#define CVMX_MMD_DEVICE_CL22_EXT 29 -+#define CVMX_MMD_DEVICE_VENDOR_1 30 -+#define CVMX_MMD_DEVICE_VENDOR_2 31 -+ -+/* Helper function to put MDIO interface into clause 45 mode */ -+static inline void __cvmx_mdio_set_clause45_mode(int bus_id) -+{ -+ union cvmx_smix_clk smi_clk; -+ /* Put bus into clause 45 mode */ -+ smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); -+ smi_clk.s.mode = 1; -+ smi_clk.s.preamble = 1; -+ cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); -+} -+ -+/* Helper function to put MDIO interface into clause 22 mode */ -+static inline void __cvmx_mdio_set_clause22_mode(int bus_id) -+{ -+ union cvmx_smix_clk smi_clk; -+ /* Put bus into clause 22 mode */ -+ smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id)); -+ smi_clk.s.mode = 0; -+ cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64); -+} -+ -+/** -+ * Perform an MII read. This function is used to read PHY -+ * registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @location: Register location to read -+ * -+ * Returns Result from the read or -1 on failure -+ */ -+static inline int cvmx_mdio_read(int bus_id, int phy_id, int location) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_rd_dat smi_rd; -+ int timeout = 1000; -+ -+ if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) -+ __cvmx_mdio_set_clause22_mode(bus_id); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = location; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); -+ } while (smi_rd.s.pending && timeout--); -+ -+ if (smi_rd.s.val) -+ return smi_rd.s.dat; -+ else -+ return -1; -+} -+ -+/** -+ * Perform an MII write. This function is used to write PHY -+ * registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @location: Register location to write -+ * @val: Value to write -+ * -+ * Returns -1 on error -+ * 0 on success -+ */ -+static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_wr_dat smi_wr; -+ int timeout = 1000; -+ -+ if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) -+ __cvmx_mdio_set_clause22_mode(bus_id); -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = val; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = location; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ return 0; -+} -+ -+/** -+ * Perform an IEEE 802.3 clause 45 MII read. This function is used to -+ * read PHY registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @device: MDIO Managable Device (MMD) id -+ * @location: Register location to read -+ * -+ * Returns Result from the read or -1 on failure -+ */ -+ -+static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device, -+ int location) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_rd_dat smi_rd; -+ union cvmx_smix_wr_dat smi_wr; -+ int timeout = 1000; -+ -+ if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) -+ return -1; -+ -+ __cvmx_mdio_set_clause45_mode(bus_id); -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = location; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) { -+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " -+ "device %2d register %2d TIME OUT(address)\n", -+ bus_id, phy_id, device, location); -+ return -1; -+ } -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id)); -+ } while (smi_rd.s.pending && timeout--); -+ -+ if (timeout <= 0) { -+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " -+ "device %2d register %2d TIME OUT(data)\n", -+ bus_id, phy_id, device, location); -+ return -1; -+ } -+ -+ if (smi_rd.s.val) -+ return smi_rd.s.dat; -+ else { -+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d " -+ "device %2d register %2d INVALID READ\n", -+ bus_id, phy_id, device, location); -+ return -1; -+ } -+} -+ -+/** -+ * Perform an IEEE 802.3 clause 45 MII write. This function is used to -+ * write PHY registers controlling auto negotiation. -+ * -+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX) -+ * support multiple busses. -+ * @phy_id: The MII phy id -+ * @device: MDIO Managable Device (MMD) id -+ * @location: Register location to write -+ * @val: Value to write -+ * -+ * Returns -1 on error -+ * 0 on success -+ */ -+static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device, -+ int location, int val) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_wr_dat smi_wr; -+ int timeout = 1000; -+ -+ if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45)) -+ return -1; -+ -+ __cvmx_mdio_set_clause45_mode(bus_id); -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = location; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = val; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = device; -+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64); -+ -+ do { -+ cvmx_wait(1000); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id)); -+ } while (smi_wr.s.pending && --timeout); -+ if (timeout <= 0) -+ return -1; -+ -+ return 0; -+} -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-packet.h -@@ -0,0 +1,65 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Packet buffer defines. -+ */ -+ -+#ifndef __CVMX_PACKET_H__ -+#define __CVMX_PACKET_H__ -+ -+/** -+ * This structure defines a buffer pointer on Octeon -+ */ -+union cvmx_buf_ptr { -+ void *ptr; -+ uint64_t u64; -+ struct { -+ /* -+ * if set, invert the "free" pick of the overall -+ * packet. HW always sets this bit to 0 on inbound -+ * packet -+ */ -+ uint64_t i:1; -+ /* -+ * Indicates the amount to back up to get to the -+ * buffer start in cache lines. In most cases this is -+ * less than one complete cache line, so the value is -+ * zero. -+ */ -+ uint64_t back:4; -+ /* The pool that the buffer came from / goes to */ -+ uint64_t pool:3; -+ /* The size of the segment pointed to by addr (in bytes) */ -+ uint64_t size:16; -+ /* Pointer to the first byte of the data, NOT buffer */ -+ uint64_t addr:40; -+ } s; -+}; -+ -+#endif /* __CVMX_PACKET_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pcsx-defs.h -@@ -0,0 +1,370 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PCSX_DEFS_H__ -+#define __CVMX_PCSX_DEFS_H__ -+ -+#define CVMX_PCSX_ANX_ADV_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001010ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_ANX_EXT_ST_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001028ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_ANX_LP_ABIL_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001018ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_ANX_RESULTS_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001020ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_INTX_EN_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001088ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_INTX_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001080ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_LINKX_TIMER_COUNT_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001040ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_LOG_ANLX_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001090ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_MISCX_CTL_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001078ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_MRX_CONTROL_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001000ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_MRX_STATUS_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001008ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_RXX_STATES_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001058ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_RXX_SYNC_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001050ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_SGMX_AN_ADV_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001068ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_SGMX_LP_ADV_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001070ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_TXX_STATES_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001060ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSX_TX_RXX_POLARITY_REG(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0001048ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_pcsx_anx_adv_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_anx_adv_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t np:1; -+ uint64_t reserved_14_14:1; -+ uint64_t rem_flt:2; -+ uint64_t reserved_9_11:3; -+ uint64_t pause:2; -+ uint64_t hfd:1; -+ uint64_t fd:1; -+ uint64_t reserved_0_4:5; -+ } s; -+ struct cvmx_pcsx_anx_adv_reg_s cn52xx; -+ struct cvmx_pcsx_anx_adv_reg_s cn52xxp1; -+ struct cvmx_pcsx_anx_adv_reg_s cn56xx; -+ struct cvmx_pcsx_anx_adv_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_anx_ext_st_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_anx_ext_st_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t thou_xfd:1; -+ uint64_t thou_xhd:1; -+ uint64_t thou_tfd:1; -+ uint64_t thou_thd:1; -+ uint64_t reserved_0_11:12; -+ } s; -+ struct cvmx_pcsx_anx_ext_st_reg_s cn52xx; -+ struct cvmx_pcsx_anx_ext_st_reg_s cn52xxp1; -+ struct cvmx_pcsx_anx_ext_st_reg_s cn56xx; -+ struct cvmx_pcsx_anx_ext_st_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_anx_lp_abil_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_anx_lp_abil_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t np:1; -+ uint64_t ack:1; -+ uint64_t rem_flt:2; -+ uint64_t reserved_9_11:3; -+ uint64_t pause:2; -+ uint64_t hfd:1; -+ uint64_t fd:1; -+ uint64_t reserved_0_4:5; -+ } s; -+ struct cvmx_pcsx_anx_lp_abil_reg_s cn52xx; -+ struct cvmx_pcsx_anx_lp_abil_reg_s cn52xxp1; -+ struct cvmx_pcsx_anx_lp_abil_reg_s cn56xx; -+ struct cvmx_pcsx_anx_lp_abil_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_anx_results_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_anx_results_reg_s { -+ uint64_t reserved_7_63:57; -+ uint64_t pause:2; -+ uint64_t spd:2; -+ uint64_t an_cpt:1; -+ uint64_t dup:1; -+ uint64_t link_ok:1; -+ } s; -+ struct cvmx_pcsx_anx_results_reg_s cn52xx; -+ struct cvmx_pcsx_anx_results_reg_s cn52xxp1; -+ struct cvmx_pcsx_anx_results_reg_s cn56xx; -+ struct cvmx_pcsx_anx_results_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_intx_en_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_intx_en_reg_s { -+ uint64_t reserved_12_63:52; -+ uint64_t dup:1; -+ uint64_t sync_bad_en:1; -+ uint64_t an_bad_en:1; -+ uint64_t rxlock_en:1; -+ uint64_t rxbad_en:1; -+ uint64_t rxerr_en:1; -+ uint64_t txbad_en:1; -+ uint64_t txfifo_en:1; -+ uint64_t txfifu_en:1; -+ uint64_t an_err_en:1; -+ uint64_t xmit_en:1; -+ uint64_t lnkspd_en:1; -+ } s; -+ struct cvmx_pcsx_intx_en_reg_s cn52xx; -+ struct cvmx_pcsx_intx_en_reg_s cn52xxp1; -+ struct cvmx_pcsx_intx_en_reg_s cn56xx; -+ struct cvmx_pcsx_intx_en_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_intx_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_intx_reg_s { -+ uint64_t reserved_12_63:52; -+ uint64_t dup:1; -+ uint64_t sync_bad:1; -+ uint64_t an_bad:1; -+ uint64_t rxlock:1; -+ uint64_t rxbad:1; -+ uint64_t rxerr:1; -+ uint64_t txbad:1; -+ uint64_t txfifo:1; -+ uint64_t txfifu:1; -+ uint64_t an_err:1; -+ uint64_t xmit:1; -+ uint64_t lnkspd:1; -+ } s; -+ struct cvmx_pcsx_intx_reg_s cn52xx; -+ struct cvmx_pcsx_intx_reg_s cn52xxp1; -+ struct cvmx_pcsx_intx_reg_s cn56xx; -+ struct cvmx_pcsx_intx_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_linkx_timer_count_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_linkx_timer_count_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t count:16; -+ } s; -+ struct cvmx_pcsx_linkx_timer_count_reg_s cn52xx; -+ struct cvmx_pcsx_linkx_timer_count_reg_s cn52xxp1; -+ struct cvmx_pcsx_linkx_timer_count_reg_s cn56xx; -+ struct cvmx_pcsx_linkx_timer_count_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_log_anlx_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_log_anlx_reg_s { -+ uint64_t reserved_4_63:60; -+ uint64_t lafifovfl:1; -+ uint64_t la_en:1; -+ uint64_t pkt_sz:2; -+ } s; -+ struct cvmx_pcsx_log_anlx_reg_s cn52xx; -+ struct cvmx_pcsx_log_anlx_reg_s cn52xxp1; -+ struct cvmx_pcsx_log_anlx_reg_s cn56xx; -+ struct cvmx_pcsx_log_anlx_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_miscx_ctl_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_miscx_ctl_reg_s { -+ uint64_t reserved_13_63:51; -+ uint64_t sgmii:1; -+ uint64_t gmxeno:1; -+ uint64_t loopbck2:1; -+ uint64_t mac_phy:1; -+ uint64_t mode:1; -+ uint64_t an_ovrd:1; -+ uint64_t samp_pt:7; -+ } s; -+ struct cvmx_pcsx_miscx_ctl_reg_s cn52xx; -+ struct cvmx_pcsx_miscx_ctl_reg_s cn52xxp1; -+ struct cvmx_pcsx_miscx_ctl_reg_s cn56xx; -+ struct cvmx_pcsx_miscx_ctl_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_mrx_control_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_mrx_control_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t reset:1; -+ uint64_t loopbck1:1; -+ uint64_t spdlsb:1; -+ uint64_t an_en:1; -+ uint64_t pwr_dn:1; -+ uint64_t reserved_10_10:1; -+ uint64_t rst_an:1; -+ uint64_t dup:1; -+ uint64_t coltst:1; -+ uint64_t spdmsb:1; -+ uint64_t uni:1; -+ uint64_t reserved_0_4:5; -+ } s; -+ struct cvmx_pcsx_mrx_control_reg_s cn52xx; -+ struct cvmx_pcsx_mrx_control_reg_s cn52xxp1; -+ struct cvmx_pcsx_mrx_control_reg_s cn56xx; -+ struct cvmx_pcsx_mrx_control_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_mrx_status_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_mrx_status_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t hun_t4:1; -+ uint64_t hun_xfd:1; -+ uint64_t hun_xhd:1; -+ uint64_t ten_fd:1; -+ uint64_t ten_hd:1; -+ uint64_t hun_t2fd:1; -+ uint64_t hun_t2hd:1; -+ uint64_t ext_st:1; -+ uint64_t reserved_7_7:1; -+ uint64_t prb_sup:1; -+ uint64_t an_cpt:1; -+ uint64_t rm_flt:1; -+ uint64_t an_abil:1; -+ uint64_t lnk_st:1; -+ uint64_t reserved_1_1:1; -+ uint64_t extnd:1; -+ } s; -+ struct cvmx_pcsx_mrx_status_reg_s cn52xx; -+ struct cvmx_pcsx_mrx_status_reg_s cn52xxp1; -+ struct cvmx_pcsx_mrx_status_reg_s cn56xx; -+ struct cvmx_pcsx_mrx_status_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_rxx_states_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_rxx_states_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t rx_bad:1; -+ uint64_t rx_st:5; -+ uint64_t sync_bad:1; -+ uint64_t sync:4; -+ uint64_t an_bad:1; -+ uint64_t an_st:4; -+ } s; -+ struct cvmx_pcsx_rxx_states_reg_s cn52xx; -+ struct cvmx_pcsx_rxx_states_reg_s cn52xxp1; -+ struct cvmx_pcsx_rxx_states_reg_s cn56xx; -+ struct cvmx_pcsx_rxx_states_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_rxx_sync_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_rxx_sync_reg_s { -+ uint64_t reserved_2_63:62; -+ uint64_t sync:1; -+ uint64_t bit_lock:1; -+ } s; -+ struct cvmx_pcsx_rxx_sync_reg_s cn52xx; -+ struct cvmx_pcsx_rxx_sync_reg_s cn52xxp1; -+ struct cvmx_pcsx_rxx_sync_reg_s cn56xx; -+ struct cvmx_pcsx_rxx_sync_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_sgmx_an_adv_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_sgmx_an_adv_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t link:1; -+ uint64_t ack:1; -+ uint64_t reserved_13_13:1; -+ uint64_t dup:1; -+ uint64_t speed:2; -+ uint64_t reserved_1_9:9; -+ uint64_t one:1; -+ } s; -+ struct cvmx_pcsx_sgmx_an_adv_reg_s cn52xx; -+ struct cvmx_pcsx_sgmx_an_adv_reg_s cn52xxp1; -+ struct cvmx_pcsx_sgmx_an_adv_reg_s cn56xx; -+ struct cvmx_pcsx_sgmx_an_adv_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_sgmx_lp_adv_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_sgmx_lp_adv_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t link:1; -+ uint64_t reserved_13_14:2; -+ uint64_t dup:1; -+ uint64_t speed:2; -+ uint64_t reserved_1_9:9; -+ uint64_t one:1; -+ } s; -+ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn52xx; -+ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn52xxp1; -+ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn56xx; -+ struct cvmx_pcsx_sgmx_lp_adv_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_txx_states_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_txx_states_reg_s { -+ uint64_t reserved_7_63:57; -+ uint64_t xmit:2; -+ uint64_t tx_bad:1; -+ uint64_t ord_st:4; -+ } s; -+ struct cvmx_pcsx_txx_states_reg_s cn52xx; -+ struct cvmx_pcsx_txx_states_reg_s cn52xxp1; -+ struct cvmx_pcsx_txx_states_reg_s cn56xx; -+ struct cvmx_pcsx_txx_states_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsx_tx_rxx_polarity_reg { -+ uint64_t u64; -+ struct cvmx_pcsx_tx_rxx_polarity_reg_s { -+ uint64_t reserved_4_63:60; -+ uint64_t rxovrd:1; -+ uint64_t autorxpl:1; -+ uint64_t rxplrt:1; -+ uint64_t txplrt:1; -+ } s; -+ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn52xx; -+ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn52xxp1; -+ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn56xx; -+ struct cvmx_pcsx_tx_rxx_polarity_reg_s cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pcsxx-defs.h -@@ -0,0 +1,316 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PCSXX_DEFS_H__ -+#define __CVMX_PCSXX_DEFS_H__ -+ -+#define CVMX_PCSXX_10GBX_STATUS_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000828ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_BIST_STATUS_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000870ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_BIT_LOCK_STATUS_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000850ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_CONTROL1_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000800ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_CONTROL2_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000818ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_INT_EN_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000860ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_INT_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000858ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_LOG_ANL_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000868ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_MISC_CTL_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000848ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_RX_SYNC_STATES_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000838ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_SPD_ABIL_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000810ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_STATUS1_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000808ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_STATUS2_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000820ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_TX_RX_POLARITY_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000840ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_PCSXX_TX_RX_STATES_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800B0000830ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_pcsxx_10gbx_status_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_10gbx_status_reg_s { -+ uint64_t reserved_13_63:51; -+ uint64_t alignd:1; -+ uint64_t pattst:1; -+ uint64_t reserved_4_10:7; -+ uint64_t l3sync:1; -+ uint64_t l2sync:1; -+ uint64_t l1sync:1; -+ uint64_t l0sync:1; -+ } s; -+ struct cvmx_pcsxx_10gbx_status_reg_s cn52xx; -+ struct cvmx_pcsxx_10gbx_status_reg_s cn52xxp1; -+ struct cvmx_pcsxx_10gbx_status_reg_s cn56xx; -+ struct cvmx_pcsxx_10gbx_status_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_bist_status_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_bist_status_reg_s { -+ uint64_t reserved_1_63:63; -+ uint64_t bist_status:1; -+ } s; -+ struct cvmx_pcsxx_bist_status_reg_s cn52xx; -+ struct cvmx_pcsxx_bist_status_reg_s cn52xxp1; -+ struct cvmx_pcsxx_bist_status_reg_s cn56xx; -+ struct cvmx_pcsxx_bist_status_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_bit_lock_status_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_bit_lock_status_reg_s { -+ uint64_t reserved_4_63:60; -+ uint64_t bitlck3:1; -+ uint64_t bitlck2:1; -+ uint64_t bitlck1:1; -+ uint64_t bitlck0:1; -+ } s; -+ struct cvmx_pcsxx_bit_lock_status_reg_s cn52xx; -+ struct cvmx_pcsxx_bit_lock_status_reg_s cn52xxp1; -+ struct cvmx_pcsxx_bit_lock_status_reg_s cn56xx; -+ struct cvmx_pcsxx_bit_lock_status_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_control1_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_control1_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t reset:1; -+ uint64_t loopbck1:1; -+ uint64_t spdsel1:1; -+ uint64_t reserved_12_12:1; -+ uint64_t lo_pwr:1; -+ uint64_t reserved_7_10:4; -+ uint64_t spdsel0:1; -+ uint64_t spd:4; -+ uint64_t reserved_0_1:2; -+ } s; -+ struct cvmx_pcsxx_control1_reg_s cn52xx; -+ struct cvmx_pcsxx_control1_reg_s cn52xxp1; -+ struct cvmx_pcsxx_control1_reg_s cn56xx; -+ struct cvmx_pcsxx_control1_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_control2_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_control2_reg_s { -+ uint64_t reserved_2_63:62; -+ uint64_t type:2; -+ } s; -+ struct cvmx_pcsxx_control2_reg_s cn52xx; -+ struct cvmx_pcsxx_control2_reg_s cn52xxp1; -+ struct cvmx_pcsxx_control2_reg_s cn56xx; -+ struct cvmx_pcsxx_control2_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_int_en_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_int_en_reg_s { -+ uint64_t reserved_6_63:58; -+ uint64_t algnlos_en:1; -+ uint64_t synlos_en:1; -+ uint64_t bitlckls_en:1; -+ uint64_t rxsynbad_en:1; -+ uint64_t rxbad_en:1; -+ uint64_t txflt_en:1; -+ } s; -+ struct cvmx_pcsxx_int_en_reg_s cn52xx; -+ struct cvmx_pcsxx_int_en_reg_s cn52xxp1; -+ struct cvmx_pcsxx_int_en_reg_s cn56xx; -+ struct cvmx_pcsxx_int_en_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_int_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_int_reg_s { -+ uint64_t reserved_6_63:58; -+ uint64_t algnlos:1; -+ uint64_t synlos:1; -+ uint64_t bitlckls:1; -+ uint64_t rxsynbad:1; -+ uint64_t rxbad:1; -+ uint64_t txflt:1; -+ } s; -+ struct cvmx_pcsxx_int_reg_s cn52xx; -+ struct cvmx_pcsxx_int_reg_s cn52xxp1; -+ struct cvmx_pcsxx_int_reg_s cn56xx; -+ struct cvmx_pcsxx_int_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_log_anl_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_log_anl_reg_s { -+ uint64_t reserved_7_63:57; -+ uint64_t enc_mode:1; -+ uint64_t drop_ln:2; -+ uint64_t lafifovfl:1; -+ uint64_t la_en:1; -+ uint64_t pkt_sz:2; -+ } s; -+ struct cvmx_pcsxx_log_anl_reg_s cn52xx; -+ struct cvmx_pcsxx_log_anl_reg_s cn52xxp1; -+ struct cvmx_pcsxx_log_anl_reg_s cn56xx; -+ struct cvmx_pcsxx_log_anl_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_misc_ctl_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_misc_ctl_reg_s { -+ uint64_t reserved_4_63:60; -+ uint64_t tx_swap:1; -+ uint64_t rx_swap:1; -+ uint64_t xaui:1; -+ uint64_t gmxeno:1; -+ } s; -+ struct cvmx_pcsxx_misc_ctl_reg_s cn52xx; -+ struct cvmx_pcsxx_misc_ctl_reg_s cn52xxp1; -+ struct cvmx_pcsxx_misc_ctl_reg_s cn56xx; -+ struct cvmx_pcsxx_misc_ctl_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_rx_sync_states_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_rx_sync_states_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t sync3st:4; -+ uint64_t sync2st:4; -+ uint64_t sync1st:4; -+ uint64_t sync0st:4; -+ } s; -+ struct cvmx_pcsxx_rx_sync_states_reg_s cn52xx; -+ struct cvmx_pcsxx_rx_sync_states_reg_s cn52xxp1; -+ struct cvmx_pcsxx_rx_sync_states_reg_s cn56xx; -+ struct cvmx_pcsxx_rx_sync_states_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_spd_abil_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_spd_abil_reg_s { -+ uint64_t reserved_2_63:62; -+ uint64_t tenpasst:1; -+ uint64_t tengb:1; -+ } s; -+ struct cvmx_pcsxx_spd_abil_reg_s cn52xx; -+ struct cvmx_pcsxx_spd_abil_reg_s cn52xxp1; -+ struct cvmx_pcsxx_spd_abil_reg_s cn56xx; -+ struct cvmx_pcsxx_spd_abil_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_status1_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_status1_reg_s { -+ uint64_t reserved_8_63:56; -+ uint64_t flt:1; -+ uint64_t reserved_3_6:4; -+ uint64_t rcv_lnk:1; -+ uint64_t lpable:1; -+ uint64_t reserved_0_0:1; -+ } s; -+ struct cvmx_pcsxx_status1_reg_s cn52xx; -+ struct cvmx_pcsxx_status1_reg_s cn52xxp1; -+ struct cvmx_pcsxx_status1_reg_s cn56xx; -+ struct cvmx_pcsxx_status1_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_status2_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_status2_reg_s { -+ uint64_t reserved_16_63:48; -+ uint64_t dev:2; -+ uint64_t reserved_12_13:2; -+ uint64_t xmtflt:1; -+ uint64_t rcvflt:1; -+ uint64_t reserved_3_9:7; -+ uint64_t tengb_w:1; -+ uint64_t tengb_x:1; -+ uint64_t tengb_r:1; -+ } s; -+ struct cvmx_pcsxx_status2_reg_s cn52xx; -+ struct cvmx_pcsxx_status2_reg_s cn52xxp1; -+ struct cvmx_pcsxx_status2_reg_s cn56xx; -+ struct cvmx_pcsxx_status2_reg_s cn56xxp1; -+}; -+ -+union cvmx_pcsxx_tx_rx_polarity_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_tx_rx_polarity_reg_s { -+ uint64_t reserved_10_63:54; -+ uint64_t xor_rxplrt:4; -+ uint64_t xor_txplrt:4; -+ uint64_t rxplrt:1; -+ uint64_t txplrt:1; -+ } s; -+ struct cvmx_pcsxx_tx_rx_polarity_reg_s cn52xx; -+ struct cvmx_pcsxx_tx_rx_polarity_reg_cn52xxp1 { -+ uint64_t reserved_2_63:62; -+ uint64_t rxplrt:1; -+ uint64_t txplrt:1; -+ } cn52xxp1; -+ struct cvmx_pcsxx_tx_rx_polarity_reg_s cn56xx; -+ struct cvmx_pcsxx_tx_rx_polarity_reg_cn52xxp1 cn56xxp1; -+}; -+ -+union cvmx_pcsxx_tx_rx_states_reg { -+ uint64_t u64; -+ struct cvmx_pcsxx_tx_rx_states_reg_s { -+ uint64_t reserved_14_63:50; -+ uint64_t term_err:1; -+ uint64_t syn3bad:1; -+ uint64_t syn2bad:1; -+ uint64_t syn1bad:1; -+ uint64_t syn0bad:1; -+ uint64_t rxbad:1; -+ uint64_t algn_st:3; -+ uint64_t rx_st:2; -+ uint64_t tx_st:3; -+ } s; -+ struct cvmx_pcsxx_tx_rx_states_reg_s cn52xx; -+ struct cvmx_pcsxx_tx_rx_states_reg_cn52xxp1 { -+ uint64_t reserved_13_63:51; -+ uint64_t syn3bad:1; -+ uint64_t syn2bad:1; -+ uint64_t syn1bad:1; -+ uint64_t syn0bad:1; -+ uint64_t rxbad:1; -+ uint64_t algn_st:3; -+ uint64_t rx_st:2; -+ uint64_t tx_st:3; -+ } cn52xxp1; -+ struct cvmx_pcsxx_tx_rx_states_reg_s cn56xx; -+ struct cvmx_pcsxx_tx_rx_states_reg_cn52xxp1 cn56xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pip-defs.h -@@ -0,0 +1,1267 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PIP_DEFS_H__ -+#define __CVMX_PIP_DEFS_H__ -+ -+/* -+ * Enumeration representing the amount of packet processing -+ * and validation performed by the input hardware. -+ */ -+enum cvmx_pip_port_parse_mode { -+ /* -+ * Packet input doesn't perform any processing of the input -+ * packet. -+ */ -+ CVMX_PIP_PORT_CFG_MODE_NONE = 0ull, -+ /* -+ * Full packet processing is performed with pointer starting -+ * at the L2 (ethernet MAC) header. -+ */ -+ CVMX_PIP_PORT_CFG_MODE_SKIPL2 = 1ull, -+ /* -+ * Input packets are assumed to be IP. Results from non IP -+ * packets is undefined. Pointers reference the beginning of -+ * the IP header. -+ */ -+ CVMX_PIP_PORT_CFG_MODE_SKIPIP = 2ull -+}; -+ -+#define CVMX_PIP_BCK_PRS \ -+ CVMX_ADD_IO_SEG(0x00011800A0000038ull) -+#define CVMX_PIP_BIST_STATUS \ -+ CVMX_ADD_IO_SEG(0x00011800A0000000ull) -+#define CVMX_PIP_CRC_CTLX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000040ull + (((offset) & 1) * 8)) -+#define CVMX_PIP_CRC_IVX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000050ull + (((offset) & 1) * 8)) -+#define CVMX_PIP_DEC_IPSECX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000080ull + (((offset) & 3) * 8)) -+#define CVMX_PIP_DSA_SRC_GRP \ -+ CVMX_ADD_IO_SEG(0x00011800A0000190ull) -+#define CVMX_PIP_DSA_VID_GRP \ -+ CVMX_ADD_IO_SEG(0x00011800A0000198ull) -+#define CVMX_PIP_FRM_LEN_CHKX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000180ull + (((offset) & 1) * 8)) -+#define CVMX_PIP_GBL_CFG \ -+ CVMX_ADD_IO_SEG(0x00011800A0000028ull) -+#define CVMX_PIP_GBL_CTL \ -+ CVMX_ADD_IO_SEG(0x00011800A0000020ull) -+#define CVMX_PIP_HG_PRI_QOS \ -+ CVMX_ADD_IO_SEG(0x00011800A00001A0ull) -+#define CVMX_PIP_INT_EN \ -+ CVMX_ADD_IO_SEG(0x00011800A0000010ull) -+#define CVMX_PIP_INT_REG \ -+ CVMX_ADD_IO_SEG(0x00011800A0000008ull) -+#define CVMX_PIP_IP_OFFSET \ -+ CVMX_ADD_IO_SEG(0x00011800A0000060ull) -+#define CVMX_PIP_PRT_CFGX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000200ull + (((offset) & 63) * 8)) -+#define CVMX_PIP_PRT_TAGX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000400ull + (((offset) & 63) * 8)) -+#define CVMX_PIP_QOS_DIFFX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000600ull + (((offset) & 63) * 8)) -+#define CVMX_PIP_QOS_VLANX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A00000C0ull + (((offset) & 7) * 8)) -+#define CVMX_PIP_QOS_WATCHX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000100ull + (((offset) & 7) * 8)) -+#define CVMX_PIP_RAW_WORD \ -+ CVMX_ADD_IO_SEG(0x00011800A00000B0ull) -+#define CVMX_PIP_SFT_RST \ -+ CVMX_ADD_IO_SEG(0x00011800A0000030ull) -+#define CVMX_PIP_STAT0_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000800ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT1_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000808ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT2_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000810ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT3_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000818ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT4_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000820ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT5_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000828ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT6_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000830ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT7_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000838ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT8_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000840ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT9_PRTX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0000848ull + (((offset) & 63) * 80)) -+#define CVMX_PIP_STAT_CTL \ -+ CVMX_ADD_IO_SEG(0x00011800A0000018ull) -+#define CVMX_PIP_STAT_INB_ERRSX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0001A10ull + (((offset) & 63) * 32)) -+#define CVMX_PIP_STAT_INB_OCTSX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0001A08ull + (((offset) & 63) * 32)) -+#define CVMX_PIP_STAT_INB_PKTSX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0001A00ull + (((offset) & 63) * 32)) -+#define CVMX_PIP_TAG_INCX(offset) \ -+ CVMX_ADD_IO_SEG(0x00011800A0001800ull + (((offset) & 63) * 8)) -+#define CVMX_PIP_TAG_MASK \ -+ CVMX_ADD_IO_SEG(0x00011800A0000070ull) -+#define CVMX_PIP_TAG_SECRET \ -+ CVMX_ADD_IO_SEG(0x00011800A0000068ull) -+#define CVMX_PIP_TODO_ENTRY \ -+ CVMX_ADD_IO_SEG(0x00011800A0000078ull) -+ -+union cvmx_pip_bck_prs { -+ uint64_t u64; -+ struct cvmx_pip_bck_prs_s { -+ uint64_t bckprs:1; -+ uint64_t reserved_13_62:50; -+ uint64_t hiwater:5; -+ uint64_t reserved_5_7:3; -+ uint64_t lowater:5; -+ } s; -+ struct cvmx_pip_bck_prs_s cn38xx; -+ struct cvmx_pip_bck_prs_s cn38xxp2; -+ struct cvmx_pip_bck_prs_s cn56xx; -+ struct cvmx_pip_bck_prs_s cn56xxp1; -+ struct cvmx_pip_bck_prs_s cn58xx; -+ struct cvmx_pip_bck_prs_s cn58xxp1; -+}; -+ -+union cvmx_pip_bist_status { -+ uint64_t u64; -+ struct cvmx_pip_bist_status_s { -+ uint64_t reserved_18_63:46; -+ uint64_t bist:18; -+ } s; -+ struct cvmx_pip_bist_status_s cn30xx; -+ struct cvmx_pip_bist_status_s cn31xx; -+ struct cvmx_pip_bist_status_s cn38xx; -+ struct cvmx_pip_bist_status_s cn38xxp2; -+ struct cvmx_pip_bist_status_cn50xx { -+ uint64_t reserved_17_63:47; -+ uint64_t bist:17; -+ } cn50xx; -+ struct cvmx_pip_bist_status_s cn52xx; -+ struct cvmx_pip_bist_status_s cn52xxp1; -+ struct cvmx_pip_bist_status_s cn56xx; -+ struct cvmx_pip_bist_status_s cn56xxp1; -+ struct cvmx_pip_bist_status_s cn58xx; -+ struct cvmx_pip_bist_status_s cn58xxp1; -+}; -+ -+union cvmx_pip_crc_ctlx { -+ uint64_t u64; -+ struct cvmx_pip_crc_ctlx_s { -+ uint64_t reserved_2_63:62; -+ uint64_t invres:1; -+ uint64_t reflect:1; -+ } s; -+ struct cvmx_pip_crc_ctlx_s cn38xx; -+ struct cvmx_pip_crc_ctlx_s cn38xxp2; -+ struct cvmx_pip_crc_ctlx_s cn58xx; -+ struct cvmx_pip_crc_ctlx_s cn58xxp1; -+}; -+ -+union cvmx_pip_crc_ivx { -+ uint64_t u64; -+ struct cvmx_pip_crc_ivx_s { -+ uint64_t reserved_32_63:32; -+ uint64_t iv:32; -+ } s; -+ struct cvmx_pip_crc_ivx_s cn38xx; -+ struct cvmx_pip_crc_ivx_s cn38xxp2; -+ struct cvmx_pip_crc_ivx_s cn58xx; -+ struct cvmx_pip_crc_ivx_s cn58xxp1; -+}; -+ -+union cvmx_pip_dec_ipsecx { -+ uint64_t u64; -+ struct cvmx_pip_dec_ipsecx_s { -+ uint64_t reserved_18_63:46; -+ uint64_t tcp:1; -+ uint64_t udp:1; -+ uint64_t dprt:16; -+ } s; -+ struct cvmx_pip_dec_ipsecx_s cn30xx; -+ struct cvmx_pip_dec_ipsecx_s cn31xx; -+ struct cvmx_pip_dec_ipsecx_s cn38xx; -+ struct cvmx_pip_dec_ipsecx_s cn38xxp2; -+ struct cvmx_pip_dec_ipsecx_s cn50xx; -+ struct cvmx_pip_dec_ipsecx_s cn52xx; -+ struct cvmx_pip_dec_ipsecx_s cn52xxp1; -+ struct cvmx_pip_dec_ipsecx_s cn56xx; -+ struct cvmx_pip_dec_ipsecx_s cn56xxp1; -+ struct cvmx_pip_dec_ipsecx_s cn58xx; -+ struct cvmx_pip_dec_ipsecx_s cn58xxp1; -+}; -+ -+union cvmx_pip_dsa_src_grp { -+ uint64_t u64; -+ struct cvmx_pip_dsa_src_grp_s { -+ uint64_t map15:4; -+ uint64_t map14:4; -+ uint64_t map13:4; -+ uint64_t map12:4; -+ uint64_t map11:4; -+ uint64_t map10:4; -+ uint64_t map9:4; -+ uint64_t map8:4; -+ uint64_t map7:4; -+ uint64_t map6:4; -+ uint64_t map5:4; -+ uint64_t map4:4; -+ uint64_t map3:4; -+ uint64_t map2:4; -+ uint64_t map1:4; -+ uint64_t map0:4; -+ } s; -+ struct cvmx_pip_dsa_src_grp_s cn52xx; -+ struct cvmx_pip_dsa_src_grp_s cn52xxp1; -+ struct cvmx_pip_dsa_src_grp_s cn56xx; -+}; -+ -+union cvmx_pip_dsa_vid_grp { -+ uint64_t u64; -+ struct cvmx_pip_dsa_vid_grp_s { -+ uint64_t map15:4; -+ uint64_t map14:4; -+ uint64_t map13:4; -+ uint64_t map12:4; -+ uint64_t map11:4; -+ uint64_t map10:4; -+ uint64_t map9:4; -+ uint64_t map8:4; -+ uint64_t map7:4; -+ uint64_t map6:4; -+ uint64_t map5:4; -+ uint64_t map4:4; -+ uint64_t map3:4; -+ uint64_t map2:4; -+ uint64_t map1:4; -+ uint64_t map0:4; -+ } s; -+ struct cvmx_pip_dsa_vid_grp_s cn52xx; -+ struct cvmx_pip_dsa_vid_grp_s cn52xxp1; -+ struct cvmx_pip_dsa_vid_grp_s cn56xx; -+}; -+ -+union cvmx_pip_frm_len_chkx { -+ uint64_t u64; -+ struct cvmx_pip_frm_len_chkx_s { -+ uint64_t reserved_32_63:32; -+ uint64_t maxlen:16; -+ uint64_t minlen:16; -+ } s; -+ struct cvmx_pip_frm_len_chkx_s cn50xx; -+ struct cvmx_pip_frm_len_chkx_s cn52xx; -+ struct cvmx_pip_frm_len_chkx_s cn52xxp1; -+ struct cvmx_pip_frm_len_chkx_s cn56xx; -+ struct cvmx_pip_frm_len_chkx_s cn56xxp1; -+}; -+ -+union cvmx_pip_gbl_cfg { -+ uint64_t u64; -+ struct cvmx_pip_gbl_cfg_s { -+ uint64_t reserved_19_63:45; -+ uint64_t tag_syn:1; -+ uint64_t ip6_udp:1; -+ uint64_t max_l2:1; -+ uint64_t reserved_11_15:5; -+ uint64_t raw_shf:3; -+ uint64_t reserved_3_7:5; -+ uint64_t nip_shf:3; -+ } s; -+ struct cvmx_pip_gbl_cfg_s cn30xx; -+ struct cvmx_pip_gbl_cfg_s cn31xx; -+ struct cvmx_pip_gbl_cfg_s cn38xx; -+ struct cvmx_pip_gbl_cfg_s cn38xxp2; -+ struct cvmx_pip_gbl_cfg_s cn50xx; -+ struct cvmx_pip_gbl_cfg_s cn52xx; -+ struct cvmx_pip_gbl_cfg_s cn52xxp1; -+ struct cvmx_pip_gbl_cfg_s cn56xx; -+ struct cvmx_pip_gbl_cfg_s cn56xxp1; -+ struct cvmx_pip_gbl_cfg_s cn58xx; -+ struct cvmx_pip_gbl_cfg_s cn58xxp1; -+}; -+ -+union cvmx_pip_gbl_ctl { -+ uint64_t u64; -+ struct cvmx_pip_gbl_ctl_s { -+ uint64_t reserved_27_63:37; -+ uint64_t dsa_grp_tvid:1; -+ uint64_t dsa_grp_scmd:1; -+ uint64_t dsa_grp_sid:1; -+ uint64_t reserved_21_23:3; -+ uint64_t ring_en:1; -+ uint64_t reserved_17_19:3; -+ uint64_t ignrs:1; -+ uint64_t vs_wqe:1; -+ uint64_t vs_qos:1; -+ uint64_t l2_mal:1; -+ uint64_t tcp_flag:1; -+ uint64_t l4_len:1; -+ uint64_t l4_chk:1; -+ uint64_t l4_prt:1; -+ uint64_t l4_mal:1; -+ uint64_t reserved_6_7:2; -+ uint64_t ip6_eext:2; -+ uint64_t ip4_opts:1; -+ uint64_t ip_hop:1; -+ uint64_t ip_mal:1; -+ uint64_t ip_chk:1; -+ } s; -+ struct cvmx_pip_gbl_ctl_cn30xx { -+ uint64_t reserved_17_63:47; -+ uint64_t ignrs:1; -+ uint64_t vs_wqe:1; -+ uint64_t vs_qos:1; -+ uint64_t l2_mal:1; -+ uint64_t tcp_flag:1; -+ uint64_t l4_len:1; -+ uint64_t l4_chk:1; -+ uint64_t l4_prt:1; -+ uint64_t l4_mal:1; -+ uint64_t reserved_6_7:2; -+ uint64_t ip6_eext:2; -+ uint64_t ip4_opts:1; -+ uint64_t ip_hop:1; -+ uint64_t ip_mal:1; -+ uint64_t ip_chk:1; -+ } cn30xx; -+ struct cvmx_pip_gbl_ctl_cn30xx cn31xx; -+ struct cvmx_pip_gbl_ctl_cn30xx cn38xx; -+ struct cvmx_pip_gbl_ctl_cn30xx cn38xxp2; -+ struct cvmx_pip_gbl_ctl_cn30xx cn50xx; -+ struct cvmx_pip_gbl_ctl_s cn52xx; -+ struct cvmx_pip_gbl_ctl_s cn52xxp1; -+ struct cvmx_pip_gbl_ctl_s cn56xx; -+ struct cvmx_pip_gbl_ctl_cn56xxp1 { -+ uint64_t reserved_21_63:43; -+ uint64_t ring_en:1; -+ uint64_t reserved_17_19:3; -+ uint64_t ignrs:1; -+ uint64_t vs_wqe:1; -+ uint64_t vs_qos:1; -+ uint64_t l2_mal:1; -+ uint64_t tcp_flag:1; -+ uint64_t l4_len:1; -+ uint64_t l4_chk:1; -+ uint64_t l4_prt:1; -+ uint64_t l4_mal:1; -+ uint64_t reserved_6_7:2; -+ uint64_t ip6_eext:2; -+ uint64_t ip4_opts:1; -+ uint64_t ip_hop:1; -+ uint64_t ip_mal:1; -+ uint64_t ip_chk:1; -+ } cn56xxp1; -+ struct cvmx_pip_gbl_ctl_cn30xx cn58xx; -+ struct cvmx_pip_gbl_ctl_cn30xx cn58xxp1; -+}; -+ -+union cvmx_pip_hg_pri_qos { -+ uint64_t u64; -+ struct cvmx_pip_hg_pri_qos_s { -+ uint64_t reserved_11_63:53; -+ uint64_t qos:3; -+ uint64_t reserved_6_7:2; -+ uint64_t pri:6; -+ } s; -+ struct cvmx_pip_hg_pri_qos_s cn52xx; -+ struct cvmx_pip_hg_pri_qos_s cn52xxp1; -+ struct cvmx_pip_hg_pri_qos_s cn56xx; -+}; -+ -+union cvmx_pip_int_en { -+ uint64_t u64; -+ struct cvmx_pip_int_en_s { -+ uint64_t reserved_13_63:51; -+ uint64_t punyerr:1; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } s; -+ struct cvmx_pip_int_en_cn30xx { -+ uint64_t reserved_9_63:55; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } cn30xx; -+ struct cvmx_pip_int_en_cn30xx cn31xx; -+ struct cvmx_pip_int_en_cn30xx cn38xx; -+ struct cvmx_pip_int_en_cn30xx cn38xxp2; -+ struct cvmx_pip_int_en_cn50xx { -+ uint64_t reserved_12_63:52; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t reserved_1_1:1; -+ uint64_t pktdrp:1; -+ } cn50xx; -+ struct cvmx_pip_int_en_cn52xx { -+ uint64_t reserved_13_63:51; -+ uint64_t punyerr:1; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t reserved_1_1:1; -+ uint64_t pktdrp:1; -+ } cn52xx; -+ struct cvmx_pip_int_en_cn52xx cn52xxp1; -+ struct cvmx_pip_int_en_s cn56xx; -+ struct cvmx_pip_int_en_cn56xxp1 { -+ uint64_t reserved_12_63:52; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } cn56xxp1; -+ struct cvmx_pip_int_en_cn58xx { -+ uint64_t reserved_13_63:51; -+ uint64_t punyerr:1; -+ uint64_t reserved_9_11:3; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } cn58xx; -+ struct cvmx_pip_int_en_cn30xx cn58xxp1; -+}; -+ -+union cvmx_pip_int_reg { -+ uint64_t u64; -+ struct cvmx_pip_int_reg_s { -+ uint64_t reserved_13_63:51; -+ uint64_t punyerr:1; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } s; -+ struct cvmx_pip_int_reg_cn30xx { -+ uint64_t reserved_9_63:55; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } cn30xx; -+ struct cvmx_pip_int_reg_cn30xx cn31xx; -+ struct cvmx_pip_int_reg_cn30xx cn38xx; -+ struct cvmx_pip_int_reg_cn30xx cn38xxp2; -+ struct cvmx_pip_int_reg_cn50xx { -+ uint64_t reserved_12_63:52; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t reserved_1_1:1; -+ uint64_t pktdrp:1; -+ } cn50xx; -+ struct cvmx_pip_int_reg_cn52xx { -+ uint64_t reserved_13_63:51; -+ uint64_t punyerr:1; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t reserved_1_1:1; -+ uint64_t pktdrp:1; -+ } cn52xx; -+ struct cvmx_pip_int_reg_cn52xx cn52xxp1; -+ struct cvmx_pip_int_reg_s cn56xx; -+ struct cvmx_pip_int_reg_cn56xxp1 { -+ uint64_t reserved_12_63:52; -+ uint64_t lenerr:1; -+ uint64_t maxerr:1; -+ uint64_t minerr:1; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } cn56xxp1; -+ struct cvmx_pip_int_reg_cn58xx { -+ uint64_t reserved_13_63:51; -+ uint64_t punyerr:1; -+ uint64_t reserved_9_11:3; -+ uint64_t beperr:1; -+ uint64_t feperr:1; -+ uint64_t todoovr:1; -+ uint64_t skprunt:1; -+ uint64_t badtag:1; -+ uint64_t prtnxa:1; -+ uint64_t bckprs:1; -+ uint64_t crcerr:1; -+ uint64_t pktdrp:1; -+ } cn58xx; -+ struct cvmx_pip_int_reg_cn30xx cn58xxp1; -+}; -+ -+union cvmx_pip_ip_offset { -+ uint64_t u64; -+ struct cvmx_pip_ip_offset_s { -+ uint64_t reserved_3_63:61; -+ uint64_t offset:3; -+ } s; -+ struct cvmx_pip_ip_offset_s cn30xx; -+ struct cvmx_pip_ip_offset_s cn31xx; -+ struct cvmx_pip_ip_offset_s cn38xx; -+ struct cvmx_pip_ip_offset_s cn38xxp2; -+ struct cvmx_pip_ip_offset_s cn50xx; -+ struct cvmx_pip_ip_offset_s cn52xx; -+ struct cvmx_pip_ip_offset_s cn52xxp1; -+ struct cvmx_pip_ip_offset_s cn56xx; -+ struct cvmx_pip_ip_offset_s cn56xxp1; -+ struct cvmx_pip_ip_offset_s cn58xx; -+ struct cvmx_pip_ip_offset_s cn58xxp1; -+}; -+ -+union cvmx_pip_prt_cfgx { -+ uint64_t u64; -+ struct cvmx_pip_prt_cfgx_s { -+ uint64_t reserved_53_63:11; -+ uint64_t pad_len:1; -+ uint64_t vlan_len:1; -+ uint64_t lenerr_en:1; -+ uint64_t maxerr_en:1; -+ uint64_t minerr_en:1; -+ uint64_t grp_wat_47:4; -+ uint64_t qos_wat_47:4; -+ uint64_t reserved_37_39:3; -+ uint64_t rawdrp:1; -+ uint64_t tag_inc:2; -+ uint64_t dyn_rs:1; -+ uint64_t inst_hdr:1; -+ uint64_t grp_wat:4; -+ uint64_t hg_qos:1; -+ uint64_t qos:3; -+ uint64_t qos_wat:4; -+ uint64_t qos_vsel:1; -+ uint64_t qos_vod:1; -+ uint64_t qos_diff:1; -+ uint64_t qos_vlan:1; -+ uint64_t reserved_13_15:3; -+ uint64_t crc_en:1; -+ uint64_t higig_en:1; -+ uint64_t dsa_en:1; -+ uint64_t mode:2; -+ uint64_t reserved_7_7:1; -+ uint64_t skip:7; -+ } s; -+ struct cvmx_pip_prt_cfgx_cn30xx { -+ uint64_t reserved_37_63:27; -+ uint64_t rawdrp:1; -+ uint64_t tag_inc:2; -+ uint64_t dyn_rs:1; -+ uint64_t inst_hdr:1; -+ uint64_t grp_wat:4; -+ uint64_t reserved_27_27:1; -+ uint64_t qos:3; -+ uint64_t qos_wat:4; -+ uint64_t reserved_18_19:2; -+ uint64_t qos_diff:1; -+ uint64_t qos_vlan:1; -+ uint64_t reserved_10_15:6; -+ uint64_t mode:2; -+ uint64_t reserved_7_7:1; -+ uint64_t skip:7; -+ } cn30xx; -+ struct cvmx_pip_prt_cfgx_cn30xx cn31xx; -+ struct cvmx_pip_prt_cfgx_cn38xx { -+ uint64_t reserved_37_63:27; -+ uint64_t rawdrp:1; -+ uint64_t tag_inc:2; -+ uint64_t dyn_rs:1; -+ uint64_t inst_hdr:1; -+ uint64_t grp_wat:4; -+ uint64_t reserved_27_27:1; -+ uint64_t qos:3; -+ uint64_t qos_wat:4; -+ uint64_t reserved_18_19:2; -+ uint64_t qos_diff:1; -+ uint64_t qos_vlan:1; -+ uint64_t reserved_13_15:3; -+ uint64_t crc_en:1; -+ uint64_t reserved_10_11:2; -+ uint64_t mode:2; -+ uint64_t reserved_7_7:1; -+ uint64_t skip:7; -+ } cn38xx; -+ struct cvmx_pip_prt_cfgx_cn38xx cn38xxp2; -+ struct cvmx_pip_prt_cfgx_cn50xx { -+ uint64_t reserved_53_63:11; -+ uint64_t pad_len:1; -+ uint64_t vlan_len:1; -+ uint64_t lenerr_en:1; -+ uint64_t maxerr_en:1; -+ uint64_t minerr_en:1; -+ uint64_t grp_wat_47:4; -+ uint64_t qos_wat_47:4; -+ uint64_t reserved_37_39:3; -+ uint64_t rawdrp:1; -+ uint64_t tag_inc:2; -+ uint64_t dyn_rs:1; -+ uint64_t inst_hdr:1; -+ uint64_t grp_wat:4; -+ uint64_t reserved_27_27:1; -+ uint64_t qos:3; -+ uint64_t qos_wat:4; -+ uint64_t reserved_19_19:1; -+ uint64_t qos_vod:1; -+ uint64_t qos_diff:1; -+ uint64_t qos_vlan:1; -+ uint64_t reserved_13_15:3; -+ uint64_t crc_en:1; -+ uint64_t reserved_10_11:2; -+ uint64_t mode:2; -+ uint64_t reserved_7_7:1; -+ uint64_t skip:7; -+ } cn50xx; -+ struct cvmx_pip_prt_cfgx_s cn52xx; -+ struct cvmx_pip_prt_cfgx_s cn52xxp1; -+ struct cvmx_pip_prt_cfgx_s cn56xx; -+ struct cvmx_pip_prt_cfgx_cn50xx cn56xxp1; -+ struct cvmx_pip_prt_cfgx_cn58xx { -+ uint64_t reserved_37_63:27; -+ uint64_t rawdrp:1; -+ uint64_t tag_inc:2; -+ uint64_t dyn_rs:1; -+ uint64_t inst_hdr:1; -+ uint64_t grp_wat:4; -+ uint64_t reserved_27_27:1; -+ uint64_t qos:3; -+ uint64_t qos_wat:4; -+ uint64_t reserved_19_19:1; -+ uint64_t qos_vod:1; -+ uint64_t qos_diff:1; -+ uint64_t qos_vlan:1; -+ uint64_t reserved_13_15:3; -+ uint64_t crc_en:1; -+ uint64_t reserved_10_11:2; -+ uint64_t mode:2; -+ uint64_t reserved_7_7:1; -+ uint64_t skip:7; -+ } cn58xx; -+ struct cvmx_pip_prt_cfgx_cn58xx cn58xxp1; -+}; -+ -+union cvmx_pip_prt_tagx { -+ uint64_t u64; -+ struct cvmx_pip_prt_tagx_s { -+ uint64_t reserved_40_63:24; -+ uint64_t grptagbase:4; -+ uint64_t grptagmask:4; -+ uint64_t grptag:1; -+ uint64_t grptag_mskip:1; -+ uint64_t tag_mode:2; -+ uint64_t inc_vs:2; -+ uint64_t inc_vlan:1; -+ uint64_t inc_prt_flag:1; -+ uint64_t ip6_dprt_flag:1; -+ uint64_t ip4_dprt_flag:1; -+ uint64_t ip6_sprt_flag:1; -+ uint64_t ip4_sprt_flag:1; -+ uint64_t ip6_nxth_flag:1; -+ uint64_t ip4_pctl_flag:1; -+ uint64_t ip6_dst_flag:1; -+ uint64_t ip4_dst_flag:1; -+ uint64_t ip6_src_flag:1; -+ uint64_t ip4_src_flag:1; -+ uint64_t tcp6_tag_type:2; -+ uint64_t tcp4_tag_type:2; -+ uint64_t ip6_tag_type:2; -+ uint64_t ip4_tag_type:2; -+ uint64_t non_tag_type:2; -+ uint64_t grp:4; -+ } s; -+ struct cvmx_pip_prt_tagx_cn30xx { -+ uint64_t reserved_40_63:24; -+ uint64_t grptagbase:4; -+ uint64_t grptagmask:4; -+ uint64_t grptag:1; -+ uint64_t reserved_30_30:1; -+ uint64_t tag_mode:2; -+ uint64_t inc_vs:2; -+ uint64_t inc_vlan:1; -+ uint64_t inc_prt_flag:1; -+ uint64_t ip6_dprt_flag:1; -+ uint64_t ip4_dprt_flag:1; -+ uint64_t ip6_sprt_flag:1; -+ uint64_t ip4_sprt_flag:1; -+ uint64_t ip6_nxth_flag:1; -+ uint64_t ip4_pctl_flag:1; -+ uint64_t ip6_dst_flag:1; -+ uint64_t ip4_dst_flag:1; -+ uint64_t ip6_src_flag:1; -+ uint64_t ip4_src_flag:1; -+ uint64_t tcp6_tag_type:2; -+ uint64_t tcp4_tag_type:2; -+ uint64_t ip6_tag_type:2; -+ uint64_t ip4_tag_type:2; -+ uint64_t non_tag_type:2; -+ uint64_t grp:4; -+ } cn30xx; -+ struct cvmx_pip_prt_tagx_cn30xx cn31xx; -+ struct cvmx_pip_prt_tagx_cn30xx cn38xx; -+ struct cvmx_pip_prt_tagx_cn30xx cn38xxp2; -+ struct cvmx_pip_prt_tagx_s cn50xx; -+ struct cvmx_pip_prt_tagx_s cn52xx; -+ struct cvmx_pip_prt_tagx_s cn52xxp1; -+ struct cvmx_pip_prt_tagx_s cn56xx; -+ struct cvmx_pip_prt_tagx_s cn56xxp1; -+ struct cvmx_pip_prt_tagx_cn30xx cn58xx; -+ struct cvmx_pip_prt_tagx_cn30xx cn58xxp1; -+}; -+ -+union cvmx_pip_qos_diffx { -+ uint64_t u64; -+ struct cvmx_pip_qos_diffx_s { -+ uint64_t reserved_3_63:61; -+ uint64_t qos:3; -+ } s; -+ struct cvmx_pip_qos_diffx_s cn30xx; -+ struct cvmx_pip_qos_diffx_s cn31xx; -+ struct cvmx_pip_qos_diffx_s cn38xx; -+ struct cvmx_pip_qos_diffx_s cn38xxp2; -+ struct cvmx_pip_qos_diffx_s cn50xx; -+ struct cvmx_pip_qos_diffx_s cn52xx; -+ struct cvmx_pip_qos_diffx_s cn52xxp1; -+ struct cvmx_pip_qos_diffx_s cn56xx; -+ struct cvmx_pip_qos_diffx_s cn56xxp1; -+ struct cvmx_pip_qos_diffx_s cn58xx; -+ struct cvmx_pip_qos_diffx_s cn58xxp1; -+}; -+ -+union cvmx_pip_qos_vlanx { -+ uint64_t u64; -+ struct cvmx_pip_qos_vlanx_s { -+ uint64_t reserved_7_63:57; -+ uint64_t qos1:3; -+ uint64_t reserved_3_3:1; -+ uint64_t qos:3; -+ } s; -+ struct cvmx_pip_qos_vlanx_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t qos:3; -+ } cn30xx; -+ struct cvmx_pip_qos_vlanx_cn30xx cn31xx; -+ struct cvmx_pip_qos_vlanx_cn30xx cn38xx; -+ struct cvmx_pip_qos_vlanx_cn30xx cn38xxp2; -+ struct cvmx_pip_qos_vlanx_cn30xx cn50xx; -+ struct cvmx_pip_qos_vlanx_s cn52xx; -+ struct cvmx_pip_qos_vlanx_s cn52xxp1; -+ struct cvmx_pip_qos_vlanx_s cn56xx; -+ struct cvmx_pip_qos_vlanx_cn30xx cn56xxp1; -+ struct cvmx_pip_qos_vlanx_cn30xx cn58xx; -+ struct cvmx_pip_qos_vlanx_cn30xx cn58xxp1; -+}; -+ -+union cvmx_pip_qos_watchx { -+ uint64_t u64; -+ struct cvmx_pip_qos_watchx_s { -+ uint64_t reserved_48_63:16; -+ uint64_t mask:16; -+ uint64_t reserved_28_31:4; -+ uint64_t grp:4; -+ uint64_t reserved_23_23:1; -+ uint64_t qos:3; -+ uint64_t reserved_19_19:1; -+ uint64_t match_type:3; -+ uint64_t match_value:16; -+ } s; -+ struct cvmx_pip_qos_watchx_cn30xx { -+ uint64_t reserved_48_63:16; -+ uint64_t mask:16; -+ uint64_t reserved_28_31:4; -+ uint64_t grp:4; -+ uint64_t reserved_23_23:1; -+ uint64_t qos:3; -+ uint64_t reserved_18_19:2; -+ uint64_t match_type:2; -+ uint64_t match_value:16; -+ } cn30xx; -+ struct cvmx_pip_qos_watchx_cn30xx cn31xx; -+ struct cvmx_pip_qos_watchx_cn30xx cn38xx; -+ struct cvmx_pip_qos_watchx_cn30xx cn38xxp2; -+ struct cvmx_pip_qos_watchx_s cn50xx; -+ struct cvmx_pip_qos_watchx_s cn52xx; -+ struct cvmx_pip_qos_watchx_s cn52xxp1; -+ struct cvmx_pip_qos_watchx_s cn56xx; -+ struct cvmx_pip_qos_watchx_s cn56xxp1; -+ struct cvmx_pip_qos_watchx_cn30xx cn58xx; -+ struct cvmx_pip_qos_watchx_cn30xx cn58xxp1; -+}; -+ -+union cvmx_pip_raw_word { -+ uint64_t u64; -+ struct cvmx_pip_raw_word_s { -+ uint64_t reserved_56_63:8; -+ uint64_t word:56; -+ } s; -+ struct cvmx_pip_raw_word_s cn30xx; -+ struct cvmx_pip_raw_word_s cn31xx; -+ struct cvmx_pip_raw_word_s cn38xx; -+ struct cvmx_pip_raw_word_s cn38xxp2; -+ struct cvmx_pip_raw_word_s cn50xx; -+ struct cvmx_pip_raw_word_s cn52xx; -+ struct cvmx_pip_raw_word_s cn52xxp1; -+ struct cvmx_pip_raw_word_s cn56xx; -+ struct cvmx_pip_raw_word_s cn56xxp1; -+ struct cvmx_pip_raw_word_s cn58xx; -+ struct cvmx_pip_raw_word_s cn58xxp1; -+}; -+ -+union cvmx_pip_sft_rst { -+ uint64_t u64; -+ struct cvmx_pip_sft_rst_s { -+ uint64_t reserved_1_63:63; -+ uint64_t rst:1; -+ } s; -+ struct cvmx_pip_sft_rst_s cn30xx; -+ struct cvmx_pip_sft_rst_s cn31xx; -+ struct cvmx_pip_sft_rst_s cn38xx; -+ struct cvmx_pip_sft_rst_s cn50xx; -+ struct cvmx_pip_sft_rst_s cn52xx; -+ struct cvmx_pip_sft_rst_s cn52xxp1; -+ struct cvmx_pip_sft_rst_s cn56xx; -+ struct cvmx_pip_sft_rst_s cn56xxp1; -+ struct cvmx_pip_sft_rst_s cn58xx; -+ struct cvmx_pip_sft_rst_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat0_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat0_prtx_s { -+ uint64_t drp_pkts:32; -+ uint64_t drp_octs:32; -+ } s; -+ struct cvmx_pip_stat0_prtx_s cn30xx; -+ struct cvmx_pip_stat0_prtx_s cn31xx; -+ struct cvmx_pip_stat0_prtx_s cn38xx; -+ struct cvmx_pip_stat0_prtx_s cn38xxp2; -+ struct cvmx_pip_stat0_prtx_s cn50xx; -+ struct cvmx_pip_stat0_prtx_s cn52xx; -+ struct cvmx_pip_stat0_prtx_s cn52xxp1; -+ struct cvmx_pip_stat0_prtx_s cn56xx; -+ struct cvmx_pip_stat0_prtx_s cn56xxp1; -+ struct cvmx_pip_stat0_prtx_s cn58xx; -+ struct cvmx_pip_stat0_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat1_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat1_prtx_s { -+ uint64_t reserved_48_63:16; -+ uint64_t octs:48; -+ } s; -+ struct cvmx_pip_stat1_prtx_s cn30xx; -+ struct cvmx_pip_stat1_prtx_s cn31xx; -+ struct cvmx_pip_stat1_prtx_s cn38xx; -+ struct cvmx_pip_stat1_prtx_s cn38xxp2; -+ struct cvmx_pip_stat1_prtx_s cn50xx; -+ struct cvmx_pip_stat1_prtx_s cn52xx; -+ struct cvmx_pip_stat1_prtx_s cn52xxp1; -+ struct cvmx_pip_stat1_prtx_s cn56xx; -+ struct cvmx_pip_stat1_prtx_s cn56xxp1; -+ struct cvmx_pip_stat1_prtx_s cn58xx; -+ struct cvmx_pip_stat1_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat2_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat2_prtx_s { -+ uint64_t pkts:32; -+ uint64_t raw:32; -+ } s; -+ struct cvmx_pip_stat2_prtx_s cn30xx; -+ struct cvmx_pip_stat2_prtx_s cn31xx; -+ struct cvmx_pip_stat2_prtx_s cn38xx; -+ struct cvmx_pip_stat2_prtx_s cn38xxp2; -+ struct cvmx_pip_stat2_prtx_s cn50xx; -+ struct cvmx_pip_stat2_prtx_s cn52xx; -+ struct cvmx_pip_stat2_prtx_s cn52xxp1; -+ struct cvmx_pip_stat2_prtx_s cn56xx; -+ struct cvmx_pip_stat2_prtx_s cn56xxp1; -+ struct cvmx_pip_stat2_prtx_s cn58xx; -+ struct cvmx_pip_stat2_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat3_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat3_prtx_s { -+ uint64_t bcst:32; -+ uint64_t mcst:32; -+ } s; -+ struct cvmx_pip_stat3_prtx_s cn30xx; -+ struct cvmx_pip_stat3_prtx_s cn31xx; -+ struct cvmx_pip_stat3_prtx_s cn38xx; -+ struct cvmx_pip_stat3_prtx_s cn38xxp2; -+ struct cvmx_pip_stat3_prtx_s cn50xx; -+ struct cvmx_pip_stat3_prtx_s cn52xx; -+ struct cvmx_pip_stat3_prtx_s cn52xxp1; -+ struct cvmx_pip_stat3_prtx_s cn56xx; -+ struct cvmx_pip_stat3_prtx_s cn56xxp1; -+ struct cvmx_pip_stat3_prtx_s cn58xx; -+ struct cvmx_pip_stat3_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat4_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat4_prtx_s { -+ uint64_t h65to127:32; -+ uint64_t h64:32; -+ } s; -+ struct cvmx_pip_stat4_prtx_s cn30xx; -+ struct cvmx_pip_stat4_prtx_s cn31xx; -+ struct cvmx_pip_stat4_prtx_s cn38xx; -+ struct cvmx_pip_stat4_prtx_s cn38xxp2; -+ struct cvmx_pip_stat4_prtx_s cn50xx; -+ struct cvmx_pip_stat4_prtx_s cn52xx; -+ struct cvmx_pip_stat4_prtx_s cn52xxp1; -+ struct cvmx_pip_stat4_prtx_s cn56xx; -+ struct cvmx_pip_stat4_prtx_s cn56xxp1; -+ struct cvmx_pip_stat4_prtx_s cn58xx; -+ struct cvmx_pip_stat4_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat5_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat5_prtx_s { -+ uint64_t h256to511:32; -+ uint64_t h128to255:32; -+ } s; -+ struct cvmx_pip_stat5_prtx_s cn30xx; -+ struct cvmx_pip_stat5_prtx_s cn31xx; -+ struct cvmx_pip_stat5_prtx_s cn38xx; -+ struct cvmx_pip_stat5_prtx_s cn38xxp2; -+ struct cvmx_pip_stat5_prtx_s cn50xx; -+ struct cvmx_pip_stat5_prtx_s cn52xx; -+ struct cvmx_pip_stat5_prtx_s cn52xxp1; -+ struct cvmx_pip_stat5_prtx_s cn56xx; -+ struct cvmx_pip_stat5_prtx_s cn56xxp1; -+ struct cvmx_pip_stat5_prtx_s cn58xx; -+ struct cvmx_pip_stat5_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat6_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat6_prtx_s { -+ uint64_t h1024to1518:32; -+ uint64_t h512to1023:32; -+ } s; -+ struct cvmx_pip_stat6_prtx_s cn30xx; -+ struct cvmx_pip_stat6_prtx_s cn31xx; -+ struct cvmx_pip_stat6_prtx_s cn38xx; -+ struct cvmx_pip_stat6_prtx_s cn38xxp2; -+ struct cvmx_pip_stat6_prtx_s cn50xx; -+ struct cvmx_pip_stat6_prtx_s cn52xx; -+ struct cvmx_pip_stat6_prtx_s cn52xxp1; -+ struct cvmx_pip_stat6_prtx_s cn56xx; -+ struct cvmx_pip_stat6_prtx_s cn56xxp1; -+ struct cvmx_pip_stat6_prtx_s cn58xx; -+ struct cvmx_pip_stat6_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat7_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat7_prtx_s { -+ uint64_t fcs:32; -+ uint64_t h1519:32; -+ } s; -+ struct cvmx_pip_stat7_prtx_s cn30xx; -+ struct cvmx_pip_stat7_prtx_s cn31xx; -+ struct cvmx_pip_stat7_prtx_s cn38xx; -+ struct cvmx_pip_stat7_prtx_s cn38xxp2; -+ struct cvmx_pip_stat7_prtx_s cn50xx; -+ struct cvmx_pip_stat7_prtx_s cn52xx; -+ struct cvmx_pip_stat7_prtx_s cn52xxp1; -+ struct cvmx_pip_stat7_prtx_s cn56xx; -+ struct cvmx_pip_stat7_prtx_s cn56xxp1; -+ struct cvmx_pip_stat7_prtx_s cn58xx; -+ struct cvmx_pip_stat7_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat8_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat8_prtx_s { -+ uint64_t frag:32; -+ uint64_t undersz:32; -+ } s; -+ struct cvmx_pip_stat8_prtx_s cn30xx; -+ struct cvmx_pip_stat8_prtx_s cn31xx; -+ struct cvmx_pip_stat8_prtx_s cn38xx; -+ struct cvmx_pip_stat8_prtx_s cn38xxp2; -+ struct cvmx_pip_stat8_prtx_s cn50xx; -+ struct cvmx_pip_stat8_prtx_s cn52xx; -+ struct cvmx_pip_stat8_prtx_s cn52xxp1; -+ struct cvmx_pip_stat8_prtx_s cn56xx; -+ struct cvmx_pip_stat8_prtx_s cn56xxp1; -+ struct cvmx_pip_stat8_prtx_s cn58xx; -+ struct cvmx_pip_stat8_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat9_prtx { -+ uint64_t u64; -+ struct cvmx_pip_stat9_prtx_s { -+ uint64_t jabber:32; -+ uint64_t oversz:32; -+ } s; -+ struct cvmx_pip_stat9_prtx_s cn30xx; -+ struct cvmx_pip_stat9_prtx_s cn31xx; -+ struct cvmx_pip_stat9_prtx_s cn38xx; -+ struct cvmx_pip_stat9_prtx_s cn38xxp2; -+ struct cvmx_pip_stat9_prtx_s cn50xx; -+ struct cvmx_pip_stat9_prtx_s cn52xx; -+ struct cvmx_pip_stat9_prtx_s cn52xxp1; -+ struct cvmx_pip_stat9_prtx_s cn56xx; -+ struct cvmx_pip_stat9_prtx_s cn56xxp1; -+ struct cvmx_pip_stat9_prtx_s cn58xx; -+ struct cvmx_pip_stat9_prtx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat_ctl { -+ uint64_t u64; -+ struct cvmx_pip_stat_ctl_s { -+ uint64_t reserved_1_63:63; -+ uint64_t rdclr:1; -+ } s; -+ struct cvmx_pip_stat_ctl_s cn30xx; -+ struct cvmx_pip_stat_ctl_s cn31xx; -+ struct cvmx_pip_stat_ctl_s cn38xx; -+ struct cvmx_pip_stat_ctl_s cn38xxp2; -+ struct cvmx_pip_stat_ctl_s cn50xx; -+ struct cvmx_pip_stat_ctl_s cn52xx; -+ struct cvmx_pip_stat_ctl_s cn52xxp1; -+ struct cvmx_pip_stat_ctl_s cn56xx; -+ struct cvmx_pip_stat_ctl_s cn56xxp1; -+ struct cvmx_pip_stat_ctl_s cn58xx; -+ struct cvmx_pip_stat_ctl_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat_inb_errsx { -+ uint64_t u64; -+ struct cvmx_pip_stat_inb_errsx_s { -+ uint64_t reserved_16_63:48; -+ uint64_t errs:16; -+ } s; -+ struct cvmx_pip_stat_inb_errsx_s cn30xx; -+ struct cvmx_pip_stat_inb_errsx_s cn31xx; -+ struct cvmx_pip_stat_inb_errsx_s cn38xx; -+ struct cvmx_pip_stat_inb_errsx_s cn38xxp2; -+ struct cvmx_pip_stat_inb_errsx_s cn50xx; -+ struct cvmx_pip_stat_inb_errsx_s cn52xx; -+ struct cvmx_pip_stat_inb_errsx_s cn52xxp1; -+ struct cvmx_pip_stat_inb_errsx_s cn56xx; -+ struct cvmx_pip_stat_inb_errsx_s cn56xxp1; -+ struct cvmx_pip_stat_inb_errsx_s cn58xx; -+ struct cvmx_pip_stat_inb_errsx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat_inb_octsx { -+ uint64_t u64; -+ struct cvmx_pip_stat_inb_octsx_s { -+ uint64_t reserved_48_63:16; -+ uint64_t octs:48; -+ } s; -+ struct cvmx_pip_stat_inb_octsx_s cn30xx; -+ struct cvmx_pip_stat_inb_octsx_s cn31xx; -+ struct cvmx_pip_stat_inb_octsx_s cn38xx; -+ struct cvmx_pip_stat_inb_octsx_s cn38xxp2; -+ struct cvmx_pip_stat_inb_octsx_s cn50xx; -+ struct cvmx_pip_stat_inb_octsx_s cn52xx; -+ struct cvmx_pip_stat_inb_octsx_s cn52xxp1; -+ struct cvmx_pip_stat_inb_octsx_s cn56xx; -+ struct cvmx_pip_stat_inb_octsx_s cn56xxp1; -+ struct cvmx_pip_stat_inb_octsx_s cn58xx; -+ struct cvmx_pip_stat_inb_octsx_s cn58xxp1; -+}; -+ -+union cvmx_pip_stat_inb_pktsx { -+ uint64_t u64; -+ struct cvmx_pip_stat_inb_pktsx_s { -+ uint64_t reserved_32_63:32; -+ uint64_t pkts:32; -+ } s; -+ struct cvmx_pip_stat_inb_pktsx_s cn30xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn31xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn38xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn38xxp2; -+ struct cvmx_pip_stat_inb_pktsx_s cn50xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn52xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn52xxp1; -+ struct cvmx_pip_stat_inb_pktsx_s cn56xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn56xxp1; -+ struct cvmx_pip_stat_inb_pktsx_s cn58xx; -+ struct cvmx_pip_stat_inb_pktsx_s cn58xxp1; -+}; -+ -+union cvmx_pip_tag_incx { -+ uint64_t u64; -+ struct cvmx_pip_tag_incx_s { -+ uint64_t reserved_8_63:56; -+ uint64_t en:8; -+ } s; -+ struct cvmx_pip_tag_incx_s cn30xx; -+ struct cvmx_pip_tag_incx_s cn31xx; -+ struct cvmx_pip_tag_incx_s cn38xx; -+ struct cvmx_pip_tag_incx_s cn38xxp2; -+ struct cvmx_pip_tag_incx_s cn50xx; -+ struct cvmx_pip_tag_incx_s cn52xx; -+ struct cvmx_pip_tag_incx_s cn52xxp1; -+ struct cvmx_pip_tag_incx_s cn56xx; -+ struct cvmx_pip_tag_incx_s cn56xxp1; -+ struct cvmx_pip_tag_incx_s cn58xx; -+ struct cvmx_pip_tag_incx_s cn58xxp1; -+}; -+ -+union cvmx_pip_tag_mask { -+ uint64_t u64; -+ struct cvmx_pip_tag_mask_s { -+ uint64_t reserved_16_63:48; -+ uint64_t mask:16; -+ } s; -+ struct cvmx_pip_tag_mask_s cn30xx; -+ struct cvmx_pip_tag_mask_s cn31xx; -+ struct cvmx_pip_tag_mask_s cn38xx; -+ struct cvmx_pip_tag_mask_s cn38xxp2; -+ struct cvmx_pip_tag_mask_s cn50xx; -+ struct cvmx_pip_tag_mask_s cn52xx; -+ struct cvmx_pip_tag_mask_s cn52xxp1; -+ struct cvmx_pip_tag_mask_s cn56xx; -+ struct cvmx_pip_tag_mask_s cn56xxp1; -+ struct cvmx_pip_tag_mask_s cn58xx; -+ struct cvmx_pip_tag_mask_s cn58xxp1; -+}; -+ -+union cvmx_pip_tag_secret { -+ uint64_t u64; -+ struct cvmx_pip_tag_secret_s { -+ uint64_t reserved_32_63:32; -+ uint64_t dst:16; -+ uint64_t src:16; -+ } s; -+ struct cvmx_pip_tag_secret_s cn30xx; -+ struct cvmx_pip_tag_secret_s cn31xx; -+ struct cvmx_pip_tag_secret_s cn38xx; -+ struct cvmx_pip_tag_secret_s cn38xxp2; -+ struct cvmx_pip_tag_secret_s cn50xx; -+ struct cvmx_pip_tag_secret_s cn52xx; -+ struct cvmx_pip_tag_secret_s cn52xxp1; -+ struct cvmx_pip_tag_secret_s cn56xx; -+ struct cvmx_pip_tag_secret_s cn56xxp1; -+ struct cvmx_pip_tag_secret_s cn58xx; -+ struct cvmx_pip_tag_secret_s cn58xxp1; -+}; -+ -+union cvmx_pip_todo_entry { -+ uint64_t u64; -+ struct cvmx_pip_todo_entry_s { -+ uint64_t val:1; -+ uint64_t reserved_62_62:1; -+ uint64_t entry:62; -+ } s; -+ struct cvmx_pip_todo_entry_s cn30xx; -+ struct cvmx_pip_todo_entry_s cn31xx; -+ struct cvmx_pip_todo_entry_s cn38xx; -+ struct cvmx_pip_todo_entry_s cn38xxp2; -+ struct cvmx_pip_todo_entry_s cn50xx; -+ struct cvmx_pip_todo_entry_s cn52xx; -+ struct cvmx_pip_todo_entry_s cn52xxp1; -+ struct cvmx_pip_todo_entry_s cn56xx; -+ struct cvmx_pip_todo_entry_s cn56xxp1; -+ struct cvmx_pip_todo_entry_s cn58xx; -+ struct cvmx_pip_todo_entry_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pip.h -@@ -0,0 +1,524 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Interface to the hardware Packet Input Processing unit. -+ * -+ */ -+ -+#ifndef __CVMX_PIP_H__ -+#define __CVMX_PIP_H__ -+ -+#include "cvmx-wqe.h" -+#include "cvmx-fpa.h" -+#include "cvmx-pip-defs.h" -+ -+#define CVMX_PIP_NUM_INPUT_PORTS 40 -+#define CVMX_PIP_NUM_WATCHERS 4 -+ -+/* -+ * Encodes the different error and exception codes -+ */ -+typedef enum { -+ CVMX_PIP_L4_NO_ERR = 0ull, -+ /* -+ * 1 = TCP (UDP) packet not long enough to cover TCP (UDP) -+ * header -+ */ -+ CVMX_PIP_L4_MAL_ERR = 1ull, -+ /* 2 = TCP/UDP checksum failure */ -+ CVMX_PIP_CHK_ERR = 2ull, -+ /* -+ * 3 = TCP/UDP length check (TCP/UDP length does not match IP -+ * length). -+ */ -+ CVMX_PIP_L4_LENGTH_ERR = 3ull, -+ /* 4 = illegal TCP/UDP port (either source or dest port is zero) */ -+ CVMX_PIP_BAD_PRT_ERR = 4ull, -+ /* 8 = TCP flags = FIN only */ -+ CVMX_PIP_TCP_FLG8_ERR = 8ull, -+ /* 9 = TCP flags = 0 */ -+ CVMX_PIP_TCP_FLG9_ERR = 9ull, -+ /* 10 = TCP flags = FIN+RST+* */ -+ CVMX_PIP_TCP_FLG10_ERR = 10ull, -+ /* 11 = TCP flags = SYN+URG+* */ -+ CVMX_PIP_TCP_FLG11_ERR = 11ull, -+ /* 12 = TCP flags = SYN+RST+* */ -+ CVMX_PIP_TCP_FLG12_ERR = 12ull, -+ /* 13 = TCP flags = SYN+FIN+* */ -+ CVMX_PIP_TCP_FLG13_ERR = 13ull -+} cvmx_pip_l4_err_t; -+ -+typedef enum { -+ -+ CVMX_PIP_IP_NO_ERR = 0ull, -+ /* 1 = not IPv4 or IPv6 */ -+ CVMX_PIP_NOT_IP = 1ull, -+ /* 2 = IPv4 header checksum violation */ -+ CVMX_PIP_IPV4_HDR_CHK = 2ull, -+ /* 3 = malformed (packet not long enough to cover IP hdr) */ -+ CVMX_PIP_IP_MAL_HDR = 3ull, -+ /* 4 = malformed (packet not long enough to cover len in IP hdr) */ -+ CVMX_PIP_IP_MAL_PKT = 4ull, -+ /* 5 = TTL / hop count equal zero */ -+ CVMX_PIP_TTL_HOP = 5ull, -+ /* 6 = IPv4 options / IPv6 early extension headers */ -+ CVMX_PIP_OPTS = 6ull -+} cvmx_pip_ip_exc_t; -+ -+/** -+ * NOTES -+ * late collision (data received before collision) -+ * late collisions cannot be detected by the receiver -+ * they would appear as JAM bits which would appear as bad FCS -+ * or carrier extend error which is CVMX_PIP_EXTEND_ERR -+ */ -+typedef enum { -+ /* No error */ -+ CVMX_PIP_RX_NO_ERR = 0ull, -+ /* RGM+SPI 1 = partially received packet (buffering/bandwidth -+ * not adequate) */ -+ CVMX_PIP_PARTIAL_ERR = 1ull, -+ /* RGM+SPI 2 = receive packet too large and truncated */ -+ CVMX_PIP_JABBER_ERR = 2ull, -+ /* -+ * RGM 3 = max frame error (pkt len > max frame len) (with FCS -+ * error) -+ */ -+ CVMX_PIP_OVER_FCS_ERR = 3ull, -+ /* RGM+SPI 4 = max frame error (pkt len > max frame len) */ -+ CVMX_PIP_OVER_ERR = 4ull, -+ /* -+ * RGM 5 = nibble error (data not byte multiple - 100M and 10M -+ * only) -+ */ -+ CVMX_PIP_ALIGN_ERR = 5ull, -+ /* -+ * RGM 6 = min frame error (pkt len < min frame len) (with FCS -+ * error) -+ */ -+ CVMX_PIP_UNDER_FCS_ERR = 6ull, -+ /* RGM 7 = FCS error */ -+ CVMX_PIP_GMX_FCS_ERR = 7ull, -+ /* RGM+SPI 8 = min frame error (pkt len < min frame len) */ -+ CVMX_PIP_UNDER_ERR = 8ull, -+ /* RGM 9 = Frame carrier extend error */ -+ CVMX_PIP_EXTEND_ERR = 9ull, -+ /* -+ * RGM 10 = length mismatch (len did not match len in L2 -+ * length/type) -+ */ -+ CVMX_PIP_LENGTH_ERR = 10ull, -+ /* RGM 11 = Frame error (some or all data bits marked err) */ -+ CVMX_PIP_DAT_ERR = 11ull, -+ /* SPI 11 = DIP4 error */ -+ CVMX_PIP_DIP_ERR = 11ull, -+ /* -+ * RGM 12 = packet was not large enough to pass the skipper - -+ * no inspection could occur. -+ */ -+ CVMX_PIP_SKIP_ERR = 12ull, -+ /* -+ * RGM 13 = studder error (data not repeated - 100M and 10M -+ * only) -+ */ -+ CVMX_PIP_NIBBLE_ERR = 13ull, -+ /* RGM+SPI 16 = FCS error */ -+ CVMX_PIP_PIP_FCS = 16L, -+ /* -+ * RGM+SPI+PCI 17 = packet was not large enough to pass the -+ * skipper - no inspection could occur. -+ */ -+ CVMX_PIP_PIP_SKIP_ERR = 17L, -+ /* -+ * RGM+SPI+PCI 18 = malformed l2 (packet not long enough to -+ * cover L2 hdr). -+ */ -+ CVMX_PIP_PIP_L2_MAL_HDR = 18L -+ /* -+ * NOTES: xx = late collision (data received before collision) -+ * late collisions cannot be detected by the receiver -+ * they would appear as JAM bits which would appear as -+ * bad FCS or carrier extend error which is -+ * CVMX_PIP_EXTEND_ERR -+ */ -+} cvmx_pip_rcv_err_t; -+ -+/** -+ * This defines the err_code field errors in the work Q entry -+ */ -+typedef union { -+ cvmx_pip_l4_err_t l4_err; -+ cvmx_pip_ip_exc_t ip_exc; -+ cvmx_pip_rcv_err_t rcv_err; -+} cvmx_pip_err_t; -+ -+/** -+ * Status statistics for a port -+ */ -+typedef struct { -+ /* Inbound octets marked to be dropped by the IPD */ -+ uint32_t dropped_octets; -+ /* Inbound packets marked to be dropped by the IPD */ -+ uint32_t dropped_packets; -+ /* RAW PCI Packets received by PIP per port */ -+ uint32_t pci_raw_packets; -+ /* Number of octets processed by PIP */ -+ uint32_t octets; -+ /* Number of packets processed by PIP */ -+ uint32_t packets; -+ /* -+ * Number of indentified L2 multicast packets. Does not -+ * include broadcast packets. Only includes packets whose -+ * parse mode is SKIP_TO_L2 -+ */ -+ uint32_t multicast_packets; -+ /* -+ * Number of indentified L2 broadcast packets. Does not -+ * include multicast packets. Only includes packets whose -+ * parse mode is SKIP_TO_L2 -+ */ -+ uint32_t broadcast_packets; -+ /* Number of 64B packets */ -+ uint32_t len_64_packets; -+ /* Number of 65-127B packets */ -+ uint32_t len_65_127_packets; -+ /* Number of 128-255B packets */ -+ uint32_t len_128_255_packets; -+ /* Number of 256-511B packets */ -+ uint32_t len_256_511_packets; -+ /* Number of 512-1023B packets */ -+ uint32_t len_512_1023_packets; -+ /* Number of 1024-1518B packets */ -+ uint32_t len_1024_1518_packets; -+ /* Number of 1519-max packets */ -+ uint32_t len_1519_max_packets; -+ /* Number of packets with FCS or Align opcode errors */ -+ uint32_t fcs_align_err_packets; -+ /* Number of packets with length < min */ -+ uint32_t runt_packets; -+ /* Number of packets with length < min and FCS error */ -+ uint32_t runt_crc_packets; -+ /* Number of packets with length > max */ -+ uint32_t oversize_packets; -+ /* Number of packets with length > max and FCS error */ -+ uint32_t oversize_crc_packets; -+ /* Number of packets without GMX/SPX/PCI errors received by PIP */ -+ uint32_t inb_packets; -+ /* -+ * Total number of octets from all packets received by PIP, -+ * including CRC -+ */ -+ uint64_t inb_octets; -+ /* Number of packets with GMX/SPX/PCI errors received by PIP */ -+ uint16_t inb_errors; -+} cvmx_pip_port_status_t; -+ -+/** -+ * Definition of the PIP custom header that can be prepended -+ * to a packet by external hardware. -+ */ -+typedef union { -+ uint64_t u64; -+ struct { -+ /* -+ * Documented as R - Set if the Packet is RAWFULL. If -+ * set, this header must be the full 8 bytes. -+ */ -+ uint64_t rawfull:1; -+ /* Must be zero */ -+ uint64_t reserved0:5; -+ /* PIP parse mode for this packet */ -+ uint64_t parse_mode:2; -+ /* Must be zero */ -+ uint64_t reserved1:1; -+ /* -+ * Skip amount, including this header, to the -+ * beginning of the packet -+ */ -+ uint64_t skip_len:7; -+ /* Must be zero */ -+ uint64_t reserved2:6; -+ /* POW input queue for this packet */ -+ uint64_t qos:3; -+ /* POW input group for this packet */ -+ uint64_t grp:4; -+ /* -+ * Flag to store this packet in the work queue entry, -+ * if possible -+ */ -+ uint64_t rs:1; -+ /* POW input tag type */ -+ uint64_t tag_type:2; -+ /* POW input tag */ -+ uint64_t tag:32; -+ } s; -+} cvmx_pip_pkt_inst_hdr_t; -+ -+/* CSR typedefs have been moved to cvmx-csr-*.h */ -+ -+/** -+ * Configure an ethernet input port -+ * -+ * @port_num: Port number to configure -+ * @port_cfg: Port hardware configuration -+ * @port_tag_cfg: -+ * Port POW tagging configuration -+ */ -+static inline void cvmx_pip_config_port(uint64_t port_num, -+ union cvmx_pip_prt_cfgx port_cfg, -+ union cvmx_pip_prt_tagx port_tag_cfg) -+{ -+ cvmx_write_csr(CVMX_PIP_PRT_CFGX(port_num), port_cfg.u64); -+ cvmx_write_csr(CVMX_PIP_PRT_TAGX(port_num), port_tag_cfg.u64); -+} -+#if 0 -+/** -+ * @deprecated This function is a thin wrapper around the Pass1 version -+ * of the CVMX_PIP_QOS_WATCHX CSR; Pass2 has added a field for -+ * setting the group that is incompatible with this function, -+ * the preferred upgrade path is to use the CSR directly. -+ * -+ * Configure the global QoS packet watchers. Each watcher is -+ * capable of matching a field in a packet to determine the -+ * QoS queue for scheduling. -+ * -+ * @watcher: Watcher number to configure (0 - 3). -+ * @match_type: Watcher match type -+ * @match_value: -+ * Value the watcher will match against -+ * @qos: QoS queue for packets matching this watcher -+ */ -+static inline void cvmx_pip_config_watcher(uint64_t watcher, -+ cvmx_pip_qos_watch_types match_type, -+ uint64_t match_value, uint64_t qos) -+{ -+ cvmx_pip_port_watcher_cfg_t watcher_config; -+ -+ watcher_config.u64 = 0; -+ watcher_config.s.match_type = match_type; -+ watcher_config.s.match_value = match_value; -+ watcher_config.s.qos = qos; -+ -+ cvmx_write_csr(CVMX_PIP_QOS_WATCHX(watcher), watcher_config.u64); -+} -+#endif -+/** -+ * Configure the VLAN priority to QoS queue mapping. -+ * -+ * @vlan_priority: -+ * VLAN priority (0-7) -+ * @qos: QoS queue for packets matching this watcher -+ */ -+static inline void cvmx_pip_config_vlan_qos(uint64_t vlan_priority, -+ uint64_t qos) -+{ -+ union cvmx_pip_qos_vlanx pip_qos_vlanx; -+ pip_qos_vlanx.u64 = 0; -+ pip_qos_vlanx.s.qos = qos; -+ cvmx_write_csr(CVMX_PIP_QOS_VLANX(vlan_priority), pip_qos_vlanx.u64); -+} -+ -+/** -+ * Configure the Diffserv to QoS queue mapping. -+ * -+ * @diffserv: Diffserv field value (0-63) -+ * @qos: QoS queue for packets matching this watcher -+ */ -+static inline void cvmx_pip_config_diffserv_qos(uint64_t diffserv, uint64_t qos) -+{ -+ union cvmx_pip_qos_diffx pip_qos_diffx; -+ pip_qos_diffx.u64 = 0; -+ pip_qos_diffx.s.qos = qos; -+ cvmx_write_csr(CVMX_PIP_QOS_DIFFX(diffserv), pip_qos_diffx.u64); -+} -+ -+/** -+ * Get the status counters for a port. -+ * -+ * @port_num: Port number to get statistics for. -+ * @clear: Set to 1 to clear the counters after they are read -+ * @status: Where to put the results. -+ */ -+static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear, -+ cvmx_pip_port_status_t *status) -+{ -+ union cvmx_pip_stat_ctl pip_stat_ctl; -+ union cvmx_pip_stat0_prtx stat0; -+ union cvmx_pip_stat1_prtx stat1; -+ union cvmx_pip_stat2_prtx stat2; -+ union cvmx_pip_stat3_prtx stat3; -+ union cvmx_pip_stat4_prtx stat4; -+ union cvmx_pip_stat5_prtx stat5; -+ union cvmx_pip_stat6_prtx stat6; -+ union cvmx_pip_stat7_prtx stat7; -+ union cvmx_pip_stat8_prtx stat8; -+ union cvmx_pip_stat9_prtx stat9; -+ union cvmx_pip_stat_inb_pktsx pip_stat_inb_pktsx; -+ union cvmx_pip_stat_inb_octsx pip_stat_inb_octsx; -+ union cvmx_pip_stat_inb_errsx pip_stat_inb_errsx; -+ -+ pip_stat_ctl.u64 = 0; -+ pip_stat_ctl.s.rdclr = clear; -+ cvmx_write_csr(CVMX_PIP_STAT_CTL, pip_stat_ctl.u64); -+ -+ stat0.u64 = cvmx_read_csr(CVMX_PIP_STAT0_PRTX(port_num)); -+ stat1.u64 = cvmx_read_csr(CVMX_PIP_STAT1_PRTX(port_num)); -+ stat2.u64 = cvmx_read_csr(CVMX_PIP_STAT2_PRTX(port_num)); -+ stat3.u64 = cvmx_read_csr(CVMX_PIP_STAT3_PRTX(port_num)); -+ stat4.u64 = cvmx_read_csr(CVMX_PIP_STAT4_PRTX(port_num)); -+ stat5.u64 = cvmx_read_csr(CVMX_PIP_STAT5_PRTX(port_num)); -+ stat6.u64 = cvmx_read_csr(CVMX_PIP_STAT6_PRTX(port_num)); -+ stat7.u64 = cvmx_read_csr(CVMX_PIP_STAT7_PRTX(port_num)); -+ stat8.u64 = cvmx_read_csr(CVMX_PIP_STAT8_PRTX(port_num)); -+ stat9.u64 = cvmx_read_csr(CVMX_PIP_STAT9_PRTX(port_num)); -+ pip_stat_inb_pktsx.u64 = -+ cvmx_read_csr(CVMX_PIP_STAT_INB_PKTSX(port_num)); -+ pip_stat_inb_octsx.u64 = -+ cvmx_read_csr(CVMX_PIP_STAT_INB_OCTSX(port_num)); -+ pip_stat_inb_errsx.u64 = -+ cvmx_read_csr(CVMX_PIP_STAT_INB_ERRSX(port_num)); -+ -+ status->dropped_octets = stat0.s.drp_octs; -+ status->dropped_packets = stat0.s.drp_pkts; -+ status->octets = stat1.s.octs; -+ status->pci_raw_packets = stat2.s.raw; -+ status->packets = stat2.s.pkts; -+ status->multicast_packets = stat3.s.mcst; -+ status->broadcast_packets = stat3.s.bcst; -+ status->len_64_packets = stat4.s.h64; -+ status->len_65_127_packets = stat4.s.h65to127; -+ status->len_128_255_packets = stat5.s.h128to255; -+ status->len_256_511_packets = stat5.s.h256to511; -+ status->len_512_1023_packets = stat6.s.h512to1023; -+ status->len_1024_1518_packets = stat6.s.h1024to1518; -+ status->len_1519_max_packets = stat7.s.h1519; -+ status->fcs_align_err_packets = stat7.s.fcs; -+ status->runt_packets = stat8.s.undersz; -+ status->runt_crc_packets = stat8.s.frag; -+ status->oversize_packets = stat9.s.oversz; -+ status->oversize_crc_packets = stat9.s.jabber; -+ status->inb_packets = pip_stat_inb_pktsx.s.pkts; -+ status->inb_octets = pip_stat_inb_octsx.s.octs; -+ status->inb_errors = pip_stat_inb_errsx.s.errs; -+ -+ if (cvmx_octeon_is_pass1()) { -+ /* -+ * Kludge to fix Octeon Pass 1 errata - Drop counts -+ * don't work. -+ */ -+ if (status->inb_packets > status->packets) -+ status->dropped_packets = -+ status->inb_packets - status->packets; -+ else -+ status->dropped_packets = 0; -+ if (status->inb_octets - status->inb_packets * 4 > -+ status->octets) -+ status->dropped_octets = -+ status->inb_octets - status->inb_packets * 4 - -+ status->octets; -+ else -+ status->dropped_octets = 0; -+ } -+} -+ -+/** -+ * Configure the hardware CRC engine -+ * -+ * @interface: Interface to configure (0 or 1) -+ * @invert_result: -+ * Invert the result of the CRC -+ * @reflect: Reflect -+ * @initialization_vector: -+ * CRC initialization vector -+ */ -+static inline void cvmx_pip_config_crc(uint64_t interface, -+ uint64_t invert_result, uint64_t reflect, -+ uint32_t initialization_vector) -+{ -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ union cvmx_pip_crc_ctlx config; -+ union cvmx_pip_crc_ivx pip_crc_ivx; -+ -+ config.u64 = 0; -+ config.s.invres = invert_result; -+ config.s.reflect = reflect; -+ cvmx_write_csr(CVMX_PIP_CRC_CTLX(interface), config.u64); -+ -+ pip_crc_ivx.u64 = 0; -+ pip_crc_ivx.s.iv = initialization_vector; -+ cvmx_write_csr(CVMX_PIP_CRC_IVX(interface), pip_crc_ivx.u64); -+ } -+} -+ -+/** -+ * Clear all bits in a tag mask. This should be called on -+ * startup before any calls to cvmx_pip_tag_mask_set. Each bit -+ * set in the final mask represent a byte used in the packet for -+ * tag generation. -+ * -+ * @mask_index: Which tag mask to clear (0..3) -+ */ -+static inline void cvmx_pip_tag_mask_clear(uint64_t mask_index) -+{ -+ uint64_t index; -+ union cvmx_pip_tag_incx pip_tag_incx; -+ pip_tag_incx.u64 = 0; -+ pip_tag_incx.s.en = 0; -+ for (index = mask_index * 16; index < (mask_index + 1) * 16; index++) -+ cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64); -+} -+ -+/** -+ * Sets a range of bits in the tag mask. The tag mask is used -+ * when the cvmx_pip_port_tag_cfg_t tag_mode is non zero. -+ * There are four separate masks that can be configured. -+ * -+ * @mask_index: Which tag mask to modify (0..3) -+ * @offset: Offset into the bitmask to set bits at. Use the GCC macro -+ * offsetof() to determine the offsets into packet headers. -+ * For example, offsetof(ethhdr, protocol) returns the offset -+ * of the ethernet protocol field. The bitmask selects which -+ * bytes to include the the tag, with bit offset X selecting -+ * byte at offset X from the beginning of the packet data. -+ * @len: Number of bytes to include. Usually this is the sizeof() -+ * the field. -+ */ -+static inline void cvmx_pip_tag_mask_set(uint64_t mask_index, uint64_t offset, -+ uint64_t len) -+{ -+ while (len--) { -+ union cvmx_pip_tag_incx pip_tag_incx; -+ uint64_t index = mask_index * 16 + offset / 8; -+ pip_tag_incx.u64 = cvmx_read_csr(CVMX_PIP_TAG_INCX(index)); -+ pip_tag_incx.s.en |= 0x80 >> (offset & 0x7); -+ cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64); -+ offset++; -+ } -+} -+ -+#endif /* __CVMX_PIP_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pko-defs.h -@@ -0,0 +1,1133 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_PKO_DEFS_H__ -+#define __CVMX_PKO_DEFS_H__ -+ -+#define CVMX_PKO_MEM_COUNT0 \ -+ CVMX_ADD_IO_SEG(0x0001180050001080ull) -+#define CVMX_PKO_MEM_COUNT1 \ -+ CVMX_ADD_IO_SEG(0x0001180050001088ull) -+#define CVMX_PKO_MEM_DEBUG0 \ -+ CVMX_ADD_IO_SEG(0x0001180050001100ull) -+#define CVMX_PKO_MEM_DEBUG1 \ -+ CVMX_ADD_IO_SEG(0x0001180050001108ull) -+#define CVMX_PKO_MEM_DEBUG10 \ -+ CVMX_ADD_IO_SEG(0x0001180050001150ull) -+#define CVMX_PKO_MEM_DEBUG11 \ -+ CVMX_ADD_IO_SEG(0x0001180050001158ull) -+#define CVMX_PKO_MEM_DEBUG12 \ -+ CVMX_ADD_IO_SEG(0x0001180050001160ull) -+#define CVMX_PKO_MEM_DEBUG13 \ -+ CVMX_ADD_IO_SEG(0x0001180050001168ull) -+#define CVMX_PKO_MEM_DEBUG14 \ -+ CVMX_ADD_IO_SEG(0x0001180050001170ull) -+#define CVMX_PKO_MEM_DEBUG2 \ -+ CVMX_ADD_IO_SEG(0x0001180050001110ull) -+#define CVMX_PKO_MEM_DEBUG3 \ -+ CVMX_ADD_IO_SEG(0x0001180050001118ull) -+#define CVMX_PKO_MEM_DEBUG4 \ -+ CVMX_ADD_IO_SEG(0x0001180050001120ull) -+#define CVMX_PKO_MEM_DEBUG5 \ -+ CVMX_ADD_IO_SEG(0x0001180050001128ull) -+#define CVMX_PKO_MEM_DEBUG6 \ -+ CVMX_ADD_IO_SEG(0x0001180050001130ull) -+#define CVMX_PKO_MEM_DEBUG7 \ -+ CVMX_ADD_IO_SEG(0x0001180050001138ull) -+#define CVMX_PKO_MEM_DEBUG8 \ -+ CVMX_ADD_IO_SEG(0x0001180050001140ull) -+#define CVMX_PKO_MEM_DEBUG9 \ -+ CVMX_ADD_IO_SEG(0x0001180050001148ull) -+#define CVMX_PKO_MEM_PORT_PTRS \ -+ CVMX_ADD_IO_SEG(0x0001180050001010ull) -+#define CVMX_PKO_MEM_PORT_QOS \ -+ CVMX_ADD_IO_SEG(0x0001180050001018ull) -+#define CVMX_PKO_MEM_PORT_RATE0 \ -+ CVMX_ADD_IO_SEG(0x0001180050001020ull) -+#define CVMX_PKO_MEM_PORT_RATE1 \ -+ CVMX_ADD_IO_SEG(0x0001180050001028ull) -+#define CVMX_PKO_MEM_QUEUE_PTRS \ -+ CVMX_ADD_IO_SEG(0x0001180050001000ull) -+#define CVMX_PKO_MEM_QUEUE_QOS \ -+ CVMX_ADD_IO_SEG(0x0001180050001008ull) -+#define CVMX_PKO_REG_BIST_RESULT \ -+ CVMX_ADD_IO_SEG(0x0001180050000080ull) -+#define CVMX_PKO_REG_CMD_BUF \ -+ CVMX_ADD_IO_SEG(0x0001180050000010ull) -+#define CVMX_PKO_REG_CRC_CTLX(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180050000028ull + (((offset) & 1) * 8)) -+#define CVMX_PKO_REG_CRC_ENABLE \ -+ CVMX_ADD_IO_SEG(0x0001180050000020ull) -+#define CVMX_PKO_REG_CRC_IVX(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180050000038ull + (((offset) & 1) * 8)) -+#define CVMX_PKO_REG_DEBUG0 \ -+ CVMX_ADD_IO_SEG(0x0001180050000098ull) -+#define CVMX_PKO_REG_DEBUG1 \ -+ CVMX_ADD_IO_SEG(0x00011800500000A0ull) -+#define CVMX_PKO_REG_DEBUG2 \ -+ CVMX_ADD_IO_SEG(0x00011800500000A8ull) -+#define CVMX_PKO_REG_DEBUG3 \ -+ CVMX_ADD_IO_SEG(0x00011800500000B0ull) -+#define CVMX_PKO_REG_ENGINE_INFLIGHT \ -+ CVMX_ADD_IO_SEG(0x0001180050000050ull) -+#define CVMX_PKO_REG_ENGINE_THRESH \ -+ CVMX_ADD_IO_SEG(0x0001180050000058ull) -+#define CVMX_PKO_REG_ERROR \ -+ CVMX_ADD_IO_SEG(0x0001180050000088ull) -+#define CVMX_PKO_REG_FLAGS \ -+ CVMX_ADD_IO_SEG(0x0001180050000000ull) -+#define CVMX_PKO_REG_GMX_PORT_MODE \ -+ CVMX_ADD_IO_SEG(0x0001180050000018ull) -+#define CVMX_PKO_REG_INT_MASK \ -+ CVMX_ADD_IO_SEG(0x0001180050000090ull) -+#define CVMX_PKO_REG_QUEUE_MODE \ -+ CVMX_ADD_IO_SEG(0x0001180050000048ull) -+#define CVMX_PKO_REG_QUEUE_PTRS1 \ -+ CVMX_ADD_IO_SEG(0x0001180050000100ull) -+#define CVMX_PKO_REG_READ_IDX \ -+ CVMX_ADD_IO_SEG(0x0001180050000008ull) -+ -+union cvmx_pko_mem_count0 { -+ uint64_t u64; -+ struct cvmx_pko_mem_count0_s { -+ uint64_t reserved_32_63:32; -+ uint64_t count:32; -+ } s; -+ struct cvmx_pko_mem_count0_s cn30xx; -+ struct cvmx_pko_mem_count0_s cn31xx; -+ struct cvmx_pko_mem_count0_s cn38xx; -+ struct cvmx_pko_mem_count0_s cn38xxp2; -+ struct cvmx_pko_mem_count0_s cn50xx; -+ struct cvmx_pko_mem_count0_s cn52xx; -+ struct cvmx_pko_mem_count0_s cn52xxp1; -+ struct cvmx_pko_mem_count0_s cn56xx; -+ struct cvmx_pko_mem_count0_s cn56xxp1; -+ struct cvmx_pko_mem_count0_s cn58xx; -+ struct cvmx_pko_mem_count0_s cn58xxp1; -+}; -+ -+union cvmx_pko_mem_count1 { -+ uint64_t u64; -+ struct cvmx_pko_mem_count1_s { -+ uint64_t reserved_48_63:16; -+ uint64_t count:48; -+ } s; -+ struct cvmx_pko_mem_count1_s cn30xx; -+ struct cvmx_pko_mem_count1_s cn31xx; -+ struct cvmx_pko_mem_count1_s cn38xx; -+ struct cvmx_pko_mem_count1_s cn38xxp2; -+ struct cvmx_pko_mem_count1_s cn50xx; -+ struct cvmx_pko_mem_count1_s cn52xx; -+ struct cvmx_pko_mem_count1_s cn52xxp1; -+ struct cvmx_pko_mem_count1_s cn56xx; -+ struct cvmx_pko_mem_count1_s cn56xxp1; -+ struct cvmx_pko_mem_count1_s cn58xx; -+ struct cvmx_pko_mem_count1_s cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug0 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug0_s { -+ uint64_t fau:28; -+ uint64_t cmd:14; -+ uint64_t segs:6; -+ uint64_t size:16; -+ } s; -+ struct cvmx_pko_mem_debug0_s cn30xx; -+ struct cvmx_pko_mem_debug0_s cn31xx; -+ struct cvmx_pko_mem_debug0_s cn38xx; -+ struct cvmx_pko_mem_debug0_s cn38xxp2; -+ struct cvmx_pko_mem_debug0_s cn50xx; -+ struct cvmx_pko_mem_debug0_s cn52xx; -+ struct cvmx_pko_mem_debug0_s cn52xxp1; -+ struct cvmx_pko_mem_debug0_s cn56xx; -+ struct cvmx_pko_mem_debug0_s cn56xxp1; -+ struct cvmx_pko_mem_debug0_s cn58xx; -+ struct cvmx_pko_mem_debug0_s cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug1 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug1_s { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t size:16; -+ uint64_t ptr:40; -+ } s; -+ struct cvmx_pko_mem_debug1_s cn30xx; -+ struct cvmx_pko_mem_debug1_s cn31xx; -+ struct cvmx_pko_mem_debug1_s cn38xx; -+ struct cvmx_pko_mem_debug1_s cn38xxp2; -+ struct cvmx_pko_mem_debug1_s cn50xx; -+ struct cvmx_pko_mem_debug1_s cn52xx; -+ struct cvmx_pko_mem_debug1_s cn52xxp1; -+ struct cvmx_pko_mem_debug1_s cn56xx; -+ struct cvmx_pko_mem_debug1_s cn56xxp1; -+ struct cvmx_pko_mem_debug1_s cn58xx; -+ struct cvmx_pko_mem_debug1_s cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug10 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug10_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_mem_debug10_cn30xx { -+ uint64_t fau:28; -+ uint64_t cmd:14; -+ uint64_t segs:6; -+ uint64_t size:16; -+ } cn30xx; -+ struct cvmx_pko_mem_debug10_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug10_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug10_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug10_cn50xx { -+ uint64_t reserved_49_63:15; -+ uint64_t ptrs1:17; -+ uint64_t reserved_17_31:15; -+ uint64_t ptrs2:17; -+ } cn50xx; -+ struct cvmx_pko_mem_debug10_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug10_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug10_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug10_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug10_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug10_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug11 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug11_s { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t size:16; -+ uint64_t reserved_0_39:40; -+ } s; -+ struct cvmx_pko_mem_debug11_cn30xx { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t size:16; -+ uint64_t ptr:40; -+ } cn30xx; -+ struct cvmx_pko_mem_debug11_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug11_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug11_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug11_cn50xx { -+ uint64_t reserved_23_63:41; -+ uint64_t maj:1; -+ uint64_t uid:3; -+ uint64_t sop:1; -+ uint64_t len:1; -+ uint64_t chk:1; -+ uint64_t cnt:13; -+ uint64_t mod:3; -+ } cn50xx; -+ struct cvmx_pko_mem_debug11_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug11_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug11_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug11_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug11_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug11_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug12 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug12_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_mem_debug12_cn30xx { -+ uint64_t data:64; -+ } cn30xx; -+ struct cvmx_pko_mem_debug12_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug12_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug12_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug12_cn50xx { -+ uint64_t fau:28; -+ uint64_t cmd:14; -+ uint64_t segs:6; -+ uint64_t size:16; -+ } cn50xx; -+ struct cvmx_pko_mem_debug12_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug12_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug12_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug12_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug12_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug12_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug13 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug13_s { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t reserved_0_55:56; -+ } s; -+ struct cvmx_pko_mem_debug13_cn30xx { -+ uint64_t reserved_51_63:13; -+ uint64_t widx:17; -+ uint64_t ridx2:17; -+ uint64_t widx2:17; -+ } cn30xx; -+ struct cvmx_pko_mem_debug13_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug13_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug13_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug13_cn50xx { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t size:16; -+ uint64_t ptr:40; -+ } cn50xx; -+ struct cvmx_pko_mem_debug13_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug13_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug13_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug13_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug13_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug13_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug14 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug14_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_mem_debug14_cn30xx { -+ uint64_t reserved_17_63:47; -+ uint64_t ridx:17; -+ } cn30xx; -+ struct cvmx_pko_mem_debug14_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug14_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug14_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug14_cn52xx { -+ uint64_t data:64; -+ } cn52xx; -+ struct cvmx_pko_mem_debug14_cn52xx cn52xxp1; -+ struct cvmx_pko_mem_debug14_cn52xx cn56xx; -+ struct cvmx_pko_mem_debug14_cn52xx cn56xxp1; -+}; -+ -+union cvmx_pko_mem_debug2 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug2_s { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t size:16; -+ uint64_t ptr:40; -+ } s; -+ struct cvmx_pko_mem_debug2_s cn30xx; -+ struct cvmx_pko_mem_debug2_s cn31xx; -+ struct cvmx_pko_mem_debug2_s cn38xx; -+ struct cvmx_pko_mem_debug2_s cn38xxp2; -+ struct cvmx_pko_mem_debug2_s cn50xx; -+ struct cvmx_pko_mem_debug2_s cn52xx; -+ struct cvmx_pko_mem_debug2_s cn52xxp1; -+ struct cvmx_pko_mem_debug2_s cn56xx; -+ struct cvmx_pko_mem_debug2_s cn56xxp1; -+ struct cvmx_pko_mem_debug2_s cn58xx; -+ struct cvmx_pko_mem_debug2_s cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug3 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug3_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_mem_debug3_cn30xx { -+ uint64_t i:1; -+ uint64_t back:4; -+ uint64_t pool:3; -+ uint64_t size:16; -+ uint64_t ptr:40; -+ } cn30xx; -+ struct cvmx_pko_mem_debug3_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug3_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug3_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug3_cn50xx { -+ uint64_t data:64; -+ } cn50xx; -+ struct cvmx_pko_mem_debug3_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug3_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug3_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug3_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug3_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug3_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug4 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug4_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_mem_debug4_cn30xx { -+ uint64_t data:64; -+ } cn30xx; -+ struct cvmx_pko_mem_debug4_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug4_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug4_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug4_cn50xx { -+ uint64_t cmnd_segs:3; -+ uint64_t cmnd_siz:16; -+ uint64_t cmnd_off:6; -+ uint64_t uid:3; -+ uint64_t dread_sop:1; -+ uint64_t init_dwrite:1; -+ uint64_t chk_once:1; -+ uint64_t chk_mode:1; -+ uint64_t active:1; -+ uint64_t static_p:1; -+ uint64_t qos:3; -+ uint64_t qcb_ridx:5; -+ uint64_t qid_off_max:4; -+ uint64_t qid_off:4; -+ uint64_t qid_base:8; -+ uint64_t wait:1; -+ uint64_t minor:2; -+ uint64_t major:3; -+ } cn50xx; -+ struct cvmx_pko_mem_debug4_cn52xx { -+ uint64_t curr_siz:8; -+ uint64_t curr_off:16; -+ uint64_t cmnd_segs:6; -+ uint64_t cmnd_siz:16; -+ uint64_t cmnd_off:6; -+ uint64_t uid:2; -+ uint64_t dread_sop:1; -+ uint64_t init_dwrite:1; -+ uint64_t chk_once:1; -+ uint64_t chk_mode:1; -+ uint64_t wait:1; -+ uint64_t minor:2; -+ uint64_t major:3; -+ } cn52xx; -+ struct cvmx_pko_mem_debug4_cn52xx cn52xxp1; -+ struct cvmx_pko_mem_debug4_cn52xx cn56xx; -+ struct cvmx_pko_mem_debug4_cn52xx cn56xxp1; -+ struct cvmx_pko_mem_debug4_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug4_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug5 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug5_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_mem_debug5_cn30xx { -+ uint64_t dwri_mod:1; -+ uint64_t dwri_sop:1; -+ uint64_t dwri_len:1; -+ uint64_t dwri_cnt:13; -+ uint64_t cmnd_siz:16; -+ uint64_t uid:1; -+ uint64_t xfer_wor:1; -+ uint64_t xfer_dwr:1; -+ uint64_t cbuf_fre:1; -+ uint64_t reserved_27_27:1; -+ uint64_t chk_mode:1; -+ uint64_t active:1; -+ uint64_t qos:3; -+ uint64_t qcb_ridx:5; -+ uint64_t qid_off:3; -+ uint64_t qid_base:7; -+ uint64_t wait:1; -+ uint64_t minor:2; -+ uint64_t major:4; -+ } cn30xx; -+ struct cvmx_pko_mem_debug5_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug5_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug5_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug5_cn50xx { -+ uint64_t curr_ptr:29; -+ uint64_t curr_siz:16; -+ uint64_t curr_off:16; -+ uint64_t cmnd_segs:3; -+ } cn50xx; -+ struct cvmx_pko_mem_debug5_cn52xx { -+ uint64_t reserved_54_63:10; -+ uint64_t nxt_inflt:6; -+ uint64_t curr_ptr:40; -+ uint64_t curr_siz:8; -+ } cn52xx; -+ struct cvmx_pko_mem_debug5_cn52xx cn52xxp1; -+ struct cvmx_pko_mem_debug5_cn52xx cn56xx; -+ struct cvmx_pko_mem_debug5_cn52xx cn56xxp1; -+ struct cvmx_pko_mem_debug5_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug5_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug6 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug6_s { -+ uint64_t reserved_37_63:27; -+ uint64_t qid_offres:4; -+ uint64_t qid_offths:4; -+ uint64_t preempter:1; -+ uint64_t preemptee:1; -+ uint64_t preempted:1; -+ uint64_t active:1; -+ uint64_t statc:1; -+ uint64_t qos:3; -+ uint64_t qcb_ridx:5; -+ uint64_t qid_offmax:4; -+ uint64_t reserved_0_11:12; -+ } s; -+ struct cvmx_pko_mem_debug6_cn30xx { -+ uint64_t reserved_11_63:53; -+ uint64_t qid_offm:3; -+ uint64_t static_p:1; -+ uint64_t work_min:3; -+ uint64_t dwri_chk:1; -+ uint64_t dwri_uid:1; -+ uint64_t dwri_mod:2; -+ } cn30xx; -+ struct cvmx_pko_mem_debug6_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug6_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug6_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug6_cn50xx { -+ uint64_t reserved_11_63:53; -+ uint64_t curr_ptr:11; -+ } cn50xx; -+ struct cvmx_pko_mem_debug6_cn52xx { -+ uint64_t reserved_37_63:27; -+ uint64_t qid_offres:4; -+ uint64_t qid_offths:4; -+ uint64_t preempter:1; -+ uint64_t preemptee:1; -+ uint64_t preempted:1; -+ uint64_t active:1; -+ uint64_t statc:1; -+ uint64_t qos:3; -+ uint64_t qcb_ridx:5; -+ uint64_t qid_offmax:4; -+ uint64_t qid_off:4; -+ uint64_t qid_base:8; -+ } cn52xx; -+ struct cvmx_pko_mem_debug6_cn52xx cn52xxp1; -+ struct cvmx_pko_mem_debug6_cn52xx cn56xx; -+ struct cvmx_pko_mem_debug6_cn52xx cn56xxp1; -+ struct cvmx_pko_mem_debug6_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug6_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug7 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug7_s { -+ uint64_t qos:5; -+ uint64_t tail:1; -+ uint64_t reserved_0_57:58; -+ } s; -+ struct cvmx_pko_mem_debug7_cn30xx { -+ uint64_t reserved_58_63:6; -+ uint64_t dwb:9; -+ uint64_t start:33; -+ uint64_t size:16; -+ } cn30xx; -+ struct cvmx_pko_mem_debug7_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug7_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug7_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug7_cn50xx { -+ uint64_t qos:5; -+ uint64_t tail:1; -+ uint64_t buf_siz:13; -+ uint64_t buf_ptr:33; -+ uint64_t qcb_widx:6; -+ uint64_t qcb_ridx:6; -+ } cn50xx; -+ struct cvmx_pko_mem_debug7_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug7_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug7_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug7_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug7_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug7_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug8 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug8_s { -+ uint64_t reserved_59_63:5; -+ uint64_t tail:1; -+ uint64_t buf_siz:13; -+ uint64_t reserved_0_44:45; -+ } s; -+ struct cvmx_pko_mem_debug8_cn30xx { -+ uint64_t qos:5; -+ uint64_t tail:1; -+ uint64_t buf_siz:13; -+ uint64_t buf_ptr:33; -+ uint64_t qcb_widx:6; -+ uint64_t qcb_ridx:6; -+ } cn30xx; -+ struct cvmx_pko_mem_debug8_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug8_cn30xx cn38xx; -+ struct cvmx_pko_mem_debug8_cn30xx cn38xxp2; -+ struct cvmx_pko_mem_debug8_cn50xx { -+ uint64_t reserved_28_63:36; -+ uint64_t doorbell:20; -+ uint64_t reserved_6_7:2; -+ uint64_t static_p:1; -+ uint64_t s_tail:1; -+ uint64_t static_q:1; -+ uint64_t qos:3; -+ } cn50xx; -+ struct cvmx_pko_mem_debug8_cn52xx { -+ uint64_t reserved_29_63:35; -+ uint64_t preempter:1; -+ uint64_t doorbell:20; -+ uint64_t reserved_7_7:1; -+ uint64_t preemptee:1; -+ uint64_t static_p:1; -+ uint64_t s_tail:1; -+ uint64_t static_q:1; -+ uint64_t qos:3; -+ } cn52xx; -+ struct cvmx_pko_mem_debug8_cn52xx cn52xxp1; -+ struct cvmx_pko_mem_debug8_cn52xx cn56xx; -+ struct cvmx_pko_mem_debug8_cn52xx cn56xxp1; -+ struct cvmx_pko_mem_debug8_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug8_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_debug9 { -+ uint64_t u64; -+ struct cvmx_pko_mem_debug9_s { -+ uint64_t reserved_49_63:15; -+ uint64_t ptrs0:17; -+ uint64_t reserved_0_31:32; -+ } s; -+ struct cvmx_pko_mem_debug9_cn30xx { -+ uint64_t reserved_28_63:36; -+ uint64_t doorbell:20; -+ uint64_t reserved_5_7:3; -+ uint64_t s_tail:1; -+ uint64_t static_q:1; -+ uint64_t qos:3; -+ } cn30xx; -+ struct cvmx_pko_mem_debug9_cn30xx cn31xx; -+ struct cvmx_pko_mem_debug9_cn38xx { -+ uint64_t reserved_28_63:36; -+ uint64_t doorbell:20; -+ uint64_t reserved_6_7:2; -+ uint64_t static_p:1; -+ uint64_t s_tail:1; -+ uint64_t static_q:1; -+ uint64_t qos:3; -+ } cn38xx; -+ struct cvmx_pko_mem_debug9_cn38xx cn38xxp2; -+ struct cvmx_pko_mem_debug9_cn50xx { -+ uint64_t reserved_49_63:15; -+ uint64_t ptrs0:17; -+ uint64_t reserved_17_31:15; -+ uint64_t ptrs3:17; -+ } cn50xx; -+ struct cvmx_pko_mem_debug9_cn50xx cn52xx; -+ struct cvmx_pko_mem_debug9_cn50xx cn52xxp1; -+ struct cvmx_pko_mem_debug9_cn50xx cn56xx; -+ struct cvmx_pko_mem_debug9_cn50xx cn56xxp1; -+ struct cvmx_pko_mem_debug9_cn50xx cn58xx; -+ struct cvmx_pko_mem_debug9_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_mem_port_ptrs { -+ uint64_t u64; -+ struct cvmx_pko_mem_port_ptrs_s { -+ uint64_t reserved_62_63:2; -+ uint64_t static_p:1; -+ uint64_t qos_mask:8; -+ uint64_t reserved_16_52:37; -+ uint64_t bp_port:6; -+ uint64_t eid:4; -+ uint64_t pid:6; -+ } s; -+ struct cvmx_pko_mem_port_ptrs_s cn52xx; -+ struct cvmx_pko_mem_port_ptrs_s cn52xxp1; -+ struct cvmx_pko_mem_port_ptrs_s cn56xx; -+ struct cvmx_pko_mem_port_ptrs_s cn56xxp1; -+}; -+ -+union cvmx_pko_mem_port_qos { -+ uint64_t u64; -+ struct cvmx_pko_mem_port_qos_s { -+ uint64_t reserved_61_63:3; -+ uint64_t qos_mask:8; -+ uint64_t reserved_10_52:43; -+ uint64_t eid:4; -+ uint64_t pid:6; -+ } s; -+ struct cvmx_pko_mem_port_qos_s cn52xx; -+ struct cvmx_pko_mem_port_qos_s cn52xxp1; -+ struct cvmx_pko_mem_port_qos_s cn56xx; -+ struct cvmx_pko_mem_port_qos_s cn56xxp1; -+}; -+ -+union cvmx_pko_mem_port_rate0 { -+ uint64_t u64; -+ struct cvmx_pko_mem_port_rate0_s { -+ uint64_t reserved_51_63:13; -+ uint64_t rate_word:19; -+ uint64_t rate_pkt:24; -+ uint64_t reserved_6_7:2; -+ uint64_t pid:6; -+ } s; -+ struct cvmx_pko_mem_port_rate0_s cn52xx; -+ struct cvmx_pko_mem_port_rate0_s cn52xxp1; -+ struct cvmx_pko_mem_port_rate0_s cn56xx; -+ struct cvmx_pko_mem_port_rate0_s cn56xxp1; -+}; -+ -+union cvmx_pko_mem_port_rate1 { -+ uint64_t u64; -+ struct cvmx_pko_mem_port_rate1_s { -+ uint64_t reserved_32_63:32; -+ uint64_t rate_lim:24; -+ uint64_t reserved_6_7:2; -+ uint64_t pid:6; -+ } s; -+ struct cvmx_pko_mem_port_rate1_s cn52xx; -+ struct cvmx_pko_mem_port_rate1_s cn52xxp1; -+ struct cvmx_pko_mem_port_rate1_s cn56xx; -+ struct cvmx_pko_mem_port_rate1_s cn56xxp1; -+}; -+ -+union cvmx_pko_mem_queue_ptrs { -+ uint64_t u64; -+ struct cvmx_pko_mem_queue_ptrs_s { -+ uint64_t s_tail:1; -+ uint64_t static_p:1; -+ uint64_t static_q:1; -+ uint64_t qos_mask:8; -+ uint64_t buf_ptr:36; -+ uint64_t tail:1; -+ uint64_t index:3; -+ uint64_t port:6; -+ uint64_t queue:7; -+ } s; -+ struct cvmx_pko_mem_queue_ptrs_s cn30xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn31xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn38xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn38xxp2; -+ struct cvmx_pko_mem_queue_ptrs_s cn50xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn52xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn52xxp1; -+ struct cvmx_pko_mem_queue_ptrs_s cn56xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn56xxp1; -+ struct cvmx_pko_mem_queue_ptrs_s cn58xx; -+ struct cvmx_pko_mem_queue_ptrs_s cn58xxp1; -+}; -+ -+union cvmx_pko_mem_queue_qos { -+ uint64_t u64; -+ struct cvmx_pko_mem_queue_qos_s { -+ uint64_t reserved_61_63:3; -+ uint64_t qos_mask:8; -+ uint64_t reserved_13_52:40; -+ uint64_t pid:6; -+ uint64_t qid:7; -+ } s; -+ struct cvmx_pko_mem_queue_qos_s cn30xx; -+ struct cvmx_pko_mem_queue_qos_s cn31xx; -+ struct cvmx_pko_mem_queue_qos_s cn38xx; -+ struct cvmx_pko_mem_queue_qos_s cn38xxp2; -+ struct cvmx_pko_mem_queue_qos_s cn50xx; -+ struct cvmx_pko_mem_queue_qos_s cn52xx; -+ struct cvmx_pko_mem_queue_qos_s cn52xxp1; -+ struct cvmx_pko_mem_queue_qos_s cn56xx; -+ struct cvmx_pko_mem_queue_qos_s cn56xxp1; -+ struct cvmx_pko_mem_queue_qos_s cn58xx; -+ struct cvmx_pko_mem_queue_qos_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_bist_result { -+ uint64_t u64; -+ struct cvmx_pko_reg_bist_result_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_pko_reg_bist_result_cn30xx { -+ uint64_t reserved_27_63:37; -+ uint64_t psb2:5; -+ uint64_t count:1; -+ uint64_t rif:1; -+ uint64_t wif:1; -+ uint64_t ncb:1; -+ uint64_t out:1; -+ uint64_t crc:1; -+ uint64_t chk:1; -+ uint64_t qsb:2; -+ uint64_t qcb:2; -+ uint64_t pdb:4; -+ uint64_t psb:7; -+ } cn30xx; -+ struct cvmx_pko_reg_bist_result_cn30xx cn31xx; -+ struct cvmx_pko_reg_bist_result_cn30xx cn38xx; -+ struct cvmx_pko_reg_bist_result_cn30xx cn38xxp2; -+ struct cvmx_pko_reg_bist_result_cn50xx { -+ uint64_t reserved_33_63:31; -+ uint64_t csr:1; -+ uint64_t iob:1; -+ uint64_t out_crc:1; -+ uint64_t out_ctl:3; -+ uint64_t out_sta:1; -+ uint64_t out_wif:1; -+ uint64_t prt_chk:3; -+ uint64_t prt_nxt:1; -+ uint64_t prt_psb:6; -+ uint64_t ncb_inb:2; -+ uint64_t prt_qcb:2; -+ uint64_t prt_qsb:3; -+ uint64_t dat_dat:4; -+ uint64_t dat_ptr:4; -+ } cn50xx; -+ struct cvmx_pko_reg_bist_result_cn52xx { -+ uint64_t reserved_35_63:29; -+ uint64_t csr:1; -+ uint64_t iob:1; -+ uint64_t out_dat:1; -+ uint64_t out_ctl:3; -+ uint64_t out_sta:1; -+ uint64_t out_wif:1; -+ uint64_t prt_chk:3; -+ uint64_t prt_nxt:1; -+ uint64_t prt_psb:8; -+ uint64_t ncb_inb:2; -+ uint64_t prt_qcb:2; -+ uint64_t prt_qsb:3; -+ uint64_t prt_ctl:2; -+ uint64_t dat_dat:2; -+ uint64_t dat_ptr:4; -+ } cn52xx; -+ struct cvmx_pko_reg_bist_result_cn52xx cn52xxp1; -+ struct cvmx_pko_reg_bist_result_cn52xx cn56xx; -+ struct cvmx_pko_reg_bist_result_cn52xx cn56xxp1; -+ struct cvmx_pko_reg_bist_result_cn50xx cn58xx; -+ struct cvmx_pko_reg_bist_result_cn50xx cn58xxp1; -+}; -+ -+union cvmx_pko_reg_cmd_buf { -+ uint64_t u64; -+ struct cvmx_pko_reg_cmd_buf_s { -+ uint64_t reserved_23_63:41; -+ uint64_t pool:3; -+ uint64_t reserved_13_19:7; -+ uint64_t size:13; -+ } s; -+ struct cvmx_pko_reg_cmd_buf_s cn30xx; -+ struct cvmx_pko_reg_cmd_buf_s cn31xx; -+ struct cvmx_pko_reg_cmd_buf_s cn38xx; -+ struct cvmx_pko_reg_cmd_buf_s cn38xxp2; -+ struct cvmx_pko_reg_cmd_buf_s cn50xx; -+ struct cvmx_pko_reg_cmd_buf_s cn52xx; -+ struct cvmx_pko_reg_cmd_buf_s cn52xxp1; -+ struct cvmx_pko_reg_cmd_buf_s cn56xx; -+ struct cvmx_pko_reg_cmd_buf_s cn56xxp1; -+ struct cvmx_pko_reg_cmd_buf_s cn58xx; -+ struct cvmx_pko_reg_cmd_buf_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_crc_ctlx { -+ uint64_t u64; -+ struct cvmx_pko_reg_crc_ctlx_s { -+ uint64_t reserved_2_63:62; -+ uint64_t invres:1; -+ uint64_t refin:1; -+ } s; -+ struct cvmx_pko_reg_crc_ctlx_s cn38xx; -+ struct cvmx_pko_reg_crc_ctlx_s cn38xxp2; -+ struct cvmx_pko_reg_crc_ctlx_s cn58xx; -+ struct cvmx_pko_reg_crc_ctlx_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_crc_enable { -+ uint64_t u64; -+ struct cvmx_pko_reg_crc_enable_s { -+ uint64_t reserved_32_63:32; -+ uint64_t enable:32; -+ } s; -+ struct cvmx_pko_reg_crc_enable_s cn38xx; -+ struct cvmx_pko_reg_crc_enable_s cn38xxp2; -+ struct cvmx_pko_reg_crc_enable_s cn58xx; -+ struct cvmx_pko_reg_crc_enable_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_crc_ivx { -+ uint64_t u64; -+ struct cvmx_pko_reg_crc_ivx_s { -+ uint64_t reserved_32_63:32; -+ uint64_t iv:32; -+ } s; -+ struct cvmx_pko_reg_crc_ivx_s cn38xx; -+ struct cvmx_pko_reg_crc_ivx_s cn38xxp2; -+ struct cvmx_pko_reg_crc_ivx_s cn58xx; -+ struct cvmx_pko_reg_crc_ivx_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_debug0 { -+ uint64_t u64; -+ struct cvmx_pko_reg_debug0_s { -+ uint64_t asserts:64; -+ } s; -+ struct cvmx_pko_reg_debug0_cn30xx { -+ uint64_t reserved_17_63:47; -+ uint64_t asserts:17; -+ } cn30xx; -+ struct cvmx_pko_reg_debug0_cn30xx cn31xx; -+ struct cvmx_pko_reg_debug0_cn30xx cn38xx; -+ struct cvmx_pko_reg_debug0_cn30xx cn38xxp2; -+ struct cvmx_pko_reg_debug0_s cn50xx; -+ struct cvmx_pko_reg_debug0_s cn52xx; -+ struct cvmx_pko_reg_debug0_s cn52xxp1; -+ struct cvmx_pko_reg_debug0_s cn56xx; -+ struct cvmx_pko_reg_debug0_s cn56xxp1; -+ struct cvmx_pko_reg_debug0_s cn58xx; -+ struct cvmx_pko_reg_debug0_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_debug1 { -+ uint64_t u64; -+ struct cvmx_pko_reg_debug1_s { -+ uint64_t asserts:64; -+ } s; -+ struct cvmx_pko_reg_debug1_s cn50xx; -+ struct cvmx_pko_reg_debug1_s cn52xx; -+ struct cvmx_pko_reg_debug1_s cn52xxp1; -+ struct cvmx_pko_reg_debug1_s cn56xx; -+ struct cvmx_pko_reg_debug1_s cn56xxp1; -+ struct cvmx_pko_reg_debug1_s cn58xx; -+ struct cvmx_pko_reg_debug1_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_debug2 { -+ uint64_t u64; -+ struct cvmx_pko_reg_debug2_s { -+ uint64_t asserts:64; -+ } s; -+ struct cvmx_pko_reg_debug2_s cn50xx; -+ struct cvmx_pko_reg_debug2_s cn52xx; -+ struct cvmx_pko_reg_debug2_s cn52xxp1; -+ struct cvmx_pko_reg_debug2_s cn56xx; -+ struct cvmx_pko_reg_debug2_s cn56xxp1; -+ struct cvmx_pko_reg_debug2_s cn58xx; -+ struct cvmx_pko_reg_debug2_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_debug3 { -+ uint64_t u64; -+ struct cvmx_pko_reg_debug3_s { -+ uint64_t asserts:64; -+ } s; -+ struct cvmx_pko_reg_debug3_s cn50xx; -+ struct cvmx_pko_reg_debug3_s cn52xx; -+ struct cvmx_pko_reg_debug3_s cn52xxp1; -+ struct cvmx_pko_reg_debug3_s cn56xx; -+ struct cvmx_pko_reg_debug3_s cn56xxp1; -+ struct cvmx_pko_reg_debug3_s cn58xx; -+ struct cvmx_pko_reg_debug3_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_engine_inflight { -+ uint64_t u64; -+ struct cvmx_pko_reg_engine_inflight_s { -+ uint64_t reserved_40_63:24; -+ uint64_t engine9:4; -+ uint64_t engine8:4; -+ uint64_t engine7:4; -+ uint64_t engine6:4; -+ uint64_t engine5:4; -+ uint64_t engine4:4; -+ uint64_t engine3:4; -+ uint64_t engine2:4; -+ uint64_t engine1:4; -+ uint64_t engine0:4; -+ } s; -+ struct cvmx_pko_reg_engine_inflight_s cn52xx; -+ struct cvmx_pko_reg_engine_inflight_s cn52xxp1; -+ struct cvmx_pko_reg_engine_inflight_s cn56xx; -+ struct cvmx_pko_reg_engine_inflight_s cn56xxp1; -+}; -+ -+union cvmx_pko_reg_engine_thresh { -+ uint64_t u64; -+ struct cvmx_pko_reg_engine_thresh_s { -+ uint64_t reserved_10_63:54; -+ uint64_t mask:10; -+ } s; -+ struct cvmx_pko_reg_engine_thresh_s cn52xx; -+ struct cvmx_pko_reg_engine_thresh_s cn52xxp1; -+ struct cvmx_pko_reg_engine_thresh_s cn56xx; -+ struct cvmx_pko_reg_engine_thresh_s cn56xxp1; -+}; -+ -+union cvmx_pko_reg_error { -+ uint64_t u64; -+ struct cvmx_pko_reg_error_s { -+ uint64_t reserved_3_63:61; -+ uint64_t currzero:1; -+ uint64_t doorbell:1; -+ uint64_t parity:1; -+ } s; -+ struct cvmx_pko_reg_error_cn30xx { -+ uint64_t reserved_2_63:62; -+ uint64_t doorbell:1; -+ uint64_t parity:1; -+ } cn30xx; -+ struct cvmx_pko_reg_error_cn30xx cn31xx; -+ struct cvmx_pko_reg_error_cn30xx cn38xx; -+ struct cvmx_pko_reg_error_cn30xx cn38xxp2; -+ struct cvmx_pko_reg_error_s cn50xx; -+ struct cvmx_pko_reg_error_s cn52xx; -+ struct cvmx_pko_reg_error_s cn52xxp1; -+ struct cvmx_pko_reg_error_s cn56xx; -+ struct cvmx_pko_reg_error_s cn56xxp1; -+ struct cvmx_pko_reg_error_s cn58xx; -+ struct cvmx_pko_reg_error_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_flags { -+ uint64_t u64; -+ struct cvmx_pko_reg_flags_s { -+ uint64_t reserved_4_63:60; -+ uint64_t reset:1; -+ uint64_t store_be:1; -+ uint64_t ena_dwb:1; -+ uint64_t ena_pko:1; -+ } s; -+ struct cvmx_pko_reg_flags_s cn30xx; -+ struct cvmx_pko_reg_flags_s cn31xx; -+ struct cvmx_pko_reg_flags_s cn38xx; -+ struct cvmx_pko_reg_flags_s cn38xxp2; -+ struct cvmx_pko_reg_flags_s cn50xx; -+ struct cvmx_pko_reg_flags_s cn52xx; -+ struct cvmx_pko_reg_flags_s cn52xxp1; -+ struct cvmx_pko_reg_flags_s cn56xx; -+ struct cvmx_pko_reg_flags_s cn56xxp1; -+ struct cvmx_pko_reg_flags_s cn58xx; -+ struct cvmx_pko_reg_flags_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_gmx_port_mode { -+ uint64_t u64; -+ struct cvmx_pko_reg_gmx_port_mode_s { -+ uint64_t reserved_6_63:58; -+ uint64_t mode1:3; -+ uint64_t mode0:3; -+ } s; -+ struct cvmx_pko_reg_gmx_port_mode_s cn30xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn31xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn38xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn38xxp2; -+ struct cvmx_pko_reg_gmx_port_mode_s cn50xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn52xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn52xxp1; -+ struct cvmx_pko_reg_gmx_port_mode_s cn56xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn56xxp1; -+ struct cvmx_pko_reg_gmx_port_mode_s cn58xx; -+ struct cvmx_pko_reg_gmx_port_mode_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_int_mask { -+ uint64_t u64; -+ struct cvmx_pko_reg_int_mask_s { -+ uint64_t reserved_3_63:61; -+ uint64_t currzero:1; -+ uint64_t doorbell:1; -+ uint64_t parity:1; -+ } s; -+ struct cvmx_pko_reg_int_mask_cn30xx { -+ uint64_t reserved_2_63:62; -+ uint64_t doorbell:1; -+ uint64_t parity:1; -+ } cn30xx; -+ struct cvmx_pko_reg_int_mask_cn30xx cn31xx; -+ struct cvmx_pko_reg_int_mask_cn30xx cn38xx; -+ struct cvmx_pko_reg_int_mask_cn30xx cn38xxp2; -+ struct cvmx_pko_reg_int_mask_s cn50xx; -+ struct cvmx_pko_reg_int_mask_s cn52xx; -+ struct cvmx_pko_reg_int_mask_s cn52xxp1; -+ struct cvmx_pko_reg_int_mask_s cn56xx; -+ struct cvmx_pko_reg_int_mask_s cn56xxp1; -+ struct cvmx_pko_reg_int_mask_s cn58xx; -+ struct cvmx_pko_reg_int_mask_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_queue_mode { -+ uint64_t u64; -+ struct cvmx_pko_reg_queue_mode_s { -+ uint64_t reserved_2_63:62; -+ uint64_t mode:2; -+ } s; -+ struct cvmx_pko_reg_queue_mode_s cn30xx; -+ struct cvmx_pko_reg_queue_mode_s cn31xx; -+ struct cvmx_pko_reg_queue_mode_s cn38xx; -+ struct cvmx_pko_reg_queue_mode_s cn38xxp2; -+ struct cvmx_pko_reg_queue_mode_s cn50xx; -+ struct cvmx_pko_reg_queue_mode_s cn52xx; -+ struct cvmx_pko_reg_queue_mode_s cn52xxp1; -+ struct cvmx_pko_reg_queue_mode_s cn56xx; -+ struct cvmx_pko_reg_queue_mode_s cn56xxp1; -+ struct cvmx_pko_reg_queue_mode_s cn58xx; -+ struct cvmx_pko_reg_queue_mode_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_queue_ptrs1 { -+ uint64_t u64; -+ struct cvmx_pko_reg_queue_ptrs1_s { -+ uint64_t reserved_2_63:62; -+ uint64_t idx3:1; -+ uint64_t qid7:1; -+ } s; -+ struct cvmx_pko_reg_queue_ptrs1_s cn50xx; -+ struct cvmx_pko_reg_queue_ptrs1_s cn52xx; -+ struct cvmx_pko_reg_queue_ptrs1_s cn52xxp1; -+ struct cvmx_pko_reg_queue_ptrs1_s cn56xx; -+ struct cvmx_pko_reg_queue_ptrs1_s cn56xxp1; -+ struct cvmx_pko_reg_queue_ptrs1_s cn58xx; -+ struct cvmx_pko_reg_queue_ptrs1_s cn58xxp1; -+}; -+ -+union cvmx_pko_reg_read_idx { -+ uint64_t u64; -+ struct cvmx_pko_reg_read_idx_s { -+ uint64_t reserved_16_63:48; -+ uint64_t inc:8; -+ uint64_t index:8; -+ } s; -+ struct cvmx_pko_reg_read_idx_s cn30xx; -+ struct cvmx_pko_reg_read_idx_s cn31xx; -+ struct cvmx_pko_reg_read_idx_s cn38xx; -+ struct cvmx_pko_reg_read_idx_s cn38xxp2; -+ struct cvmx_pko_reg_read_idx_s cn50xx; -+ struct cvmx_pko_reg_read_idx_s cn52xx; -+ struct cvmx_pko_reg_read_idx_s cn52xxp1; -+ struct cvmx_pko_reg_read_idx_s cn56xx; -+ struct cvmx_pko_reg_read_idx_s cn56xxp1; -+ struct cvmx_pko_reg_read_idx_s cn58xx; -+ struct cvmx_pko_reg_read_idx_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pko.c -@@ -0,0 +1,506 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * Support library for the hardware Packet Output unit. -+ */ -+ -+#include -+ -+#include "cvmx-config.h" -+#include "cvmx-pko.h" -+#include "cvmx-helper.h" -+ -+/** -+ * Internal state of packet output -+ */ -+ -+/** -+ * Call before any other calls to initialize the packet -+ * output system. This does chip global config, and should only be -+ * done by one core. -+ */ -+ -+void cvmx_pko_initialize_global(void) -+{ -+ int i; -+ uint64_t priority = 8; -+ union cvmx_pko_reg_cmd_buf config; -+ -+ /* -+ * Set the size of the PKO command buffers to an odd number of -+ * 64bit words. This allows the normal two word send to stay -+ * aligned and never span a comamnd word buffer. -+ */ -+ config.u64 = 0; -+ config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL; -+ config.s.size = CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE / 8 - 1; -+ -+ cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64); -+ -+ for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) -+ cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1, -+ &priority); -+ -+ /* -+ * If we aren't using all of the queues optimize PKO's -+ * internal memory. -+ */ -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX) -+ || OCTEON_IS_MODEL(OCTEON_CN56XX) -+ || OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ int num_interfaces = cvmx_helper_get_number_of_interfaces(); -+ int last_port = -+ cvmx_helper_get_last_ipd_port(num_interfaces - 1); -+ int max_queues = -+ cvmx_pko_get_base_queue(last_port) + -+ cvmx_pko_get_num_queues(last_port); -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { -+ if (max_queues <= 32) -+ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2); -+ else if (max_queues <= 64) -+ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1); -+ } else { -+ if (max_queues <= 64) -+ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2); -+ else if (max_queues <= 128) -+ cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1); -+ } -+ } -+} -+ -+/** -+ * This function does per-core initialization required by the PKO routines. -+ * This must be called on all cores that will do packet output, and must -+ * be called after the FPA has been initialized and filled with pages. -+ * -+ * Returns 0 on success -+ * !0 on failure -+ */ -+int cvmx_pko_initialize_local(void) -+{ -+ /* Nothing to do */ -+ return 0; -+} -+ -+/** -+ * Enables the packet output hardware. It must already be -+ * configured. -+ */ -+void cvmx_pko_enable(void) -+{ -+ union cvmx_pko_reg_flags flags; -+ -+ flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); -+ if (flags.s.ena_pko) -+ cvmx_dprintf -+ ("Warning: Enabling PKO when PKO already enabled.\n"); -+ -+ flags.s.ena_dwb = 1; -+ flags.s.ena_pko = 1; -+ /* -+ * always enable big endian for 3-word command. Does nothing -+ * for 2-word. -+ */ -+ flags.s.store_be = 1; -+ cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64); -+} -+ -+/** -+ * Disables the packet output. Does not affect any configuration. -+ */ -+void cvmx_pko_disable(void) -+{ -+ union cvmx_pko_reg_flags pko_reg_flags; -+ pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); -+ pko_reg_flags.s.ena_pko = 0; -+ cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); -+} -+ -+ -+/** -+ * Reset the packet output. -+ */ -+static void __cvmx_pko_reset(void) -+{ -+ union cvmx_pko_reg_flags pko_reg_flags; -+ pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS); -+ pko_reg_flags.s.reset = 1; -+ cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); -+} -+ -+/** -+ * Shutdown and free resources required by packet output. -+ */ -+void cvmx_pko_shutdown(void) -+{ -+ union cvmx_pko_mem_queue_ptrs config; -+ int queue; -+ -+ cvmx_pko_disable(); -+ -+ for (queue = 0; queue < CVMX_PKO_MAX_OUTPUT_QUEUES; queue++) { -+ config.u64 = 0; -+ config.s.tail = 1; -+ config.s.index = 0; -+ config.s.port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID; -+ config.s.queue = queue & 0x7f; -+ config.s.qos_mask = 0; -+ config.s.buf_ptr = 0; -+ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ union cvmx_pko_reg_queue_ptrs1 config1; -+ config1.u64 = 0; -+ config1.s.qid7 = queue >> 7; -+ cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); -+ } -+ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); -+ cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue)); -+ } -+ __cvmx_pko_reset(); -+} -+ -+/** -+ * Configure a output port and the associated queues for use. -+ * -+ * @port: Port to configure. -+ * @base_queue: First queue number to associate with this port. -+ * @num_queues: Number of queues to associate with this port -+ * @priority: Array of priority levels for each queue. Values are -+ * allowed to be 0-8. A value of 8 get 8 times the traffic -+ * of a value of 1. A value of 0 indicates that no rounds -+ * will be participated in. These priorities can be changed -+ * on the fly while the pko is enabled. A priority of 9 -+ * indicates that static priority should be used. If static -+ * priority is used all queues with static priority must be -+ * contiguous starting at the base_queue, and lower numbered -+ * queues have higher priority than higher numbered queues. -+ * There must be num_queues elements in the array. -+ */ -+cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, -+ uint64_t num_queues, -+ const uint64_t priority[]) -+{ -+ cvmx_pko_status_t result_code; -+ uint64_t queue; -+ union cvmx_pko_mem_queue_ptrs config; -+ union cvmx_pko_reg_queue_ptrs1 config1; -+ int static_priority_base = -1; -+ int static_priority_end = -1; -+ -+ if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS) -+ && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) { -+ cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n", -+ (unsigned long long)port); -+ return CVMX_PKO_INVALID_PORT; -+ } -+ -+ if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES) { -+ cvmx_dprintf -+ ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n", -+ (unsigned long long)(base_queue + num_queues)); -+ return CVMX_PKO_INVALID_QUEUE; -+ } -+ -+ if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { -+ /* -+ * Validate the static queue priority setup and set -+ * static_priority_base and static_priority_end -+ * accordingly. -+ */ -+ for (queue = 0; queue < num_queues; queue++) { -+ /* Find first queue of static priority */ -+ if (static_priority_base == -1 -+ && priority[queue] == -+ CVMX_PKO_QUEUE_STATIC_PRIORITY) -+ static_priority_base = queue; -+ /* Find last queue of static priority */ -+ if (static_priority_base != -1 -+ && static_priority_end == -1 -+ && priority[queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY -+ && queue) -+ static_priority_end = queue - 1; -+ else if (static_priority_base != -1 -+ && static_priority_end == -1 -+ && queue == num_queues - 1) -+ /* all queues are static priority */ -+ static_priority_end = queue; -+ /* -+ * Check to make sure all static priority -+ * queues are contiguous. Also catches some -+ * cases of static priorites not starting at -+ * queue 0. -+ */ -+ if (static_priority_end != -1 -+ && (int)queue > static_priority_end -+ && priority[queue] == -+ CVMX_PKO_QUEUE_STATIC_PRIORITY) { -+ cvmx_dprintf("ERROR: cvmx_pko_config_port: " -+ "Static priority queues aren't " -+ "contiguous or don't start at " -+ "base queue. q: %d, eq: %d\n", -+ (int)queue, static_priority_end); -+ return CVMX_PKO_INVALID_PRIORITY; -+ } -+ } -+ if (static_priority_base > 0) { -+ cvmx_dprintf("ERROR: cvmx_pko_config_port: Static " -+ "priority queues don't start at base " -+ "queue. sq: %d\n", -+ static_priority_base); -+ return CVMX_PKO_INVALID_PRIORITY; -+ } -+#if 0 -+ cvmx_dprintf("Port %d: Static priority queue base: %d, " -+ "end: %d\n", port, -+ static_priority_base, static_priority_end); -+#endif -+ } -+ /* -+ * At this point, static_priority_base and static_priority_end -+ * are either both -1, or are valid start/end queue -+ * numbers. -+ */ -+ -+ result_code = CVMX_PKO_SUCCESS; -+ -+#ifdef PKO_DEBUG -+ cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues, -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0, -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1); -+#endif -+ -+ for (queue = 0; queue < num_queues; queue++) { -+ uint64_t *buf_ptr = NULL; -+ -+ config1.u64 = 0; -+ config1.s.idx3 = queue >> 3; -+ config1.s.qid7 = (base_queue + queue) >> 7; -+ -+ config.u64 = 0; -+ config.s.tail = queue == (num_queues - 1); -+ config.s.index = queue; -+ config.s.port = port; -+ config.s.queue = base_queue + queue; -+ -+ if (!cvmx_octeon_is_pass1()) { -+ config.s.static_p = static_priority_base >= 0; -+ config.s.static_q = (int)queue <= static_priority_end; -+ config.s.s_tail = (int)queue == static_priority_end; -+ } -+ /* -+ * Convert the priority into an enable bit field. Try -+ * to space the bits out evenly so the packet don't -+ * get grouped up -+ */ -+ switch ((int)priority[queue]) { -+ case 0: -+ config.s.qos_mask = 0x00; -+ break; -+ case 1: -+ config.s.qos_mask = 0x01; -+ break; -+ case 2: -+ config.s.qos_mask = 0x11; -+ break; -+ case 3: -+ config.s.qos_mask = 0x49; -+ break; -+ case 4: -+ config.s.qos_mask = 0x55; -+ break; -+ case 5: -+ config.s.qos_mask = 0x57; -+ break; -+ case 6: -+ config.s.qos_mask = 0x77; -+ break; -+ case 7: -+ config.s.qos_mask = 0x7f; -+ break; -+ case 8: -+ config.s.qos_mask = 0xff; -+ break; -+ case CVMX_PKO_QUEUE_STATIC_PRIORITY: -+ /* Pass 1 will fall through to the error case */ -+ if (!cvmx_octeon_is_pass1()) { -+ config.s.qos_mask = 0xff; -+ break; -+ } -+ default: -+ cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid " -+ "priority %llu\n", -+ (unsigned long long)priority[queue]); -+ config.s.qos_mask = 0xff; -+ result_code = CVMX_PKO_INVALID_PRIORITY; -+ break; -+ } -+ -+ if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) { -+ cvmx_cmd_queue_result_t cmd_res = -+ cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO -+ (base_queue + queue), -+ CVMX_PKO_MAX_QUEUE_DEPTH, -+ CVMX_FPA_OUTPUT_BUFFER_POOL, -+ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE -+ - -+ CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST -+ * 8); -+ if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) { -+ switch (cmd_res) { -+ case CVMX_CMD_QUEUE_NO_MEMORY: -+ cvmx_dprintf("ERROR: " -+ "cvmx_pko_config_port: " -+ "Unable to allocate " -+ "output buffer.\n"); -+ return CVMX_PKO_NO_MEMORY; -+ case CVMX_CMD_QUEUE_ALREADY_SETUP: -+ cvmx_dprintf -+ ("ERROR: cvmx_pko_config_port: Port already setup.\n"); -+ return CVMX_PKO_PORT_ALREADY_SETUP; -+ case CVMX_CMD_QUEUE_INVALID_PARAM: -+ default: -+ cvmx_dprintf -+ ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n"); -+ return CVMX_PKO_CMD_QUEUE_INIT_ERROR; -+ } -+ } -+ -+ buf_ptr = -+ (uint64_t *) -+ cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO -+ (base_queue + queue)); -+ config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr); -+ } else -+ config.s.buf_ptr = 0; -+ -+ CVMX_SYNCWS; -+ -+ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) -+ cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64); -+ cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64); -+ } -+ -+ return result_code; -+} -+ -+#ifdef PKO_DEBUG -+/** -+ * Show map of ports -> queues for different cores. -+ */ -+void cvmx_pko_show_queue_map() -+{ -+ int core, port; -+ int pko_output_ports = 36; -+ -+ cvmx_dprintf("port"); -+ for (port = 0; port < pko_output_ports; port++) -+ cvmx_dprintf("%3d ", port); -+ cvmx_dprintf("\n"); -+ -+ for (core = 0; core < CVMX_MAX_CORES; core++) { -+ cvmx_dprintf("\n%2d: ", core); -+ for (port = 0; port < pko_output_ports; port++) { -+ cvmx_dprintf("%3d ", -+ cvmx_pko_get_base_queue_per_core(port, -+ core)); -+ } -+ } -+ cvmx_dprintf("\n"); -+} -+#endif -+ -+/** -+ * Rate limit a PKO port to a max packets/sec. This function is only -+ * supported on CN51XX and higher, excluding CN58XX. -+ * -+ * @port: Port to rate limit -+ * @packets_s: Maximum packet/sec -+ * @burst: Maximum number of packets to burst in a row before rate -+ * limiting cuts in. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst) -+{ -+ union cvmx_pko_mem_port_rate0 pko_mem_port_rate0; -+ union cvmx_pko_mem_port_rate1 pko_mem_port_rate1; -+ -+ pko_mem_port_rate0.u64 = 0; -+ pko_mem_port_rate0.s.pid = port; -+ pko_mem_port_rate0.s.rate_pkt = -+ cvmx_sysinfo_get()->cpu_clock_hz / packets_s / 16; -+ /* No cost per word since we are limited by packets/sec, not bits/sec */ -+ pko_mem_port_rate0.s.rate_word = 0; -+ -+ pko_mem_port_rate1.u64 = 0; -+ pko_mem_port_rate1.s.pid = port; -+ pko_mem_port_rate1.s.rate_lim = -+ ((uint64_t) pko_mem_port_rate0.s.rate_pkt * burst) >> 8; -+ -+ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64); -+ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64); -+ return 0; -+} -+ -+/** -+ * Rate limit a PKO port to a max bits/sec. This function is only -+ * supported on CN51XX and higher, excluding CN58XX. -+ * -+ * @port: Port to rate limit -+ * @bits_s: PKO rate limit in bits/sec -+ * @burst: Maximum number of bits to burst before rate -+ * limiting cuts in. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst) -+{ -+ union cvmx_pko_mem_port_rate0 pko_mem_port_rate0; -+ union cvmx_pko_mem_port_rate1 pko_mem_port_rate1; -+ uint64_t clock_rate = cvmx_sysinfo_get()->cpu_clock_hz; -+ uint64_t tokens_per_bit = clock_rate * 16 / bits_s; -+ -+ pko_mem_port_rate0.u64 = 0; -+ pko_mem_port_rate0.s.pid = port; -+ /* -+ * Each packet has a 12 bytes of interframe gap, an 8 byte -+ * preamble, and a 4 byte CRC. These are not included in the -+ * per word count. Multiply by 8 to covert to bits and divide -+ * by 256 for limit granularity. -+ */ -+ pko_mem_port_rate0.s.rate_pkt = (12 + 8 + 4) * 8 * tokens_per_bit / 256; -+ /* Each 8 byte word has 64bits */ -+ pko_mem_port_rate0.s.rate_word = 64 * tokens_per_bit; -+ -+ pko_mem_port_rate1.u64 = 0; -+ pko_mem_port_rate1.s.pid = port; -+ pko_mem_port_rate1.s.rate_lim = tokens_per_bit * burst / 256; -+ -+ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64); -+ cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64); -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pko.h -@@ -0,0 +1,610 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * Interface to the hardware Packet Output unit. -+ * -+ * Starting with SDK 1.7.0, the PKO output functions now support -+ * two types of locking. CVMX_PKO_LOCK_ATOMIC_TAG continues to -+ * function similarly to previous SDKs by using POW atomic tags -+ * to preserve ordering and exclusivity. As a new option, you -+ * can now pass CVMX_PKO_LOCK_CMD_QUEUE which uses a ll/sc -+ * memory based locking instead. This locking has the advantage -+ * of not affecting the tag state but doesn't preserve packet -+ * ordering. CVMX_PKO_LOCK_CMD_QUEUE is appropriate in most -+ * generic code while CVMX_PKO_LOCK_CMD_QUEUE should be used -+ * with hand tuned fast path code. -+ * -+ * Some of other SDK differences visible to the command command -+ * queuing: -+ * - PKO indexes are no longer stored in the FAU. A large -+ * percentage of the FAU register block used to be tied up -+ * maintaining PKO queue pointers. These are now stored in a -+ * global named block. -+ * - The PKO use_locking parameter can now have a global -+ * effect. Since all application use the same named block, -+ * queue locking correctly applies across all operating -+ * systems when using CVMX_PKO_LOCK_CMD_QUEUE. -+ * - PKO 3 word commands are now supported. Use -+ * cvmx_pko_send_packet_finish3(). -+ * -+ */ -+ -+#ifndef __CVMX_PKO_H__ -+#define __CVMX_PKO_H__ -+ -+#include "cvmx-fpa.h" -+#include "cvmx-pow.h" -+#include "cvmx-cmd-queue.h" -+#include "cvmx-pko-defs.h" -+ -+/* Adjust the command buffer size by 1 word so that in the case of using only -+ * two word PKO commands no command words stradle buffers. The useful values -+ * for this are 0 and 1. */ -+#define CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST (1) -+ -+#define CVMX_PKO_MAX_OUTPUT_QUEUES_STATIC 256 -+#define CVMX_PKO_MAX_OUTPUT_QUEUES ((OCTEON_IS_MODEL(OCTEON_CN31XX) || \ -+ OCTEON_IS_MODEL(OCTEON_CN3010) || OCTEON_IS_MODEL(OCTEON_CN3005) || \ -+ OCTEON_IS_MODEL(OCTEON_CN50XX)) ? 32 : \ -+ (OCTEON_IS_MODEL(OCTEON_CN58XX) || \ -+ OCTEON_IS_MODEL(OCTEON_CN56XX)) ? 256 : 128) -+#define CVMX_PKO_NUM_OUTPUT_PORTS 40 -+/* use this for queues that are not used */ -+#define CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID 63 -+#define CVMX_PKO_QUEUE_STATIC_PRIORITY 9 -+#define CVMX_PKO_ILLEGAL_QUEUE 0xFFFF -+#define CVMX_PKO_MAX_QUEUE_DEPTH 0 -+ -+typedef enum { -+ CVMX_PKO_SUCCESS, -+ CVMX_PKO_INVALID_PORT, -+ CVMX_PKO_INVALID_QUEUE, -+ CVMX_PKO_INVALID_PRIORITY, -+ CVMX_PKO_NO_MEMORY, -+ CVMX_PKO_PORT_ALREADY_SETUP, -+ CVMX_PKO_CMD_QUEUE_INIT_ERROR -+} cvmx_pko_status_t; -+ -+/** -+ * This enumeration represents the differnet locking modes supported by PKO. -+ */ -+typedef enum { -+ /* -+ * PKO doesn't do any locking. It is the responsibility of the -+ * application to make sure that no other core is accessing -+ * the same queue at the smae time -+ */ -+ CVMX_PKO_LOCK_NONE = 0, -+ /* -+ * PKO performs an atomic tagswitch to insure exclusive access -+ * to the output queue. This will maintain packet ordering on -+ * output. -+ */ -+ CVMX_PKO_LOCK_ATOMIC_TAG = 1, -+ /* -+ * PKO uses the common command queue locks to insure exclusive -+ * access to the output queue. This is a memory based -+ * ll/sc. This is the most portable locking mechanism. -+ */ -+ CVMX_PKO_LOCK_CMD_QUEUE = 2, -+} cvmx_pko_lock_t; -+ -+typedef struct { -+ uint32_t packets; -+ uint64_t octets; -+ uint64_t doorbell; -+} cvmx_pko_port_status_t; -+ -+/** -+ * This structure defines the address to use on a packet enqueue -+ */ -+typedef union { -+ uint64_t u64; -+ struct { -+ /* Must CVMX_IO_SEG */ -+ uint64_t mem_space:2; -+ /* Must be zero */ -+ uint64_t reserved:13; -+ /* Must be one */ -+ uint64_t is_io:1; -+ /* The ID of the device on the non-coherent bus */ -+ uint64_t did:8; -+ /* Must be zero */ -+ uint64_t reserved2:4; -+ /* Must be zero */ -+ uint64_t reserved3:18; -+ /* -+ * The hardware likes to have the output port in -+ * addition to the output queue, -+ */ -+ uint64_t port:6; -+ /* -+ * The output queue to send the packet to (0-127 are -+ * legal) -+ */ -+ uint64_t queue:9; -+ /* Must be zero */ -+ uint64_t reserved4:3; -+ } s; -+} cvmx_pko_doorbell_address_t; -+ -+/** -+ * Structure of the first packet output command word. -+ */ -+typedef union { -+ uint64_t u64; -+ struct { -+ /* -+ * The size of the reg1 operation - could be 8, 16, -+ * 32, or 64 bits. -+ */ -+ uint64_t size1:2; -+ /* -+ * The size of the reg0 operation - could be 8, 16, -+ * 32, or 64 bits. -+ */ -+ uint64_t size0:2; -+ /* -+ * If set, subtract 1, if clear, subtract packet -+ * size. -+ */ -+ uint64_t subone1:1; -+ /* -+ * The register, subtract will be done if reg1 is -+ * non-zero. -+ */ -+ uint64_t reg1:11; -+ /* If set, subtract 1, if clear, subtract packet size */ -+ uint64_t subone0:1; -+ /* The register, subtract will be done if reg0 is non-zero */ -+ uint64_t reg0:11; -+ /* -+ * When set, interpret segment pointer and segment -+ * bytes in little endian order. -+ */ -+ uint64_t le:1; -+ /* -+ * When set, packet data not allocated in L2 cache by -+ * PKO. -+ */ -+ uint64_t n2:1; -+ /* -+ * If set and rsp is set, word3 contains a pointer to -+ * a work queue entry. -+ */ -+ uint64_t wqp:1; -+ /* If set, the hardware will send a response when done */ -+ uint64_t rsp:1; -+ /* -+ * If set, the supplied pkt_ptr is really a pointer to -+ * a list of pkt_ptr's. -+ */ -+ uint64_t gather:1; -+ /* -+ * If ipoffp1 is non zero, (ipoffp1-1) is the number -+ * of bytes to IP header, and the hardware will -+ * calculate and insert the UDP/TCP checksum. -+ */ -+ uint64_t ipoffp1:7; -+ /* -+ * If set, ignore the I bit (force to zero) from all -+ * pointer structures. -+ */ -+ uint64_t ignore_i:1; -+ /* -+ * If clear, the hardware will attempt to free the -+ * buffers containing the packet. -+ */ -+ uint64_t dontfree:1; -+ /* -+ * The total number of segs in the packet, if gather -+ * set, also gather list length. -+ */ -+ uint64_t segs:6; -+ /* Including L2, but no trailing CRC */ -+ uint64_t total_bytes:16; -+ } s; -+} cvmx_pko_command_word0_t; -+ -+/* CSR typedefs have been moved to cvmx-csr-*.h */ -+ -+/** -+ * Definition of internal state for Packet output processing -+ */ -+typedef struct { -+ /* ptr to start of buffer, offset kept in FAU reg */ -+ uint64_t *start_ptr; -+} cvmx_pko_state_elem_t; -+ -+/** -+ * Call before any other calls to initialize the packet -+ * output system. -+ */ -+extern void cvmx_pko_initialize_global(void); -+extern int cvmx_pko_initialize_local(void); -+ -+/** -+ * Enables the packet output hardware. It must already be -+ * configured. -+ */ -+extern void cvmx_pko_enable(void); -+ -+/** -+ * Disables the packet output. Does not affect any configuration. -+ */ -+extern void cvmx_pko_disable(void); -+ -+/** -+ * Shutdown and free resources required by packet output. -+ */ -+ -+extern void cvmx_pko_shutdown(void); -+ -+/** -+ * Configure a output port and the associated queues for use. -+ * -+ * @port: Port to configure. -+ * @base_queue: First queue number to associate with this port. -+ * @num_queues: Number of queues t oassociate with this port -+ * @priority: Array of priority levels for each queue. Values are -+ * allowed to be 1-8. A value of 8 get 8 times the traffic -+ * of a value of 1. There must be num_queues elements in the -+ * array. -+ */ -+extern cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, -+ uint64_t base_queue, -+ uint64_t num_queues, -+ const uint64_t priority[]); -+ -+/** -+ * Ring the packet output doorbell. This tells the packet -+ * output hardware that "len" command words have been added -+ * to its pending list. This command includes the required -+ * CVMX_SYNCWS before the doorbell ring. -+ * -+ * @port: Port the packet is for -+ * @queue: Queue the packet is for -+ * @len: Length of the command in 64 bit words -+ */ -+static inline void cvmx_pko_doorbell(uint64_t port, uint64_t queue, -+ uint64_t len) -+{ -+ cvmx_pko_doorbell_address_t ptr; -+ -+ ptr.u64 = 0; -+ ptr.s.mem_space = CVMX_IO_SEG; -+ ptr.s.did = CVMX_OCT_DID_PKT_SEND; -+ ptr.s.is_io = 1; -+ ptr.s.port = port; -+ ptr.s.queue = queue; -+ /* -+ * Need to make sure output queue data is in DRAM before -+ * doorbell write. -+ */ -+ CVMX_SYNCWS; -+ cvmx_write_io(ptr.u64, len); -+} -+ -+/** -+ * Prepare to send a packet. This may initiate a tag switch to -+ * get exclusive access to the output queue structure, and -+ * performs other prep work for the packet send operation. -+ * -+ * cvmx_pko_send_packet_finish() MUST be called after this function is called, -+ * and must be called with the same port/queue/use_locking arguments. -+ * -+ * The use_locking parameter allows the caller to use three -+ * possible locking modes. -+ * - CVMX_PKO_LOCK_NONE -+ * - PKO doesn't do any locking. It is the responsibility -+ * of the application to make sure that no other core -+ * is accessing the same queue at the smae time. -+ * - CVMX_PKO_LOCK_ATOMIC_TAG -+ * - PKO performs an atomic tagswitch to insure exclusive -+ * access to the output queue. This will maintain -+ * packet ordering on output. -+ * - CVMX_PKO_LOCK_CMD_QUEUE -+ * - PKO uses the common command queue locks to insure -+ * exclusive access to the output queue. This is a -+ * memory based ll/sc. This is the most portable -+ * locking mechanism. -+ * -+ * NOTE: If atomic locking is used, the POW entry CANNOT be -+ * descheduled, as it does not contain a valid WQE pointer. -+ * -+ * @port: Port to send it on -+ * @queue: Queue to use -+ * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or -+ * CVMX_PKO_LOCK_CMD_QUEUE -+ */ -+ -+static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, -+ cvmx_pko_lock_t use_locking) -+{ -+ if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) { -+ /* -+ * Must do a full switch here to handle all cases. We -+ * use a fake WQE pointer, as the POW does not access -+ * this memory. The WQE pointer and group are only -+ * used if this work is descheduled, which is not -+ * supported by the -+ * cvmx_pko_send_packet_prepare/cvmx_pko_send_packet_finish -+ * combination. Note that this is a special case in -+ * which these fake values can be used - this is not a -+ * general technique. -+ */ -+ uint32_t tag = -+ CVMX_TAG_SW_BITS_INTERNAL << CVMX_TAG_SW_SHIFT | -+ CVMX_TAG_SUBGROUP_PKO << CVMX_TAG_SUBGROUP_SHIFT | -+ (CVMX_TAG_SUBGROUP_MASK & queue); -+ cvmx_pow_tag_sw_full((cvmx_wqe_t *) cvmx_phys_to_ptr(0x80), tag, -+ CVMX_POW_TAG_TYPE_ATOMIC, 0); -+ } -+} -+ -+/** -+ * Complete packet output. cvmx_pko_send_packet_prepare() must be -+ * called exactly once before this, and the same parameters must be -+ * passed to both cvmx_pko_send_packet_prepare() and -+ * cvmx_pko_send_packet_finish(). -+ * -+ * @port: Port to send it on -+ * @queue: Queue to use -+ * @pko_command: -+ * PKO HW command word -+ * @packet: Packet to send -+ * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or -+ * CVMX_PKO_LOCK_CMD_QUEUE -+ * -+ * Returns returns CVMX_PKO_SUCCESS on success, or error code on -+ * failure of output -+ */ -+static inline cvmx_pko_status_t cvmx_pko_send_packet_finish( -+ uint64_t port, -+ uint64_t queue, -+ cvmx_pko_command_word0_t pko_command, -+ union cvmx_buf_ptr packet, -+ cvmx_pko_lock_t use_locking) -+{ -+ cvmx_cmd_queue_result_t result; -+ if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) -+ cvmx_pow_tag_sw_wait(); -+ result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue), -+ (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), -+ pko_command.u64, packet.u64); -+ if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) { -+ cvmx_pko_doorbell(port, queue, 2); -+ return CVMX_PKO_SUCCESS; -+ } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) -+ || (result == CVMX_CMD_QUEUE_FULL)) { -+ return CVMX_PKO_NO_MEMORY; -+ } else { -+ return CVMX_PKO_INVALID_QUEUE; -+ } -+} -+ -+/** -+ * Complete packet output. cvmx_pko_send_packet_prepare() must be -+ * called exactly once before this, and the same parameters must be -+ * passed to both cvmx_pko_send_packet_prepare() and -+ * cvmx_pko_send_packet_finish(). -+ * -+ * @port: Port to send it on -+ * @queue: Queue to use -+ * @pko_command: -+ * PKO HW command word -+ * @packet: Packet to send -+ * @addr: Plysical address of a work queue entry or physical address -+ * to zero on complete. -+ * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or -+ * CVMX_PKO_LOCK_CMD_QUEUE -+ * -+ * Returns returns CVMX_PKO_SUCCESS on success, or error code on -+ * failure of output -+ */ -+static inline cvmx_pko_status_t cvmx_pko_send_packet_finish3( -+ uint64_t port, -+ uint64_t queue, -+ cvmx_pko_command_word0_t pko_command, -+ union cvmx_buf_ptr packet, -+ uint64_t addr, -+ cvmx_pko_lock_t use_locking) -+{ -+ cvmx_cmd_queue_result_t result; -+ if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) -+ cvmx_pow_tag_sw_wait(); -+ result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue), -+ (use_locking == CVMX_PKO_LOCK_CMD_QUEUE), -+ pko_command.u64, packet.u64, addr); -+ if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) { -+ cvmx_pko_doorbell(port, queue, 3); -+ return CVMX_PKO_SUCCESS; -+ } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY) -+ || (result == CVMX_CMD_QUEUE_FULL)) { -+ return CVMX_PKO_NO_MEMORY; -+ } else { -+ return CVMX_PKO_INVALID_QUEUE; -+ } -+} -+ -+/** -+ * Return the pko output queue associated with a port and a specific core. -+ * In normal mode (PKO lockless operation is disabled), the value returned -+ * is the base queue. -+ * -+ * @port: Port number -+ * @core: Core to get queue for -+ * -+ * Returns Core-specific output queue -+ */ -+static inline int cvmx_pko_get_base_queue_per_core(int port, int core) -+{ -+#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 -+#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 16 -+#endif -+#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 -+#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 16 -+#endif -+ -+ if (port < CVMX_PKO_MAX_PORTS_INTERFACE0) -+ return port * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + core; -+ else if (port >= 16 && port < 16 + CVMX_PKO_MAX_PORTS_INTERFACE1) -+ return CVMX_PKO_MAX_PORTS_INTERFACE0 * -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + (port - -+ 16) * -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + core; -+ else if ((port >= 32) && (port < 36)) -+ return CVMX_PKO_MAX_PORTS_INTERFACE0 * -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + -+ CVMX_PKO_MAX_PORTS_INTERFACE1 * -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + (port - -+ 32) * -+ CVMX_PKO_QUEUES_PER_PORT_PCI; -+ else if ((port >= 36) && (port < 40)) -+ return CVMX_PKO_MAX_PORTS_INTERFACE0 * -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + -+ CVMX_PKO_MAX_PORTS_INTERFACE1 * -+ CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + -+ 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + (port - -+ 36) * -+ CVMX_PKO_QUEUES_PER_PORT_LOOP; -+ else -+ /* Given the limit on the number of ports we can map to -+ * CVMX_MAX_OUTPUT_QUEUES_STATIC queues (currently 256, -+ * divided among all cores), the remaining unmapped ports -+ * are assigned an illegal queue number */ -+ return CVMX_PKO_ILLEGAL_QUEUE; -+} -+ -+/** -+ * For a given port number, return the base pko output queue -+ * for the port. -+ * -+ * @port: Port number -+ * Returns Base output queue -+ */ -+static inline int cvmx_pko_get_base_queue(int port) -+{ -+ return cvmx_pko_get_base_queue_per_core(port, 0); -+} -+ -+/** -+ * For a given port number, return the number of pko output queues. -+ * -+ * @port: Port number -+ * Returns Number of output queues -+ */ -+static inline int cvmx_pko_get_num_queues(int port) -+{ -+ if (port < 16) -+ return CVMX_PKO_QUEUES_PER_PORT_INTERFACE0; -+ else if (port < 32) -+ return CVMX_PKO_QUEUES_PER_PORT_INTERFACE1; -+ else if (port < 36) -+ return CVMX_PKO_QUEUES_PER_PORT_PCI; -+ else if (port < 40) -+ return CVMX_PKO_QUEUES_PER_PORT_LOOP; -+ else -+ return 0; -+} -+ -+/** -+ * Get the status counters for a port. -+ * -+ * @port_num: Port number to get statistics for. -+ * @clear: Set to 1 to clear the counters after they are read -+ * @status: Where to put the results. -+ */ -+static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, -+ cvmx_pko_port_status_t *status) -+{ -+ union cvmx_pko_reg_read_idx pko_reg_read_idx; -+ union cvmx_pko_mem_count0 pko_mem_count0; -+ union cvmx_pko_mem_count1 pko_mem_count1; -+ -+ pko_reg_read_idx.u64 = 0; -+ pko_reg_read_idx.s.index = port_num; -+ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); -+ -+ pko_mem_count0.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT0); -+ status->packets = pko_mem_count0.s.count; -+ if (clear) { -+ pko_mem_count0.s.count = port_num; -+ cvmx_write_csr(CVMX_PKO_MEM_COUNT0, pko_mem_count0.u64); -+ } -+ -+ pko_mem_count1.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT1); -+ status->octets = pko_mem_count1.s.count; -+ if (clear) { -+ pko_mem_count1.s.count = port_num; -+ cvmx_write_csr(CVMX_PKO_MEM_COUNT1, pko_mem_count1.u64); -+ } -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ union cvmx_pko_mem_debug9 debug9; -+ pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); -+ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); -+ debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9); -+ status->doorbell = debug9.cn38xx.doorbell; -+ } else { -+ union cvmx_pko_mem_debug8 debug8; -+ pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num); -+ cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64); -+ debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8); -+ status->doorbell = debug8.cn58xx.doorbell; -+ } -+} -+ -+/** -+ * Rate limit a PKO port to a max packets/sec. This function is only -+ * supported on CN57XX, CN56XX, CN55XX, and CN54XX. -+ * -+ * @port: Port to rate limit -+ * @packets_s: Maximum packet/sec -+ * @burst: Maximum number of packets to burst in a row before rate -+ * limiting cuts in. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst); -+ -+/** -+ * Rate limit a PKO port to a max bits/sec. This function is only -+ * supported on CN57XX, CN56XX, CN55XX, and CN54XX. -+ * -+ * @port: Port to rate limit -+ * @bits_s: PKO rate limit in bits/sec -+ * @burst: Maximum number of bits to burst before rate -+ * limiting cuts in. -+ * -+ * Returns Zero on success, negative on failure -+ */ -+extern int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst); -+ -+#endif /* __CVMX_PKO_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-pow.h -@@ -0,0 +1,1982 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * Interface to the hardware Packet Order / Work unit. -+ * -+ * New, starting with SDK 1.7.0, cvmx-pow supports a number of -+ * extended consistency checks. The define -+ * CVMX_ENABLE_POW_CHECKS controls the runtime insertion of POW -+ * internal state checks to find common programming errors. If -+ * CVMX_ENABLE_POW_CHECKS is not defined, checks are by default -+ * enabled. For example, cvmx-pow will check for the following -+ * program errors or POW state inconsistency. -+ * - Requesting a POW operation with an active tag switch in -+ * progress. -+ * - Waiting for a tag switch to complete for an excessively -+ * long period. This is normally a sign of an error in locking -+ * causing deadlock. -+ * - Illegal tag switches from NULL_NULL. -+ * - Illegal tag switches from NULL. -+ * - Illegal deschedule request. -+ * - WQE pointer not matching the one attached to the core by -+ * the POW. -+ * -+ */ -+ -+#ifndef __CVMX_POW_H__ -+#define __CVMX_POW_H__ -+ -+#include -+ -+#include "cvmx-scratch.h" -+#include "cvmx-wqe.h" -+ -+/* Default to having all POW constancy checks turned on */ -+#ifndef CVMX_ENABLE_POW_CHECKS -+#define CVMX_ENABLE_POW_CHECKS 1 -+#endif -+ -+enum cvmx_pow_tag_type { -+ /* Tag ordering is maintained */ -+ CVMX_POW_TAG_TYPE_ORDERED = 0L, -+ /* Tag ordering is maintained, and at most one PP has the tag */ -+ CVMX_POW_TAG_TYPE_ATOMIC = 1L, -+ /* -+ * The work queue entry from the order - NEVER tag switch from -+ * NULL to NULL -+ */ -+ CVMX_POW_TAG_TYPE_NULL = 2L, -+ /* A tag switch to NULL, and there is no space reserved in POW -+ * - NEVER tag switch to NULL_NULL -+ * - NEVER tag switch from NULL_NULL -+ * - NULL_NULL is entered at the beginning of time and on a deschedule. -+ * - NULL_NULL can be exited by a new work request. A NULL_SWITCH -+ * load can also switch the state to NULL -+ */ -+ CVMX_POW_TAG_TYPE_NULL_NULL = 3L -+}; -+ -+/** -+ * Wait flag values for pow functions. -+ */ -+typedef enum { -+ CVMX_POW_WAIT = 1, -+ CVMX_POW_NO_WAIT = 0, -+} cvmx_pow_wait_t; -+ -+/** -+ * POW tag operations. These are used in the data stored to the POW. -+ */ -+typedef enum { -+ /* -+ * switch the tag (only) for this PP -+ * - the previous tag should be non-NULL in this case -+ * - tag switch response required -+ * - fields used: op, type, tag -+ */ -+ CVMX_POW_TAG_OP_SWTAG = 0L, -+ /* -+ * switch the tag for this PP, with full information -+ * - this should be used when the previous tag is NULL -+ * - tag switch response required -+ * - fields used: address, op, grp, type, tag -+ */ -+ CVMX_POW_TAG_OP_SWTAG_FULL = 1L, -+ /* -+ * switch the tag (and/or group) for this PP and de-schedule -+ * - OK to keep the tag the same and only change the group -+ * - fields used: op, no_sched, grp, type, tag -+ */ -+ CVMX_POW_TAG_OP_SWTAG_DESCH = 2L, -+ /* -+ * just de-schedule -+ * - fields used: op, no_sched -+ */ -+ CVMX_POW_TAG_OP_DESCH = 3L, -+ /* -+ * create an entirely new work queue entry -+ * - fields used: address, op, qos, grp, type, tag -+ */ -+ CVMX_POW_TAG_OP_ADDWQ = 4L, -+ /* -+ * just update the work queue pointer and grp for this PP -+ * - fields used: address, op, grp -+ */ -+ CVMX_POW_TAG_OP_UPDATE_WQP_GRP = 5L, -+ /* -+ * set the no_sched bit on the de-schedule list -+ * -+ * - does nothing if the selected entry is not on the -+ * de-schedule list -+ * -+ * - does nothing if the stored work queue pointer does not -+ * match the address field -+ * -+ * - fields used: address, index, op -+ * -+ * Before issuing a *_NSCHED operation, SW must guarantee -+ * that all prior deschedules and set/clr NSCHED operations -+ * are complete and all prior switches are complete. The -+ * hardware provides the opsdone bit and swdone bit for SW -+ * polling. After issuing a *_NSCHED operation, SW must -+ * guarantee that the set/clr NSCHED is complete before any -+ * subsequent operations. -+ */ -+ CVMX_POW_TAG_OP_SET_NSCHED = 6L, -+ /* -+ * clears the no_sched bit on the de-schedule list -+ * -+ * - does nothing if the selected entry is not on the -+ * de-schedule list -+ * -+ * - does nothing if the stored work queue pointer does not -+ * match the address field -+ * -+ * - fields used: address, index, op -+ * -+ * Before issuing a *_NSCHED operation, SW must guarantee that -+ * all prior deschedules and set/clr NSCHED operations are -+ * complete and all prior switches are complete. The hardware -+ * provides the opsdone bit and swdone bit for SW -+ * polling. After issuing a *_NSCHED operation, SW must -+ * guarantee that the set/clr NSCHED is complete before any -+ * subsequent operations. -+ */ -+ CVMX_POW_TAG_OP_CLR_NSCHED = 7L, -+ /* do nothing */ -+ CVMX_POW_TAG_OP_NOP = 15L -+} cvmx_pow_tag_op_t; -+ -+/** -+ * This structure defines the store data on a store to POW -+ */ -+typedef union { -+ uint64_t u64; -+ struct { -+ /* -+ * Don't reschedule this entry. no_sched is used for -+ * CVMX_POW_TAG_OP_SWTAG_DESCH and -+ * CVMX_POW_TAG_OP_DESCH -+ */ -+ uint64_t no_sched:1; -+ uint64_t unused:2; -+ /* Tontains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */ -+ uint64_t index:13; -+ /* The operation to perform */ -+ cvmx_pow_tag_op_t op:4; -+ uint64_t unused2:2; -+ /* -+ * The QOS level for the packet. qos is only used for -+ * CVMX_POW_TAG_OP_ADDWQ -+ */ -+ uint64_t qos:3; -+ /* -+ * The group that the work queue entry will be -+ * scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ, -+ * CVMX_POW_TAG_OP_SWTAG_FULL, -+ * CVMX_POW_TAG_OP_SWTAG_DESCH, and -+ * CVMX_POW_TAG_OP_UPDATE_WQP_GRP -+ */ -+ uint64_t grp:4; -+ /* -+ * The type of the tag. type is used for everything -+ * except CVMX_POW_TAG_OP_DESCH, -+ * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and -+ * CVMX_POW_TAG_OP_*_NSCHED -+ */ -+ uint64_t type:3; -+ /* -+ * The actual tag. tag is used for everything except -+ * CVMX_POW_TAG_OP_DESCH, -+ * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and -+ * CVMX_POW_TAG_OP_*_NSCHED -+ */ -+ uint64_t tag:32; -+ } s; -+} cvmx_pow_tag_req_t; -+ -+/** -+ * This structure describes the address to load stuff from POW -+ */ -+typedef union { -+ uint64_t u64; -+ -+ /** -+ * Address for new work request loads (did<2:0> == 0) -+ */ -+ struct { -+ /* Mips64 address region. Should be CVMX_IO_SEG */ -+ uint64_t mem_region:2; -+ /* Must be zero */ -+ uint64_t reserved_49_61:13; -+ /* Must be one */ -+ uint64_t is_io:1; -+ /* the ID of POW -- did<2:0> == 0 in this case */ -+ uint64_t did:8; -+ /* Must be zero */ -+ uint64_t reserved_4_39:36; -+ /* -+ * If set, don't return load response until work is -+ * available. -+ */ -+ uint64_t wait:1; -+ /* Must be zero */ -+ uint64_t reserved_0_2:3; -+ } swork; -+ -+ /** -+ * Address for loads to get POW internal status -+ */ -+ struct { -+ /* Mips64 address region. Should be CVMX_IO_SEG */ -+ uint64_t mem_region:2; -+ /* Must be zero */ -+ uint64_t reserved_49_61:13; -+ /* Must be one */ -+ uint64_t is_io:1; -+ /* the ID of POW -- did<2:0> == 1 in this case */ -+ uint64_t did:8; -+ /* Must be zero */ -+ uint64_t reserved_10_39:30; -+ /* The core id to get status for */ -+ uint64_t coreid:4; -+ /* -+ * If set and get_cur is set, return reverse tag-list -+ * pointer rather than forward tag-list pointer. -+ */ -+ uint64_t get_rev:1; -+ /* -+ * If set, return current status rather than pending -+ * status. -+ */ -+ uint64_t get_cur:1; -+ /* -+ * If set, get the work-queue pointer rather than -+ * tag/type. -+ */ -+ uint64_t get_wqp:1; -+ /* Must be zero */ -+ uint64_t reserved_0_2:3; -+ } sstatus; -+ -+ /** -+ * Address for memory loads to get POW internal state -+ */ -+ struct { -+ /* Mips64 address region. Should be CVMX_IO_SEG */ -+ uint64_t mem_region:2; -+ /* Must be zero */ -+ uint64_t reserved_49_61:13; -+ /* Must be one */ -+ uint64_t is_io:1; -+ /* the ID of POW -- did<2:0> == 2 in this case */ -+ uint64_t did:8; -+ /* Must be zero */ -+ uint64_t reserved_16_39:24; -+ /* POW memory index */ -+ uint64_t index:11; -+ /* -+ * If set, return deschedule information rather than -+ * the standard response for work-queue index (invalid -+ * if the work-queue entry is not on the deschedule -+ * list). -+ */ -+ uint64_t get_des:1; -+ /* -+ * If set, get the work-queue pointer rather than -+ * tag/type (no effect when get_des set). -+ */ -+ uint64_t get_wqp:1; -+ /* Must be zero */ -+ uint64_t reserved_0_2:3; -+ } smemload; -+ -+ /** -+ * Address for index/pointer loads -+ */ -+ struct { -+ /* Mips64 address region. Should be CVMX_IO_SEG */ -+ uint64_t mem_region:2; -+ /* Must be zero */ -+ uint64_t reserved_49_61:13; -+ /* Must be one */ -+ uint64_t is_io:1; -+ /* the ID of POW -- did<2:0> == 3 in this case */ -+ uint64_t did:8; -+ /* Must be zero */ -+ uint64_t reserved_9_39:31; -+ /* -+ * when {get_rmt ==0 AND get_des_get_tail == 0}, this -+ * field selects one of eight POW internal-input -+ * queues (0-7), one per QOS level; values 8-15 are -+ * illegal in this case; when {get_rmt ==0 AND -+ * get_des_get_tail == 1}, this field selects one of -+ * 16 deschedule lists (per group); when get_rmt ==1, -+ * this field selects one of 16 memory-input queue -+ * lists. The two memory-input queue lists associated -+ * with each QOS level are: -+ * -+ * - qosgrp = 0, qosgrp = 8: QOS0 -+ * - qosgrp = 1, qosgrp = 9: QOS1 -+ * - qosgrp = 2, qosgrp = 10: QOS2 -+ * - qosgrp = 3, qosgrp = 11: QOS3 -+ * - qosgrp = 4, qosgrp = 12: QOS4 -+ * - qosgrp = 5, qosgrp = 13: QOS5 -+ * - qosgrp = 6, qosgrp = 14: QOS6 -+ * - qosgrp = 7, qosgrp = 15: QOS7 -+ */ -+ uint64_t qosgrp:4; -+ /* -+ * If set and get_rmt is clear, return deschedule list -+ * indexes rather than indexes for the specified qos -+ * level; if set and get_rmt is set, return the tail -+ * pointer rather than the head pointer for the -+ * specified qos level. -+ */ -+ uint64_t get_des_get_tail:1; -+ /* -+ * If set, return remote pointers rather than the -+ * local indexes for the specified qos level. -+ */ -+ uint64_t get_rmt:1; -+ /* Must be zero */ -+ uint64_t reserved_0_2:3; -+ } sindexload; -+ -+ /** -+ * address for NULL_RD request (did<2:0> == 4) when this is read, -+ * HW attempts to change the state to NULL if it is NULL_NULL (the -+ * hardware cannot switch from NULL_NULL to NULL if a POW entry is -+ * not available - software may need to recover by finishing -+ * another piece of work before a POW entry can ever become -+ * available.) -+ */ -+ struct { -+ /* Mips64 address region. Should be CVMX_IO_SEG */ -+ uint64_t mem_region:2; -+ /* Must be zero */ -+ uint64_t reserved_49_61:13; -+ /* Must be one */ -+ uint64_t is_io:1; -+ /* the ID of POW -- did<2:0> == 4 in this case */ -+ uint64_t did:8; -+ /* Must be zero */ -+ uint64_t reserved_0_39:40; -+ } snull_rd; -+} cvmx_pow_load_addr_t; -+ -+/** -+ * This structure defines the response to a load/SENDSINGLE to POW -+ * (except CSR reads) -+ */ -+typedef union { -+ uint64_t u64; -+ -+ /** -+ * Response to new work request loads -+ */ -+ struct { -+ /* -+ * Set when no new work queue entry was returned. * -+ * If there was de-scheduled work, the HW will -+ * definitely return it. When this bit is set, it -+ * could mean either mean: -+ * -+ * - There was no work, or -+ * -+ * - There was no work that the HW could find. This -+ * case can happen, regardless of the wait bit value -+ * in the original request, when there is work in -+ * the IQ's that is too deep down the list. -+ */ -+ uint64_t no_work:1; -+ /* Must be zero */ -+ uint64_t reserved_40_62:23; -+ /* 36 in O1 -- the work queue pointer */ -+ uint64_t addr:40; -+ } s_work; -+ -+ /** -+ * Result for a POW Status Load (when get_cur==0 and get_wqp==0) -+ */ -+ struct { -+ uint64_t reserved_62_63:2; -+ /* Set when there is a pending non-NULL SWTAG or -+ * SWTAG_FULL, and the POW entry has not left the list -+ * for the original tag. */ -+ uint64_t pend_switch:1; -+ /* Set when SWTAG_FULL and pend_switch is set. */ -+ uint64_t pend_switch_full:1; -+ /* -+ * Set when there is a pending NULL SWTAG, or an -+ * implicit switch to NULL. -+ */ -+ uint64_t pend_switch_null:1; -+ /* Set when there is a pending DESCHED or SWTAG_DESCHED. */ -+ uint64_t pend_desched:1; -+ /* -+ * Set when there is a pending SWTAG_DESCHED and -+ * pend_desched is set. -+ */ -+ uint64_t pend_desched_switch:1; -+ /* Set when nosched is desired and pend_desched is set. */ -+ uint64_t pend_nosched:1; -+ /* Set when there is a pending GET_WORK. */ -+ uint64_t pend_new_work:1; -+ /* -+ * When pend_new_work is set, this bit indicates that -+ * the wait bit was set. -+ */ -+ uint64_t pend_new_work_wait:1; -+ /* Set when there is a pending NULL_RD. */ -+ uint64_t pend_null_rd:1; -+ /* Set when there is a pending CLR_NSCHED. */ -+ uint64_t pend_nosched_clr:1; -+ uint64_t reserved_51:1; -+ /* This is the index when pend_nosched_clr is set. */ -+ uint64_t pend_index:11; -+ /* -+ * This is the new_grp when (pend_desched AND -+ * pend_desched_switch) is set. -+ */ -+ uint64_t pend_grp:4; -+ uint64_t reserved_34_35:2; -+ /* -+ * This is the tag type when pend_switch or -+ * (pend_desched AND pend_desched_switch) are set. -+ */ -+ uint64_t pend_type:2; -+ /* -+ * - this is the tag when pend_switch or (pend_desched -+ * AND pend_desched_switch) are set. -+ */ -+ uint64_t pend_tag:32; -+ } s_sstatus0; -+ -+ /** -+ * Result for a POW Status Load (when get_cur==0 and get_wqp==1) -+ */ -+ struct { -+ uint64_t reserved_62_63:2; -+ /* -+ * Set when there is a pending non-NULL SWTAG or -+ * SWTAG_FULL, and the POW entry has not left the list -+ * for the original tag. -+ */ -+ uint64_t pend_switch:1; -+ /* Set when SWTAG_FULL and pend_switch is set. */ -+ uint64_t pend_switch_full:1; -+ /* -+ * Set when there is a pending NULL SWTAG, or an -+ * implicit switch to NULL. -+ */ -+ uint64_t pend_switch_null:1; -+ /* -+ * Set when there is a pending DESCHED or -+ * SWTAG_DESCHED. -+ */ -+ uint64_t pend_desched:1; -+ /* -+ * Set when there is a pending SWTAG_DESCHED and -+ * pend_desched is set. -+ */ -+ uint64_t pend_desched_switch:1; -+ /* Set when nosched is desired and pend_desched is set. */ -+ uint64_t pend_nosched:1; -+ /* Set when there is a pending GET_WORK. */ -+ uint64_t pend_new_work:1; -+ /* -+ * When pend_new_work is set, this bit indicates that -+ * the wait bit was set. -+ */ -+ uint64_t pend_new_work_wait:1; -+ /* Set when there is a pending NULL_RD. */ -+ uint64_t pend_null_rd:1; -+ /* Set when there is a pending CLR_NSCHED. */ -+ uint64_t pend_nosched_clr:1; -+ uint64_t reserved_51:1; -+ /* This is the index when pend_nosched_clr is set. */ -+ uint64_t pend_index:11; -+ /* -+ * This is the new_grp when (pend_desched AND -+ * pend_desched_switch) is set. -+ */ -+ uint64_t pend_grp:4; -+ /* This is the wqp when pend_nosched_clr is set. */ -+ uint64_t pend_wqp:36; -+ } s_sstatus1; -+ -+ /** -+ * Result for a POW Status Load (when get_cur==1, get_wqp==0, and -+ * get_rev==0) -+ */ -+ struct { -+ uint64_t reserved_62_63:2; -+ /* -+ * Points to the next POW entry in the tag list when -+ * tail == 0 (and tag_type is not NULL or NULL_NULL). -+ */ -+ uint64_t link_index:11; -+ /* The POW entry attached to the core. */ -+ uint64_t index:11; -+ /* -+ * The group attached to the core (updated when new -+ * tag list entered on SWTAG_FULL). -+ */ -+ uint64_t grp:4; -+ /* -+ * Set when this POW entry is at the head of its tag -+ * list (also set when in the NULL or NULL_NULL -+ * state). -+ */ -+ uint64_t head:1; -+ /* -+ * Set when this POW entry is at the tail of its tag -+ * list (also set when in the NULL or NULL_NULL -+ * state). -+ */ -+ uint64_t tail:1; -+ /* -+ * The tag type attached to the core (updated when new -+ * tag list entered on SWTAG, SWTAG_FULL, or -+ * SWTAG_DESCHED). -+ */ -+ uint64_t tag_type:2; -+ /* -+ * The tag attached to the core (updated when new tag -+ * list entered on SWTAG, SWTAG_FULL, or -+ * SWTAG_DESCHED). -+ */ -+ uint64_t tag:32; -+ } s_sstatus2; -+ -+ /** -+ * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==1) -+ */ -+ struct { -+ uint64_t reserved_62_63:2; -+ /* -+ * Points to the prior POW entry in the tag list when -+ * head == 0 (and tag_type is not NULL or -+ * NULL_NULL). This field is unpredictable when the -+ * core's state is NULL or NULL_NULL. -+ */ -+ uint64_t revlink_index:11; -+ /* The POW entry attached to the core. */ -+ uint64_t index:11; -+ /* -+ * The group attached to the core (updated when new -+ * tag list entered on SWTAG_FULL). -+ */ -+ uint64_t grp:4; -+ /* Set when this POW entry is at the head of its tag -+ * list (also set when in the NULL or NULL_NULL -+ * state). -+ */ -+ uint64_t head:1; -+ /* -+ * Set when this POW entry is at the tail of its tag -+ * list (also set when in the NULL or NULL_NULL -+ * state). -+ */ -+ uint64_t tail:1; -+ /* -+ * The tag type attached to the core (updated when new -+ * tag list entered on SWTAG, SWTAG_FULL, or -+ * SWTAG_DESCHED). -+ */ -+ uint64_t tag_type:2; -+ /* -+ * The tag attached to the core (updated when new tag -+ * list entered on SWTAG, SWTAG_FULL, or -+ * SWTAG_DESCHED). -+ */ -+ uint64_t tag:32; -+ } s_sstatus3; -+ -+ /** -+ * Result for a POW Status Load (when get_cur==1, get_wqp==1, and -+ * get_rev==0) -+ */ -+ struct { -+ uint64_t reserved_62_63:2; -+ /* -+ * Points to the next POW entry in the tag list when -+ * tail == 0 (and tag_type is not NULL or NULL_NULL). -+ */ -+ uint64_t link_index:11; -+ /* The POW entry attached to the core. */ -+ uint64_t index:11; -+ /* -+ * The group attached to the core (updated when new -+ * tag list entered on SWTAG_FULL). -+ */ -+ uint64_t grp:4; -+ /* -+ * The wqp attached to the core (updated when new tag -+ * list entered on SWTAG_FULL). -+ */ -+ uint64_t wqp:36; -+ } s_sstatus4; -+ -+ /** -+ * Result for a POW Status Load (when get_cur==1, get_wqp==1, and -+ * get_rev==1) -+ */ -+ struct { -+ uint64_t reserved_62_63:2; -+ /* -+ * Points to the prior POW entry in the tag list when -+ * head == 0 (and tag_type is not NULL or -+ * NULL_NULL). This field is unpredictable when the -+ * core's state is NULL or NULL_NULL. -+ */ -+ uint64_t revlink_index:11; -+ /* The POW entry attached to the core. */ -+ uint64_t index:11; -+ /* -+ * The group attached to the core (updated when new -+ * tag list entered on SWTAG_FULL). -+ */ -+ uint64_t grp:4; -+ /* -+ * The wqp attached to the core (updated when new tag -+ * list entered on SWTAG_FULL). -+ */ -+ uint64_t wqp:36; -+ } s_sstatus5; -+ -+ /** -+ * Result For POW Memory Load (get_des == 0 and get_wqp == 0) -+ */ -+ struct { -+ uint64_t reserved_51_63:13; -+ /* -+ * The next entry in the input, free, descheduled_head -+ * list (unpredictable if entry is the tail of the -+ * list). -+ */ -+ uint64_t next_index:11; -+ /* The group of the POW entry. */ -+ uint64_t grp:4; -+ uint64_t reserved_35:1; -+ /* -+ * Set when this POW entry is at the tail of its tag -+ * list (also set when in the NULL or NULL_NULL -+ * state). -+ */ -+ uint64_t tail:1; -+ /* The tag type of the POW entry. */ -+ uint64_t tag_type:2; -+ /* The tag of the POW entry. */ -+ uint64_t tag:32; -+ } s_smemload0; -+ -+ /** -+ * Result For POW Memory Load (get_des == 0 and get_wqp == 1) -+ */ -+ struct { -+ uint64_t reserved_51_63:13; -+ /* -+ * The next entry in the input, free, descheduled_head -+ * list (unpredictable if entry is the tail of the -+ * list). -+ */ -+ uint64_t next_index:11; -+ /* The group of the POW entry. */ -+ uint64_t grp:4; -+ /* The WQP held in the POW entry. */ -+ uint64_t wqp:36; -+ } s_smemload1; -+ -+ /** -+ * Result For POW Memory Load (get_des == 1) -+ */ -+ struct { -+ uint64_t reserved_51_63:13; -+ /* -+ * The next entry in the tag list connected to the -+ * descheduled head. -+ */ -+ uint64_t fwd_index:11; -+ /* The group of the POW entry. */ -+ uint64_t grp:4; -+ /* The nosched bit for the POW entry. */ -+ uint64_t nosched:1; -+ /* There is a pending tag switch */ -+ uint64_t pend_switch:1; -+ /* -+ * The next tag type for the new tag list when -+ * pend_switch is set. -+ */ -+ uint64_t pend_type:2; -+ /* -+ * The next tag for the new tag list when pend_switch -+ * is set. -+ */ -+ uint64_t pend_tag:32; -+ } s_smemload2; -+ -+ /** -+ * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 0) -+ */ -+ struct { -+ uint64_t reserved_52_63:12; -+ /* -+ * set when there is one or more POW entries on the -+ * free list. -+ */ -+ uint64_t free_val:1; -+ /* -+ * set when there is exactly one POW entry on the free -+ * list. -+ */ -+ uint64_t free_one:1; -+ uint64_t reserved_49:1; -+ /* -+ * when free_val is set, indicates the first entry on -+ * the free list. -+ */ -+ uint64_t free_head:11; -+ uint64_t reserved_37:1; -+ /* -+ * when free_val is set, indicates the last entry on -+ * the free list. -+ */ -+ uint64_t free_tail:11; -+ /* -+ * set when there is one or more POW entries on the -+ * input Q list selected by qosgrp. -+ */ -+ uint64_t loc_val:1; -+ /* -+ * set when there is exactly one POW entry on the -+ * input Q list selected by qosgrp. -+ */ -+ uint64_t loc_one:1; -+ uint64_t reserved_23:1; -+ /* -+ * when loc_val is set, indicates the first entry on -+ * the input Q list selected by qosgrp. -+ */ -+ uint64_t loc_head:11; -+ uint64_t reserved_11:1; -+ /* -+ * when loc_val is set, indicates the last entry on -+ * the input Q list selected by qosgrp. -+ */ -+ uint64_t loc_tail:11; -+ } sindexload0; -+ -+ /** -+ * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 1) -+ */ -+ struct { -+ uint64_t reserved_52_63:12; -+ /* -+ * set when there is one or more POW entries on the -+ * nosched list. -+ */ -+ uint64_t nosched_val:1; -+ /* -+ * set when there is exactly one POW entry on the -+ * nosched list. -+ */ -+ uint64_t nosched_one:1; -+ uint64_t reserved_49:1; -+ /* -+ * when nosched_val is set, indicates the first entry -+ * on the nosched list. -+ */ -+ uint64_t nosched_head:11; -+ uint64_t reserved_37:1; -+ /* -+ * when nosched_val is set, indicates the last entry -+ * on the nosched list. -+ */ -+ uint64_t nosched_tail:11; -+ /* -+ * set when there is one or more descheduled heads on -+ * the descheduled list selected by qosgrp. -+ */ -+ uint64_t des_val:1; -+ /* -+ * set when there is exactly one descheduled head on -+ * the descheduled list selected by qosgrp. -+ */ -+ uint64_t des_one:1; -+ uint64_t reserved_23:1; -+ /* -+ * when des_val is set, indicates the first -+ * descheduled head on the descheduled list selected -+ * by qosgrp. -+ */ -+ uint64_t des_head:11; -+ uint64_t reserved_11:1; -+ /* -+ * when des_val is set, indicates the last descheduled -+ * head on the descheduled list selected by qosgrp. -+ */ -+ uint64_t des_tail:11; -+ } sindexload1; -+ -+ /** -+ * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 0) -+ */ -+ struct { -+ uint64_t reserved_39_63:25; -+ /* -+ * Set when this DRAM list is the current head -+ * (i.e. is the next to be reloaded when the POW -+ * hardware reloads a POW entry from DRAM). The POW -+ * hardware alternates between the two DRAM lists -+ * associated with a QOS level when it reloads work -+ * from DRAM into the POW unit. -+ */ -+ uint64_t rmt_is_head:1; -+ /* -+ * Set when the DRAM portion of the input Q list -+ * selected by qosgrp contains one or more pieces of -+ * work. -+ */ -+ uint64_t rmt_val:1; -+ /* -+ * Set when the DRAM portion of the input Q list -+ * selected by qosgrp contains exactly one piece of -+ * work. -+ */ -+ uint64_t rmt_one:1; -+ /* -+ * When rmt_val is set, indicates the first piece of -+ * work on the DRAM input Q list selected by -+ * qosgrp. -+ */ -+ uint64_t rmt_head:36; -+ } sindexload2; -+ -+ /** -+ * Result For POW Index/Pointer Load (get_rmt == -+ * 1/get_des_get_tail == 1) -+ */ -+ struct { -+ uint64_t reserved_39_63:25; -+ /* -+ * set when this DRAM list is the current head -+ * (i.e. is the next to be reloaded when the POW -+ * hardware reloads a POW entry from DRAM). The POW -+ * hardware alternates between the two DRAM lists -+ * associated with a QOS level when it reloads work -+ * from DRAM into the POW unit. -+ */ -+ uint64_t rmt_is_head:1; -+ /* -+ * set when the DRAM portion of the input Q list -+ * selected by qosgrp contains one or more pieces of -+ * work. -+ */ -+ uint64_t rmt_val:1; -+ /* -+ * set when the DRAM portion of the input Q list -+ * selected by qosgrp contains exactly one piece of -+ * work. -+ */ -+ uint64_t rmt_one:1; -+ /* -+ * when rmt_val is set, indicates the last piece of -+ * work on the DRAM input Q list selected by -+ * qosgrp. -+ */ -+ uint64_t rmt_tail:36; -+ } sindexload3; -+ -+ /** -+ * Response to NULL_RD request loads -+ */ -+ struct { -+ uint64_t unused:62; -+ /* of type cvmx_pow_tag_type_t. state is one of the -+ * following: -+ * -+ * - CVMX_POW_TAG_TYPE_ORDERED -+ * - CVMX_POW_TAG_TYPE_ATOMIC -+ * - CVMX_POW_TAG_TYPE_NULL -+ * - CVMX_POW_TAG_TYPE_NULL_NULL -+ */ -+ uint64_t state:2; -+ } s_null_rd; -+ -+} cvmx_pow_tag_load_resp_t; -+ -+/** -+ * This structure describes the address used for stores to the POW. -+ * The store address is meaningful on stores to the POW. The -+ * hardware assumes that an aligned 64-bit store was used for all -+ * these stores. Note the assumption that the work queue entry is -+ * aligned on an 8-byte boundary (since the low-order 3 address bits -+ * must be zero). Note that not all fields are used by all -+ * operations. -+ * -+ * NOTE: The following is the behavior of the pending switch bit at the PP -+ * for POW stores (i.e. when did<7:3> == 0xc) -+ * - did<2:0> == 0 => pending switch bit is set -+ * - did<2:0> == 1 => no affect on the pending switch bit -+ * - did<2:0> == 3 => pending switch bit is cleared -+ * - did<2:0> == 7 => no affect on the pending switch bit -+ * - did<2:0> == others => must not be used -+ * - No other loads/stores have an affect on the pending switch bit -+ * - The switch bus from POW can clear the pending switch bit -+ * -+ * NOTE: did<2:0> == 2 is used by the HW for a special single-cycle -+ * ADDWQ command that only contains the pointer). SW must never use -+ * did<2:0> == 2. -+ */ -+typedef union { -+ /** -+ * Unsigned 64 bit integer representation of store address -+ */ -+ uint64_t u64; -+ -+ struct { -+ /* Memory region. Should be CVMX_IO_SEG in most cases */ -+ uint64_t mem_reg:2; -+ uint64_t reserved_49_61:13; /* Must be zero */ -+ uint64_t is_io:1; /* Must be one */ -+ /* Device ID of POW. Note that different sub-dids are used. */ -+ uint64_t did:8; -+ uint64_t reserved_36_39:4; /* Must be zero */ -+ /* Address field. addr<2:0> must be zero */ -+ uint64_t addr:36; -+ } stag; -+} cvmx_pow_tag_store_addr_t; -+ -+/** -+ * decode of the store data when an IOBDMA SENDSINGLE is sent to POW -+ */ -+typedef union { -+ uint64_t u64; -+ -+ struct { -+ /* -+ * the (64-bit word) location in scratchpad to write -+ * to (if len != 0) -+ */ -+ uint64_t scraddr:8; -+ /* the number of words in the response (0 => no response) */ -+ uint64_t len:8; -+ /* the ID of the device on the non-coherent bus */ -+ uint64_t did:8; -+ uint64_t unused:36; -+ /* if set, don't return load response until work is available */ -+ uint64_t wait:1; -+ uint64_t unused2:3; -+ } s; -+ -+} cvmx_pow_iobdma_store_t; -+ -+/* CSR typedefs have been moved to cvmx-csr-*.h */ -+ -+/** -+ * Get the POW tag for this core. This returns the current -+ * tag type, tag, group, and POW entry index associated with -+ * this core. Index is only valid if the tag type isn't NULL_NULL. -+ * If a tag switch is pending this routine returns the tag before -+ * the tag switch, not after. -+ * -+ * Returns Current tag -+ */ -+static inline cvmx_pow_tag_req_t cvmx_pow_get_current_tag(void) -+{ -+ cvmx_pow_load_addr_t load_addr; -+ cvmx_pow_tag_load_resp_t load_resp; -+ cvmx_pow_tag_req_t result; -+ -+ load_addr.u64 = 0; -+ load_addr.sstatus.mem_region = CVMX_IO_SEG; -+ load_addr.sstatus.is_io = 1; -+ load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1; -+ load_addr.sstatus.coreid = cvmx_get_core_num(); -+ load_addr.sstatus.get_cur = 1; -+ load_resp.u64 = cvmx_read_csr(load_addr.u64); -+ result.u64 = 0; -+ result.s.grp = load_resp.s_sstatus2.grp; -+ result.s.index = load_resp.s_sstatus2.index; -+ result.s.type = load_resp.s_sstatus2.tag_type; -+ result.s.tag = load_resp.s_sstatus2.tag; -+ return result; -+} -+ -+/** -+ * Get the POW WQE for this core. This returns the work queue -+ * entry currently associated with this core. -+ * -+ * Returns WQE pointer -+ */ -+static inline cvmx_wqe_t *cvmx_pow_get_current_wqp(void) -+{ -+ cvmx_pow_load_addr_t load_addr; -+ cvmx_pow_tag_load_resp_t load_resp; -+ -+ load_addr.u64 = 0; -+ load_addr.sstatus.mem_region = CVMX_IO_SEG; -+ load_addr.sstatus.is_io = 1; -+ load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1; -+ load_addr.sstatus.coreid = cvmx_get_core_num(); -+ load_addr.sstatus.get_cur = 1; -+ load_addr.sstatus.get_wqp = 1; -+ load_resp.u64 = cvmx_read_csr(load_addr.u64); -+ return (cvmx_wqe_t *) cvmx_phys_to_ptr(load_resp.s_sstatus4.wqp); -+} -+ -+#ifndef CVMX_MF_CHORD -+#define CVMX_MF_CHORD(dest) CVMX_RDHWR(dest, 30) -+#endif -+ -+/** -+ * Print a warning if a tag switch is pending for this core -+ * -+ * @function: Function name checking for a pending tag switch -+ */ -+static inline void __cvmx_pow_warn_if_pending_switch(const char *function) -+{ -+ uint64_t switch_complete; -+ CVMX_MF_CHORD(switch_complete); -+ if (!switch_complete) -+ pr_warning("%s called with tag switch in progress\n", function); -+} -+ -+/** -+ * Waits for a tag switch to complete by polling the completion bit. -+ * Note that switches to NULL complete immediately and do not need -+ * to be waited for. -+ */ -+static inline void cvmx_pow_tag_sw_wait(void) -+{ -+ const uint64_t MAX_CYCLES = 1ull << 31; -+ uint64_t switch_complete; -+ uint64_t start_cycle = cvmx_get_cycle(); -+ while (1) { -+ CVMX_MF_CHORD(switch_complete); -+ if (unlikely(switch_complete)) -+ break; -+ if (unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES)) { -+ pr_warning("Tag switch is taking a long time, " -+ "possible deadlock\n"); -+ start_cycle = -MAX_CYCLES - 1; -+ } -+ } -+} -+ -+/** -+ * Synchronous work request. Requests work from the POW. -+ * This function does NOT wait for previous tag switches to complete, -+ * so the caller must ensure that there is not a pending tag switch. -+ * -+ * @wait: When set, call stalls until work becomes avaiable, or times out. -+ * If not set, returns immediately. -+ * -+ * Returns Returns the WQE pointer from POW. Returns NULL if no work -+ * was available. -+ */ -+static inline cvmx_wqe_t *cvmx_pow_work_request_sync_nocheck(cvmx_pow_wait_t -+ wait) -+{ -+ cvmx_pow_load_addr_t ptr; -+ cvmx_pow_tag_load_resp_t result; -+ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ ptr.u64 = 0; -+ ptr.swork.mem_region = CVMX_IO_SEG; -+ ptr.swork.is_io = 1; -+ ptr.swork.did = CVMX_OCT_DID_TAG_SWTAG; -+ ptr.swork.wait = wait; -+ -+ result.u64 = cvmx_read_csr(ptr.u64); -+ -+ if (result.s_work.no_work) -+ return NULL; -+ else -+ return (cvmx_wqe_t *) cvmx_phys_to_ptr(result.s_work.addr); -+} -+ -+/** -+ * Synchronous work request. Requests work from the POW. -+ * This function waits for any previous tag switch to complete before -+ * requesting the new work. -+ * -+ * @wait: When set, call stalls until work becomes avaiable, or times out. -+ * If not set, returns immediately. -+ * -+ * Returns Returns the WQE pointer from POW. Returns NULL if no work -+ * was available. -+ */ -+static inline cvmx_wqe_t *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait) -+{ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* Must not have a switch pending when requesting work */ -+ cvmx_pow_tag_sw_wait(); -+ return cvmx_pow_work_request_sync_nocheck(wait); -+ -+} -+ -+/** -+ * Synchronous null_rd request. Requests a switch out of NULL_NULL POW state. -+ * This function waits for any previous tag switch to complete before -+ * requesting the null_rd. -+ * -+ * Returns Returns the POW state of type cvmx_pow_tag_type_t. -+ */ -+static inline enum cvmx_pow_tag_type cvmx_pow_work_request_null_rd(void) -+{ -+ cvmx_pow_load_addr_t ptr; -+ cvmx_pow_tag_load_resp_t result; -+ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* Must not have a switch pending when requesting work */ -+ cvmx_pow_tag_sw_wait(); -+ -+ ptr.u64 = 0; -+ ptr.snull_rd.mem_region = CVMX_IO_SEG; -+ ptr.snull_rd.is_io = 1; -+ ptr.snull_rd.did = CVMX_OCT_DID_TAG_NULL_RD; -+ -+ result.u64 = cvmx_read_csr(ptr.u64); -+ -+ return (enum cvmx_pow_tag_type) result.s_null_rd.state; -+} -+ -+/** -+ * Asynchronous work request. Work is requested from the POW unit, -+ * and should later be checked with function -+ * cvmx_pow_work_response_async. This function does NOT wait for -+ * previous tag switches to complete, so the caller must ensure that -+ * there is not a pending tag switch. -+ * -+ * @scr_addr: Scratch memory address that response will be returned -+ * to, which is either a valid WQE, or a response with the -+ * invalid bit set. Byte address, must be 8 byte aligned. -+ * -+ * @wait: 1 to cause response to wait for work to become available (or -+ * timeout), 0 to cause response to return immediately -+ */ -+static inline void cvmx_pow_work_request_async_nocheck(int scr_addr, -+ cvmx_pow_wait_t wait) -+{ -+ cvmx_pow_iobdma_store_t data; -+ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* scr_addr must be 8 byte aligned */ -+ data.s.scraddr = scr_addr >> 3; -+ data.s.len = 1; -+ data.s.did = CVMX_OCT_DID_TAG_SWTAG; -+ data.s.wait = wait; -+ cvmx_send_single(data.u64); -+} -+ -+/** -+ * Asynchronous work request. Work is requested from the POW unit, -+ * and should later be checked with function -+ * cvmx_pow_work_response_async. This function waits for any previous -+ * tag switch to complete before requesting the new work. -+ * -+ * @scr_addr: Scratch memory address that response will be returned -+ * to, which is either a valid WQE, or a response with the -+ * invalid bit set. Byte address, must be 8 byte aligned. -+ * -+ * @wait: 1 to cause response to wait for work to become available (or -+ * timeout), 0 to cause response to return immediately -+ */ -+static inline void cvmx_pow_work_request_async(int scr_addr, -+ cvmx_pow_wait_t wait) -+{ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* Must not have a switch pending when requesting work */ -+ cvmx_pow_tag_sw_wait(); -+ cvmx_pow_work_request_async_nocheck(scr_addr, wait); -+} -+ -+/** -+ * Gets result of asynchronous work request. Performs a IOBDMA sync -+ * to wait for the response. -+ * -+ * @scr_addr: Scratch memory address to get result from Byte address, -+ * must be 8 byte aligned. -+ * -+ * Returns Returns the WQE from the scratch register, or NULL if no -+ * work was available. -+ */ -+static inline cvmx_wqe_t *cvmx_pow_work_response_async(int scr_addr) -+{ -+ cvmx_pow_tag_load_resp_t result; -+ -+ CVMX_SYNCIOBDMA; -+ result.u64 = cvmx_scratch_read64(scr_addr); -+ -+ if (result.s_work.no_work) -+ return NULL; -+ else -+ return (cvmx_wqe_t *) cvmx_phys_to_ptr(result.s_work.addr); -+} -+ -+/** -+ * Checks if a work queue entry pointer returned by a work -+ * request is valid. It may be invalid due to no work -+ * being available or due to a timeout. -+ * -+ * @wqe_ptr: pointer to a work queue entry returned by the POW -+ * -+ * Returns 0 if pointer is valid -+ * 1 if invalid (no work was returned) -+ */ -+static inline uint64_t cvmx_pow_work_invalid(cvmx_wqe_t *wqe_ptr) -+{ -+ return wqe_ptr == NULL; -+} -+ -+/** -+ * Starts a tag switch to the provided tag value and tag type. -+ * Completion for the tag switch must be checked for separately. This -+ * function does NOT update the work queue entry in dram to match tag -+ * value and type, so the application must keep track of these if they -+ * are important to the application. This tag switch command must not -+ * be used for switches to NULL, as the tag switch pending bit will be -+ * set by the switch request, but never cleared by the hardware. -+ * -+ * NOTE: This should not be used when switching from a NULL tag. Use -+ * cvmx_pow_tag_sw_full() instead. -+ * -+ * This function does no checks, so the caller must ensure that any -+ * previous tag switch has completed. -+ * -+ * @tag: new tag value -+ * @tag_type: new tag type (ordered or atomic) -+ */ -+static inline void cvmx_pow_tag_sw_nocheck(uint32_t tag, -+ enum cvmx_pow_tag_type tag_type) -+{ -+ cvmx_addr_t ptr; -+ cvmx_pow_tag_req_t tag_req; -+ -+ if (CVMX_ENABLE_POW_CHECKS) { -+ cvmx_pow_tag_req_t current_tag; -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ current_tag = cvmx_pow_get_current_tag(); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) -+ pr_warning("%s called with NULL_NULL tag\n", -+ __func__); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) -+ pr_warning("%s called with NULL tag\n", __func__); -+ if ((current_tag.s.type == tag_type) -+ && (current_tag.s.tag == tag)) -+ pr_warning("%s called to perform a tag switch to the " -+ "same tag\n", -+ __func__); -+ if (tag_type == CVMX_POW_TAG_TYPE_NULL) -+ pr_warning("%s called to perform a tag switch to " -+ "NULL. Use cvmx_pow_tag_sw_null() instead\n", -+ __func__); -+ } -+ -+ /* -+ * Note that WQE in DRAM is not updated here, as the POW does -+ * not read from DRAM once the WQE is in flight. See hardware -+ * manual for complete details. It is the application's -+ * responsibility to keep track of the current tag value if -+ * that is important. -+ */ -+ -+ tag_req.u64 = 0; -+ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG; -+ tag_req.s.tag = tag; -+ tag_req.s.type = tag_type; -+ -+ ptr.u64 = 0; -+ ptr.sio.mem_region = CVMX_IO_SEG; -+ ptr.sio.is_io = 1; -+ ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG; -+ -+ /* once this store arrives at POW, it will attempt the switch -+ software must wait for the switch to complete separately */ -+ cvmx_write_io(ptr.u64, tag_req.u64); -+} -+ -+/** -+ * Starts a tag switch to the provided tag value and tag type. -+ * Completion for the tag switch must be checked for separately. This -+ * function does NOT update the work queue entry in dram to match tag -+ * value and type, so the application must keep track of these if they -+ * are important to the application. This tag switch command must not -+ * be used for switches to NULL, as the tag switch pending bit will be -+ * set by the switch request, but never cleared by the hardware. -+ * -+ * NOTE: This should not be used when switching from a NULL tag. Use -+ * cvmx_pow_tag_sw_full() instead. -+ * -+ * This function waits for any previous tag switch to complete, and also -+ * displays an error on tag switches to NULL. -+ * -+ * @tag: new tag value -+ * @tag_type: new tag type (ordered or atomic) -+ */ -+static inline void cvmx_pow_tag_sw(uint32_t tag, -+ enum cvmx_pow_tag_type tag_type) -+{ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* -+ * Note that WQE in DRAM is not updated here, as the POW does -+ * not read from DRAM once the WQE is in flight. See hardware -+ * manual for complete details. It is the application's -+ * responsibility to keep track of the current tag value if -+ * that is important. -+ */ -+ -+ /* -+ * Ensure that there is not a pending tag switch, as a tag -+ * switch cannot be started if a previous switch is still -+ * pending. -+ */ -+ cvmx_pow_tag_sw_wait(); -+ cvmx_pow_tag_sw_nocheck(tag, tag_type); -+} -+ -+/** -+ * Starts a tag switch to the provided tag value and tag type. -+ * Completion for the tag switch must be checked for separately. This -+ * function does NOT update the work queue entry in dram to match tag -+ * value and type, so the application must keep track of these if they -+ * are important to the application. This tag switch command must not -+ * be used for switches to NULL, as the tag switch pending bit will be -+ * set by the switch request, but never cleared by the hardware. -+ * -+ * This function must be used for tag switches from NULL. -+ * -+ * This function does no checks, so the caller must ensure that any -+ * previous tag switch has completed. -+ * -+ * @wqp: pointer to work queue entry to submit. This entry is -+ * updated to match the other parameters -+ * @tag: tag value to be assigned to work queue entry -+ * @tag_type: type of tag -+ * @group: group value for the work queue entry. -+ */ -+static inline void cvmx_pow_tag_sw_full_nocheck(cvmx_wqe_t *wqp, uint32_t tag, -+ enum cvmx_pow_tag_type tag_type, -+ uint64_t group) -+{ -+ cvmx_addr_t ptr; -+ cvmx_pow_tag_req_t tag_req; -+ -+ if (CVMX_ENABLE_POW_CHECKS) { -+ cvmx_pow_tag_req_t current_tag; -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ current_tag = cvmx_pow_get_current_tag(); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) -+ pr_warning("%s called with NULL_NULL tag\n", -+ __func__); -+ if ((current_tag.s.type == tag_type) -+ && (current_tag.s.tag == tag)) -+ pr_warning("%s called to perform a tag switch to " -+ "the same tag\n", -+ __func__); -+ if (tag_type == CVMX_POW_TAG_TYPE_NULL) -+ pr_warning("%s called to perform a tag switch to " -+ "NULL. Use cvmx_pow_tag_sw_null() instead\n", -+ __func__); -+ if (wqp != cvmx_phys_to_ptr(0x80)) -+ if (wqp != cvmx_pow_get_current_wqp()) -+ pr_warning("%s passed WQE(%p) doesn't match " -+ "the address in the POW(%p)\n", -+ __func__, wqp, -+ cvmx_pow_get_current_wqp()); -+ } -+ -+ /* -+ * Note that WQE in DRAM is not updated here, as the POW does -+ * not read from DRAM once the WQE is in flight. See hardware -+ * manual for complete details. It is the application's -+ * responsibility to keep track of the current tag value if -+ * that is important. -+ */ -+ -+ tag_req.u64 = 0; -+ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_FULL; -+ tag_req.s.tag = tag; -+ tag_req.s.type = tag_type; -+ tag_req.s.grp = group; -+ -+ ptr.u64 = 0; -+ ptr.sio.mem_region = CVMX_IO_SEG; -+ ptr.sio.is_io = 1; -+ ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG; -+ ptr.sio.offset = CAST64(wqp); -+ -+ /* -+ * once this store arrives at POW, it will attempt the switch -+ * software must wait for the switch to complete separately. -+ */ -+ cvmx_write_io(ptr.u64, tag_req.u64); -+} -+ -+/** -+ * Starts a tag switch to the provided tag value and tag type. -+ * Completion for the tag switch must be checked for separately. This -+ * function does NOT update the work queue entry in dram to match tag -+ * value and type, so the application must keep track of these if they -+ * are important to the application. This tag switch command must not -+ * be used for switches to NULL, as the tag switch pending bit will be -+ * set by the switch request, but never cleared by the hardware. -+ * -+ * This function must be used for tag switches from NULL. -+ * -+ * This function waits for any pending tag switches to complete -+ * before requesting the tag switch. -+ * -+ * @wqp: pointer to work queue entry to submit. This entry is updated -+ * to match the other parameters -+ * @tag: tag value to be assigned to work queue entry -+ * @tag_type: type of tag -+ * @group: group value for the work queue entry. -+ */ -+static inline void cvmx_pow_tag_sw_full(cvmx_wqe_t *wqp, uint32_t tag, -+ enum cvmx_pow_tag_type tag_type, -+ uint64_t group) -+{ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* -+ * Ensure that there is not a pending tag switch, as a tag -+ * switch cannot be started if a previous switch is still -+ * pending. -+ */ -+ cvmx_pow_tag_sw_wait(); -+ cvmx_pow_tag_sw_full_nocheck(wqp, tag, tag_type, group); -+} -+ -+/** -+ * Switch to a NULL tag, which ends any ordering or -+ * synchronization provided by the POW for the current -+ * work queue entry. This operation completes immediatly, -+ * so completetion should not be waited for. -+ * This function does NOT wait for previous tag switches to complete, -+ * so the caller must ensure that any previous tag switches have completed. -+ */ -+static inline void cvmx_pow_tag_sw_null_nocheck(void) -+{ -+ cvmx_addr_t ptr; -+ cvmx_pow_tag_req_t tag_req; -+ -+ if (CVMX_ENABLE_POW_CHECKS) { -+ cvmx_pow_tag_req_t current_tag; -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ current_tag = cvmx_pow_get_current_tag(); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) -+ pr_warning("%s called with NULL_NULL tag\n", -+ __func__); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) -+ pr_warning("%s called when we already have a " -+ "NULL tag\n", -+ __func__); -+ } -+ -+ tag_req.u64 = 0; -+ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG; -+ tag_req.s.type = CVMX_POW_TAG_TYPE_NULL; -+ -+ ptr.u64 = 0; -+ ptr.sio.mem_region = CVMX_IO_SEG; -+ ptr.sio.is_io = 1; -+ ptr.sio.did = CVMX_OCT_DID_TAG_TAG1; -+ -+ cvmx_write_io(ptr.u64, tag_req.u64); -+ -+ /* switch to NULL completes immediately */ -+} -+ -+/** -+ * Switch to a NULL tag, which ends any ordering or -+ * synchronization provided by the POW for the current -+ * work queue entry. This operation completes immediatly, -+ * so completetion should not be waited for. -+ * This function waits for any pending tag switches to complete -+ * before requesting the switch to NULL. -+ */ -+static inline void cvmx_pow_tag_sw_null(void) -+{ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* -+ * Ensure that there is not a pending tag switch, as a tag -+ * switch cannot be started if a previous switch is still -+ * pending. -+ */ -+ cvmx_pow_tag_sw_wait(); -+ cvmx_pow_tag_sw_null_nocheck(); -+ -+ /* switch to NULL completes immediately */ -+} -+ -+/** -+ * Submits work to an input queue. This function updates the work -+ * queue entry in DRAM to match the arguments given. Note that the -+ * tag provided is for the work queue entry submitted, and is -+ * unrelated to the tag that the core currently holds. -+ * -+ * @wqp: pointer to work queue entry to submit. This entry is -+ * updated to match the other parameters -+ * @tag: tag value to be assigned to work queue entry -+ * @tag_type: type of tag -+ * @qos: Input queue to add to. -+ * @grp: group value for the work queue entry. -+ */ -+static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag, -+ enum cvmx_pow_tag_type tag_type, -+ uint64_t qos, uint64_t grp) -+{ -+ cvmx_addr_t ptr; -+ cvmx_pow_tag_req_t tag_req; -+ -+ wqp->qos = qos; -+ wqp->tag = tag; -+ wqp->tag_type = tag_type; -+ wqp->grp = grp; -+ -+ tag_req.u64 = 0; -+ tag_req.s.op = CVMX_POW_TAG_OP_ADDWQ; -+ tag_req.s.type = tag_type; -+ tag_req.s.tag = tag; -+ tag_req.s.qos = qos; -+ tag_req.s.grp = grp; -+ -+ ptr.u64 = 0; -+ ptr.sio.mem_region = CVMX_IO_SEG; -+ ptr.sio.is_io = 1; -+ ptr.sio.did = CVMX_OCT_DID_TAG_TAG1; -+ ptr.sio.offset = cvmx_ptr_to_phys(wqp); -+ -+ /* -+ * SYNC write to memory before the work submit. This is -+ * necessary as POW may read values from DRAM at this time. -+ */ -+ CVMX_SYNCWS; -+ cvmx_write_io(ptr.u64, tag_req.u64); -+} -+ -+/** -+ * This function sets the group mask for a core. The group mask -+ * indicates which groups each core will accept work from. There are -+ * 16 groups. -+ * -+ * @core_num: core to apply mask to -+ * @mask: Group mask. There are 16 groups, so only bits 0-15 are valid, -+ * representing groups 0-15. -+ * Each 1 bit in the mask enables the core to accept work from -+ * the corresponding group. -+ */ -+static inline void cvmx_pow_set_group_mask(uint64_t core_num, uint64_t mask) -+{ -+ union cvmx_pow_pp_grp_mskx grp_msk; -+ -+ grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num)); -+ grp_msk.s.grp_msk = mask; -+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64); -+} -+ -+/** -+ * This function sets POW static priorities for a core. Each input queue has -+ * an associated priority value. -+ * -+ * @core_num: core to apply priorities to -+ * @priority: Vector of 8 priorities, one per POW Input Queue (0-7). -+ * Highest priority is 0 and lowest is 7. A priority value -+ * of 0xF instructs POW to skip the Input Queue when -+ * scheduling to this specific core. -+ * NOTE: priorities should not have gaps in values, meaning -+ * {0,1,1,1,1,1,1,1} is a valid configuration while -+ * {0,2,2,2,2,2,2,2} is not. -+ */ -+static inline void cvmx_pow_set_priority(uint64_t core_num, -+ const uint8_t priority[]) -+{ -+ /* POW priorities are supported on CN5xxx and later */ -+ if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ union cvmx_pow_pp_grp_mskx grp_msk; -+ -+ grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num)); -+ grp_msk.s.qos0_pri = priority[0]; -+ grp_msk.s.qos1_pri = priority[1]; -+ grp_msk.s.qos2_pri = priority[2]; -+ grp_msk.s.qos3_pri = priority[3]; -+ grp_msk.s.qos4_pri = priority[4]; -+ grp_msk.s.qos5_pri = priority[5]; -+ grp_msk.s.qos6_pri = priority[6]; -+ grp_msk.s.qos7_pri = priority[7]; -+ -+ /* Detect gaps between priorities and flag error */ -+ { -+ int i; -+ uint32_t prio_mask = 0; -+ -+ for (i = 0; i < 8; i++) -+ if (priority[i] != 0xF) -+ prio_mask |= 1 << priority[i]; -+ -+ if (prio_mask ^ ((1 << cvmx_pop(prio_mask)) - 1)) { -+ pr_err("POW static priorities should be " -+ "contiguous (0x%llx)\n", -+ (unsigned long long)prio_mask); -+ return; -+ } -+ } -+ -+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64); -+ } -+} -+ -+/** -+ * Performs a tag switch and then an immediate deschedule. This completes -+ * immediatly, so completion must not be waited for. This function does NOT -+ * update the wqe in DRAM to match arguments. -+ * -+ * This function does NOT wait for any prior tag switches to complete, so the -+ * calling code must do this. -+ * -+ * Note the following CAVEAT of the Octeon HW behavior when -+ * re-scheduling DE-SCHEDULEd items whose (next) state is -+ * ORDERED: -+ * - If there are no switches pending at the time that the -+ * HW executes the de-schedule, the HW will only re-schedule -+ * the head of the FIFO associated with the given tag. This -+ * means that in many respects, the HW treats this ORDERED -+ * tag as an ATOMIC tag. Note that in the SWTAG_DESCH -+ * case (to an ORDERED tag), the HW will do the switch -+ * before the deschedule whenever it is possible to do -+ * the switch immediately, so it may often look like -+ * this case. -+ * - If there is a pending switch to ORDERED at the time -+ * the HW executes the de-schedule, the HW will perform -+ * the switch at the time it re-schedules, and will be -+ * able to reschedule any/all of the entries with the -+ * same tag. -+ * Due to this behavior, the RECOMMENDATION to software is -+ * that they have a (next) state of ATOMIC when they -+ * DE-SCHEDULE. If an ORDERED tag is what was really desired, -+ * SW can choose to immediately switch to an ORDERED tag -+ * after the work (that has an ATOMIC tag) is re-scheduled. -+ * Note that since there are never any tag switches pending -+ * when the HW re-schedules, this switch can be IMMEDIATE upon -+ * the reception of the pointer during the re-schedule. -+ * -+ * @tag: New tag value -+ * @tag_type: New tag type -+ * @group: New group value -+ * @no_sched: Control whether this work queue entry will be rescheduled. -+ * - 1 : don't schedule this work -+ * - 0 : allow this work to be scheduled. -+ */ -+static inline void cvmx_pow_tag_sw_desched_nocheck( -+ uint32_t tag, -+ enum cvmx_pow_tag_type tag_type, -+ uint64_t group, -+ uint64_t no_sched) -+{ -+ cvmx_addr_t ptr; -+ cvmx_pow_tag_req_t tag_req; -+ -+ if (CVMX_ENABLE_POW_CHECKS) { -+ cvmx_pow_tag_req_t current_tag; -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ current_tag = cvmx_pow_get_current_tag(); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) -+ pr_warning("%s called with NULL_NULL tag\n", -+ __func__); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) -+ pr_warning("%s called with NULL tag. Deschedule not " -+ "allowed from NULL state\n", -+ __func__); -+ if ((current_tag.s.type != CVMX_POW_TAG_TYPE_ATOMIC) -+ && (tag_type != CVMX_POW_TAG_TYPE_ATOMIC)) -+ pr_warning("%s called where neither the before or " -+ "after tag is ATOMIC\n", -+ __func__); -+ } -+ -+ tag_req.u64 = 0; -+ tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_DESCH; -+ tag_req.s.tag = tag; -+ tag_req.s.type = tag_type; -+ tag_req.s.grp = group; -+ tag_req.s.no_sched = no_sched; -+ -+ ptr.u64 = 0; -+ ptr.sio.mem_region = CVMX_IO_SEG; -+ ptr.sio.is_io = 1; -+ ptr.sio.did = CVMX_OCT_DID_TAG_TAG3; -+ /* -+ * since TAG3 is used, this store will clear the local pending -+ * switch bit. -+ */ -+ cvmx_write_io(ptr.u64, tag_req.u64); -+} -+ -+/** -+ * Performs a tag switch and then an immediate deschedule. This completes -+ * immediatly, so completion must not be waited for. This function does NOT -+ * update the wqe in DRAM to match arguments. -+ * -+ * This function waits for any prior tag switches to complete, so the -+ * calling code may call this function with a pending tag switch. -+ * -+ * Note the following CAVEAT of the Octeon HW behavior when -+ * re-scheduling DE-SCHEDULEd items whose (next) state is -+ * ORDERED: -+ * - If there are no switches pending at the time that the -+ * HW executes the de-schedule, the HW will only re-schedule -+ * the head of the FIFO associated with the given tag. This -+ * means that in many respects, the HW treats this ORDERED -+ * tag as an ATOMIC tag. Note that in the SWTAG_DESCH -+ * case (to an ORDERED tag), the HW will do the switch -+ * before the deschedule whenever it is possible to do -+ * the switch immediately, so it may often look like -+ * this case. -+ * - If there is a pending switch to ORDERED at the time -+ * the HW executes the de-schedule, the HW will perform -+ * the switch at the time it re-schedules, and will be -+ * able to reschedule any/all of the entries with the -+ * same tag. -+ * Due to this behavior, the RECOMMENDATION to software is -+ * that they have a (next) state of ATOMIC when they -+ * DE-SCHEDULE. If an ORDERED tag is what was really desired, -+ * SW can choose to immediately switch to an ORDERED tag -+ * after the work (that has an ATOMIC tag) is re-scheduled. -+ * Note that since there are never any tag switches pending -+ * when the HW re-schedules, this switch can be IMMEDIATE upon -+ * the reception of the pointer during the re-schedule. -+ * -+ * @tag: New tag value -+ * @tag_type: New tag type -+ * @group: New group value -+ * @no_sched: Control whether this work queue entry will be rescheduled. -+ * - 1 : don't schedule this work -+ * - 0 : allow this work to be scheduled. -+ */ -+static inline void cvmx_pow_tag_sw_desched(uint32_t tag, -+ enum cvmx_pow_tag_type tag_type, -+ uint64_t group, uint64_t no_sched) -+{ -+ if (CVMX_ENABLE_POW_CHECKS) -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ -+ /* Need to make sure any writes to the work queue entry are complete */ -+ CVMX_SYNCWS; -+ /* -+ * Ensure that there is not a pending tag switch, as a tag -+ * switch cannot be started if a previous switch is still -+ * pending. -+ */ -+ cvmx_pow_tag_sw_wait(); -+ cvmx_pow_tag_sw_desched_nocheck(tag, tag_type, group, no_sched); -+} -+ -+/** -+ * Descchedules the current work queue entry. -+ * -+ * @no_sched: no schedule flag value to be set on the work queue -+ * entry. If this is set the entry will not be -+ * rescheduled. -+ */ -+static inline void cvmx_pow_desched(uint64_t no_sched) -+{ -+ cvmx_addr_t ptr; -+ cvmx_pow_tag_req_t tag_req; -+ -+ if (CVMX_ENABLE_POW_CHECKS) { -+ cvmx_pow_tag_req_t current_tag; -+ __cvmx_pow_warn_if_pending_switch(__func__); -+ current_tag = cvmx_pow_get_current_tag(); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) -+ pr_warning("%s called with NULL_NULL tag\n", -+ __func__); -+ if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) -+ pr_warning("%s called with NULL tag. Deschedule not " -+ "expected from NULL state\n", -+ __func__); -+ } -+ -+ /* Need to make sure any writes to the work queue entry are complete */ -+ CVMX_SYNCWS; -+ -+ tag_req.u64 = 0; -+ tag_req.s.op = CVMX_POW_TAG_OP_DESCH; -+ tag_req.s.no_sched = no_sched; -+ -+ ptr.u64 = 0; -+ ptr.sio.mem_region = CVMX_IO_SEG; -+ ptr.sio.is_io = 1; -+ ptr.sio.did = CVMX_OCT_DID_TAG_TAG3; -+ /* -+ * since TAG3 is used, this store will clear the local pending -+ * switch bit. -+ */ -+ cvmx_write_io(ptr.u64, tag_req.u64); -+} -+ -+/**************************************************** -+* Define usage of bits within the 32 bit tag values. -+*****************************************************/ -+ -+/* -+ * Number of bits of the tag used by software. The SW bits are always -+ * a contiguous block of the high starting at bit 31. The hardware -+ * bits are always the low bits. By default, the top 8 bits of the -+ * tag are reserved for software, and the low 24 are set by the IPD -+ * unit. -+ */ -+#define CVMX_TAG_SW_BITS (8) -+#define CVMX_TAG_SW_SHIFT (32 - CVMX_TAG_SW_BITS) -+ -+/* Below is the list of values for the top 8 bits of the tag. */ -+/* -+ * Tag values with top byte of this value are reserved for internal -+ * executive uses. -+ */ -+#define CVMX_TAG_SW_BITS_INTERNAL 0x1 -+/* The executive divides the remaining 24 bits as follows: -+ * - the upper 8 bits (bits 23 - 16 of the tag) define a subgroup -+ * -+ * - the lower 16 bits (bits 15 - 0 of the tag) define are the value -+ * with the subgroup -+ * -+ * Note that this section describes the format of tags generated by -+ * software - refer to the hardware documentation for a description of -+ * the tags values generated by the packet input hardware. Subgroups -+ * are defined here. -+ */ -+/* Mask for the value portion of the tag */ -+#define CVMX_TAG_SUBGROUP_MASK 0xFFFF -+#define CVMX_TAG_SUBGROUP_SHIFT 16 -+#define CVMX_TAG_SUBGROUP_PKO 0x1 -+ -+/* End of executive tag subgroup definitions */ -+ -+/* -+ * The remaining values software bit values 0x2 - 0xff are available -+ * for application use. -+ */ -+ -+/** -+ * This function creates a 32 bit tag value from the two values provided. -+ * -+ * @sw_bits: The upper bits (number depends on configuration) are set -+ * to this value. The remainder of bits are set by the -+ * hw_bits parameter. -+ * -+ * @hw_bits: The lower bits (number depends on configuration) are set -+ * to this value. The remainder of bits are set by the -+ * sw_bits parameter. -+ * -+ * Returns 32 bit value of the combined hw and sw bits. -+ */ -+static inline uint32_t cvmx_pow_tag_compose(uint64_t sw_bits, uint64_t hw_bits) -+{ -+ return ((sw_bits & cvmx_build_mask(CVMX_TAG_SW_BITS)) << -+ CVMX_TAG_SW_SHIFT) | -+ (hw_bits & cvmx_build_mask(32 - CVMX_TAG_SW_BITS)); -+} -+ -+/** -+ * Extracts the bits allocated for software use from the tag -+ * -+ * @tag: 32 bit tag value -+ * -+ * Returns N bit software tag value, where N is configurable with the -+ * CVMX_TAG_SW_BITS define -+ */ -+static inline uint32_t cvmx_pow_tag_get_sw_bits(uint64_t tag) -+{ -+ return (tag >> (32 - CVMX_TAG_SW_BITS)) & -+ cvmx_build_mask(CVMX_TAG_SW_BITS); -+} -+ -+/** -+ * -+ * Extracts the bits allocated for hardware use from the tag -+ * -+ * @tag: 32 bit tag value -+ * -+ * Returns (32 - N) bit software tag value, where N is configurable -+ * with the CVMX_TAG_SW_BITS define -+ */ -+static inline uint32_t cvmx_pow_tag_get_hw_bits(uint64_t tag) -+{ -+ return tag & cvmx_build_mask(32 - CVMX_TAG_SW_BITS); -+} -+ -+/** -+ * Store the current POW internal state into the supplied -+ * buffer. It is recommended that you pass a buffer of at least -+ * 128KB. The format of the capture may change based on SDK -+ * version and Octeon chip. -+ * -+ * @buffer: Buffer to store capture into -+ * @buffer_size: -+ * The size of the supplied buffer -+ * -+ * Returns Zero on sucess, negative on failure -+ */ -+extern int cvmx_pow_capture(void *buffer, int buffer_size); -+ -+/** -+ * Dump a POW capture to the console in a human readable format. -+ * -+ * @buffer: POW capture from cvmx_pow_capture() -+ * @buffer_size: -+ * Size of the buffer -+ */ -+extern void cvmx_pow_display(void *buffer, int buffer_size); -+ -+/** -+ * Return the number of POW entries supported by this chip -+ * -+ * Returns Number of POW entries -+ */ -+extern int cvmx_pow_get_num_entries(void); -+ -+#endif /* __CVMX_POW_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-scratch.h -@@ -0,0 +1,139 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * This file provides support for the processor local scratch memory. -+ * Scratch memory is byte addressable - all addresses are byte addresses. -+ * -+ */ -+ -+#ifndef __CVMX_SCRATCH_H__ -+#define __CVMX_SCRATCH_H__ -+ -+/* -+ * Note: This define must be a long, not a long long in order to -+ * compile without warnings for both 32bit and 64bit. -+ */ -+#define CVMX_SCRATCH_BASE (-32768l) /* 0xffffffffffff8000 */ -+ -+/** -+ * Reads an 8 bit value from the processor local scratchpad memory. -+ * -+ * @address: byte address to read from -+ * -+ * Returns value read -+ */ -+static inline uint8_t cvmx_scratch_read8(uint64_t address) -+{ -+ return *CASTPTR(volatile uint8_t, CVMX_SCRATCH_BASE + address); -+} -+ -+/** -+ * Reads a 16 bit value from the processor local scratchpad memory. -+ * -+ * @address: byte address to read from -+ * -+ * Returns value read -+ */ -+static inline uint16_t cvmx_scratch_read16(uint64_t address) -+{ -+ return *CASTPTR(volatile uint16_t, CVMX_SCRATCH_BASE + address); -+} -+ -+/** -+ * Reads a 32 bit value from the processor local scratchpad memory. -+ * -+ * @address: byte address to read from -+ * -+ * Returns value read -+ */ -+static inline uint32_t cvmx_scratch_read32(uint64_t address) -+{ -+ return *CASTPTR(volatile uint32_t, CVMX_SCRATCH_BASE + address); -+} -+ -+/** -+ * Reads a 64 bit value from the processor local scratchpad memory. -+ * -+ * @address: byte address to read from -+ * -+ * Returns value read -+ */ -+static inline uint64_t cvmx_scratch_read64(uint64_t address) -+{ -+ return *CASTPTR(volatile uint64_t, CVMX_SCRATCH_BASE + address); -+} -+ -+/** -+ * Writes an 8 bit value to the processor local scratchpad memory. -+ * -+ * @address: byte address to write to -+ * @value: value to write -+ */ -+static inline void cvmx_scratch_write8(uint64_t address, uint64_t value) -+{ -+ *CASTPTR(volatile uint8_t, CVMX_SCRATCH_BASE + address) = -+ (uint8_t) value; -+} -+ -+/** -+ * Writes a 32 bit value to the processor local scratchpad memory. -+ * -+ * @address: byte address to write to -+ * @value: value to write -+ */ -+static inline void cvmx_scratch_write16(uint64_t address, uint64_t value) -+{ -+ *CASTPTR(volatile uint16_t, CVMX_SCRATCH_BASE + address) = -+ (uint16_t) value; -+} -+ -+/** -+ * Writes a 16 bit value to the processor local scratchpad memory. -+ * -+ * @address: byte address to write to -+ * @value: value to write -+ */ -+static inline void cvmx_scratch_write32(uint64_t address, uint64_t value) -+{ -+ *CASTPTR(volatile uint32_t, CVMX_SCRATCH_BASE + address) = -+ (uint32_t) value; -+} -+ -+/** -+ * Writes a 64 bit value to the processor local scratchpad memory. -+ * -+ * @address: byte address to write to -+ * @value: value to write -+ */ -+static inline void cvmx_scratch_write64(uint64_t address, uint64_t value) -+{ -+ *CASTPTR(volatile uint64_t, CVMX_SCRATCH_BASE + address) = value; -+} -+ -+#endif /* __CVMX_SCRATCH_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-smix-defs.h -@@ -0,0 +1,178 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_SMIX_DEFS_H__ -+#define __CVMX_SMIX_DEFS_H__ -+ -+#define CVMX_SMIX_CLK(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_CMD(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_EN(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_RD_DAT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256)) -+#define CVMX_SMIX_WR_DAT(offset) \ -+ CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256)) -+ -+union cvmx_smix_clk { -+ uint64_t u64; -+ struct cvmx_smix_clk_s { -+ uint64_t reserved_25_63:39; -+ uint64_t mode:1; -+ uint64_t reserved_21_23:3; -+ uint64_t sample_hi:5; -+ uint64_t sample_mode:1; -+ uint64_t reserved_14_14:1; -+ uint64_t clk_idle:1; -+ uint64_t preamble:1; -+ uint64_t sample:4; -+ uint64_t phase:8; -+ } s; -+ struct cvmx_smix_clk_cn30xx { -+ uint64_t reserved_21_63:43; -+ uint64_t sample_hi:5; -+ uint64_t reserved_14_15:2; -+ uint64_t clk_idle:1; -+ uint64_t preamble:1; -+ uint64_t sample:4; -+ uint64_t phase:8; -+ } cn30xx; -+ struct cvmx_smix_clk_cn30xx cn31xx; -+ struct cvmx_smix_clk_cn30xx cn38xx; -+ struct cvmx_smix_clk_cn30xx cn38xxp2; -+ struct cvmx_smix_clk_cn50xx { -+ uint64_t reserved_25_63:39; -+ uint64_t mode:1; -+ uint64_t reserved_21_23:3; -+ uint64_t sample_hi:5; -+ uint64_t reserved_14_15:2; -+ uint64_t clk_idle:1; -+ uint64_t preamble:1; -+ uint64_t sample:4; -+ uint64_t phase:8; -+ } cn50xx; -+ struct cvmx_smix_clk_s cn52xx; -+ struct cvmx_smix_clk_cn50xx cn52xxp1; -+ struct cvmx_smix_clk_s cn56xx; -+ struct cvmx_smix_clk_cn50xx cn56xxp1; -+ struct cvmx_smix_clk_cn30xx cn58xx; -+ struct cvmx_smix_clk_cn30xx cn58xxp1; -+}; -+ -+union cvmx_smix_cmd { -+ uint64_t u64; -+ struct cvmx_smix_cmd_s { -+ uint64_t reserved_18_63:46; -+ uint64_t phy_op:2; -+ uint64_t reserved_13_15:3; -+ uint64_t phy_adr:5; -+ uint64_t reserved_5_7:3; -+ uint64_t reg_adr:5; -+ } s; -+ struct cvmx_smix_cmd_cn30xx { -+ uint64_t reserved_17_63:47; -+ uint64_t phy_op:1; -+ uint64_t reserved_13_15:3; -+ uint64_t phy_adr:5; -+ uint64_t reserved_5_7:3; -+ uint64_t reg_adr:5; -+ } cn30xx; -+ struct cvmx_smix_cmd_cn30xx cn31xx; -+ struct cvmx_smix_cmd_cn30xx cn38xx; -+ struct cvmx_smix_cmd_cn30xx cn38xxp2; -+ struct cvmx_smix_cmd_s cn50xx; -+ struct cvmx_smix_cmd_s cn52xx; -+ struct cvmx_smix_cmd_s cn52xxp1; -+ struct cvmx_smix_cmd_s cn56xx; -+ struct cvmx_smix_cmd_s cn56xxp1; -+ struct cvmx_smix_cmd_cn30xx cn58xx; -+ struct cvmx_smix_cmd_cn30xx cn58xxp1; -+}; -+ -+union cvmx_smix_en { -+ uint64_t u64; -+ struct cvmx_smix_en_s { -+ uint64_t reserved_1_63:63; -+ uint64_t en:1; -+ } s; -+ struct cvmx_smix_en_s cn30xx; -+ struct cvmx_smix_en_s cn31xx; -+ struct cvmx_smix_en_s cn38xx; -+ struct cvmx_smix_en_s cn38xxp2; -+ struct cvmx_smix_en_s cn50xx; -+ struct cvmx_smix_en_s cn52xx; -+ struct cvmx_smix_en_s cn52xxp1; -+ struct cvmx_smix_en_s cn56xx; -+ struct cvmx_smix_en_s cn56xxp1; -+ struct cvmx_smix_en_s cn58xx; -+ struct cvmx_smix_en_s cn58xxp1; -+}; -+ -+union cvmx_smix_rd_dat { -+ uint64_t u64; -+ struct cvmx_smix_rd_dat_s { -+ uint64_t reserved_18_63:46; -+ uint64_t pending:1; -+ uint64_t val:1; -+ uint64_t dat:16; -+ } s; -+ struct cvmx_smix_rd_dat_s cn30xx; -+ struct cvmx_smix_rd_dat_s cn31xx; -+ struct cvmx_smix_rd_dat_s cn38xx; -+ struct cvmx_smix_rd_dat_s cn38xxp2; -+ struct cvmx_smix_rd_dat_s cn50xx; -+ struct cvmx_smix_rd_dat_s cn52xx; -+ struct cvmx_smix_rd_dat_s cn52xxp1; -+ struct cvmx_smix_rd_dat_s cn56xx; -+ struct cvmx_smix_rd_dat_s cn56xxp1; -+ struct cvmx_smix_rd_dat_s cn58xx; -+ struct cvmx_smix_rd_dat_s cn58xxp1; -+}; -+ -+union cvmx_smix_wr_dat { -+ uint64_t u64; -+ struct cvmx_smix_wr_dat_s { -+ uint64_t reserved_18_63:46; -+ uint64_t pending:1; -+ uint64_t val:1; -+ uint64_t dat:16; -+ } s; -+ struct cvmx_smix_wr_dat_s cn30xx; -+ struct cvmx_smix_wr_dat_s cn31xx; -+ struct cvmx_smix_wr_dat_s cn38xx; -+ struct cvmx_smix_wr_dat_s cn38xxp2; -+ struct cvmx_smix_wr_dat_s cn50xx; -+ struct cvmx_smix_wr_dat_s cn52xx; -+ struct cvmx_smix_wr_dat_s cn52xxp1; -+ struct cvmx_smix_wr_dat_s cn56xx; -+ struct cvmx_smix_wr_dat_s cn56xxp1; -+ struct cvmx_smix_wr_dat_s cn58xx; -+ struct cvmx_smix_wr_dat_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-spi.c -@@ -0,0 +1,667 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * Support library for the SPI -+ */ -+#include -+ -+#include "cvmx-config.h" -+ -+#include "cvmx-pko.h" -+#include "cvmx-spi.h" -+ -+#include "cvmx-spxx-defs.h" -+#include "cvmx-stxx-defs.h" -+#include "cvmx-srxx-defs.h" -+ -+#define INVOKE_CB(function_p, args...) \ -+ do { \ -+ if (function_p) { \ -+ res = function_p(args); \ -+ if (res) \ -+ return res; \ -+ } \ -+ } while (0) -+ -+#if CVMX_ENABLE_DEBUG_PRINTS -+static const char *modes[] = -+ { "UNKNOWN", "TX Halfplex", "Rx Halfplex", "Duplex" }; -+#endif -+ -+/* Default callbacks, can be overridden -+ * using cvmx_spi_get_callbacks/cvmx_spi_set_callbacks -+ */ -+static cvmx_spi_callbacks_t cvmx_spi_callbacks = { -+ .reset_cb = cvmx_spi_reset_cb, -+ .calendar_setup_cb = cvmx_spi_calendar_setup_cb, -+ .clock_detect_cb = cvmx_spi_clock_detect_cb, -+ .training_cb = cvmx_spi_training_cb, -+ .calendar_sync_cb = cvmx_spi_calendar_sync_cb, -+ .interface_up_cb = cvmx_spi_interface_up_cb -+}; -+ -+/** -+ * Get current SPI4 initialization callbacks -+ * -+ * @callbacks: Pointer to the callbacks structure.to fill -+ * -+ * Returns Pointer to cvmx_spi_callbacks_t structure. -+ */ -+void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks) -+{ -+ memcpy(callbacks, &cvmx_spi_callbacks, sizeof(cvmx_spi_callbacks)); -+} -+ -+/** -+ * Set new SPI4 initialization callbacks -+ * -+ * @new_callbacks: Pointer to an updated callbacks structure. -+ */ -+void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks) -+{ -+ memcpy(&cvmx_spi_callbacks, new_callbacks, sizeof(cvmx_spi_callbacks)); -+} -+ -+/** -+ * Initialize and start the SPI interface. -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for clock synchronization in seconds -+ * @num_ports: Number of SPI ports to configure -+ * -+ * Returns Zero on success, negative of failure. -+ */ -+int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode, int timeout, -+ int num_ports) -+{ -+ int res = -1; -+ -+ if (!(OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))) -+ return res; -+ -+ /* Callback to perform SPI4 reset */ -+ INVOKE_CB(cvmx_spi_callbacks.reset_cb, interface, mode); -+ -+ /* Callback to perform calendar setup */ -+ INVOKE_CB(cvmx_spi_callbacks.calendar_setup_cb, interface, mode, -+ num_ports); -+ -+ /* Callback to perform clock detection */ -+ INVOKE_CB(cvmx_spi_callbacks.clock_detect_cb, interface, mode, timeout); -+ -+ /* Callback to perform SPI4 link training */ -+ INVOKE_CB(cvmx_spi_callbacks.training_cb, interface, mode, timeout); -+ -+ /* Callback to perform calendar sync */ -+ INVOKE_CB(cvmx_spi_callbacks.calendar_sync_cb, interface, mode, -+ timeout); -+ -+ /* Callback to handle interface coming up */ -+ INVOKE_CB(cvmx_spi_callbacks.interface_up_cb, interface, mode); -+ -+ return res; -+} -+ -+/** -+ * This routine restarts the SPI interface after it has lost synchronization -+ * with its correspondent system. -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for clock synchronization in seconds -+ * -+ * Returns Zero on success, negative of failure. -+ */ -+int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, int timeout) -+{ -+ int res = -1; -+ -+ if (!(OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))) -+ return res; -+ -+ cvmx_dprintf("SPI%d: Restart %s\n", interface, modes[mode]); -+ -+ /* Callback to perform SPI4 reset */ -+ INVOKE_CB(cvmx_spi_callbacks.reset_cb, interface, mode); -+ -+ /* NOTE: Calendar setup is not performed during restart */ -+ /* Refer to cvmx_spi_start_interface() for the full sequence */ -+ -+ /* Callback to perform clock detection */ -+ INVOKE_CB(cvmx_spi_callbacks.clock_detect_cb, interface, mode, timeout); -+ -+ /* Callback to perform SPI4 link training */ -+ INVOKE_CB(cvmx_spi_callbacks.training_cb, interface, mode, timeout); -+ -+ /* Callback to perform calendar sync */ -+ INVOKE_CB(cvmx_spi_callbacks.calendar_sync_cb, interface, mode, -+ timeout); -+ -+ /* Callback to handle interface coming up */ -+ INVOKE_CB(cvmx_spi_callbacks.interface_up_cb, interface, mode); -+ -+ return res; -+} -+ -+/** -+ * Callback to perform SPI4 reset -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode) -+{ -+ union cvmx_spxx_dbg_deskew_ctl spxx_dbg_deskew_ctl; -+ union cvmx_spxx_clk_ctl spxx_clk_ctl; -+ union cvmx_spxx_bist_stat spxx_bist_stat; -+ union cvmx_spxx_int_msk spxx_int_msk; -+ union cvmx_stxx_int_msk stxx_int_msk; -+ union cvmx_spxx_trn4_ctl spxx_trn4_ctl; -+ int index; -+ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; -+ -+ /* Disable SPI error events while we run BIST */ -+ spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); -+ stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); -+ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); -+ -+ /* Run BIST in the SPI interface */ -+ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), 0); -+ cvmx_write_csr(CVMX_STXX_COM_CTL(interface), 0); -+ spxx_clk_ctl.u64 = 0; -+ spxx_clk_ctl.s.runbist = 1; -+ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); -+ cvmx_wait(10 * MS); -+ spxx_bist_stat.u64 = cvmx_read_csr(CVMX_SPXX_BIST_STAT(interface)); -+ if (spxx_bist_stat.s.stat0) -+ cvmx_dprintf -+ ("ERROR SPI%d: BIST failed on receive datapath FIFO\n", -+ interface); -+ if (spxx_bist_stat.s.stat1) -+ cvmx_dprintf("ERROR SPI%d: BIST failed on RX calendar table\n", -+ interface); -+ if (spxx_bist_stat.s.stat2) -+ cvmx_dprintf("ERROR SPI%d: BIST failed on TX calendar table\n", -+ interface); -+ -+ /* Clear the calendar table after BIST to fix parity errors */ -+ for (index = 0; index < 32; index++) { -+ union cvmx_srxx_spi4_calx srxx_spi4_calx; -+ union cvmx_stxx_spi4_calx stxx_spi4_calx; -+ -+ srxx_spi4_calx.u64 = 0; -+ srxx_spi4_calx.s.oddpar = 1; -+ cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), -+ srxx_spi4_calx.u64); -+ -+ stxx_spi4_calx.u64 = 0; -+ stxx_spi4_calx.s.oddpar = 1; -+ cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), -+ stxx_spi4_calx.u64); -+ } -+ -+ /* Re enable reporting of error interrupts */ -+ cvmx_write_csr(CVMX_SPXX_INT_REG(interface), -+ cvmx_read_csr(CVMX_SPXX_INT_REG(interface))); -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); -+ cvmx_write_csr(CVMX_STXX_INT_REG(interface), -+ cvmx_read_csr(CVMX_STXX_INT_REG(interface))); -+ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); -+ -+ /* Setup the CLKDLY right in the middle */ -+ spxx_clk_ctl.u64 = 0; -+ spxx_clk_ctl.s.seetrn = 0; -+ spxx_clk_ctl.s.clkdly = 0x10; -+ spxx_clk_ctl.s.runbist = 0; -+ spxx_clk_ctl.s.statdrv = 0; -+ /* This should always be on the opposite edge as statdrv */ -+ spxx_clk_ctl.s.statrcv = 1; -+ spxx_clk_ctl.s.sndtrn = 0; -+ spxx_clk_ctl.s.drptrn = 0; -+ spxx_clk_ctl.s.rcvtrn = 0; -+ spxx_clk_ctl.s.srxdlck = 0; -+ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); -+ cvmx_wait(100 * MS); -+ -+ /* Reset SRX0 DLL */ -+ spxx_clk_ctl.s.srxdlck = 1; -+ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); -+ -+ /* Waiting for Inf0 Spi4 RX DLL to lock */ -+ cvmx_wait(100 * MS); -+ -+ /* Enable dynamic alignment */ -+ spxx_trn4_ctl.s.trntest = 0; -+ spxx_trn4_ctl.s.jitter = 1; -+ spxx_trn4_ctl.s.clr_boot = 1; -+ spxx_trn4_ctl.s.set_boot = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN58XX)) -+ spxx_trn4_ctl.s.maxdist = 3; -+ else -+ spxx_trn4_ctl.s.maxdist = 8; -+ spxx_trn4_ctl.s.macro_en = 1; -+ spxx_trn4_ctl.s.mux_en = 1; -+ cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64); -+ -+ spxx_dbg_deskew_ctl.u64 = 0; -+ cvmx_write_csr(CVMX_SPXX_DBG_DESKEW_CTL(interface), -+ spxx_dbg_deskew_ctl.u64); -+ -+ return 0; -+} -+ -+/** -+ * Callback to setup calendar and miscellaneous settings before clock detection -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @num_ports: Number of ports to configure on SPI -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode, -+ int num_ports) -+{ -+ int port; -+ int index; -+ if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { -+ union cvmx_srxx_com_ctl srxx_com_ctl; -+ union cvmx_srxx_spi4_stat srxx_spi4_stat; -+ -+ /* SRX0 number of Ports */ -+ srxx_com_ctl.u64 = 0; -+ srxx_com_ctl.s.prts = num_ports - 1; -+ srxx_com_ctl.s.st_en = 0; -+ srxx_com_ctl.s.inf_en = 0; -+ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); -+ -+ /* SRX0 Calendar Table. This round robbins through all ports */ -+ port = 0; -+ index = 0; -+ while (port < num_ports) { -+ union cvmx_srxx_spi4_calx srxx_spi4_calx; -+ srxx_spi4_calx.u64 = 0; -+ srxx_spi4_calx.s.prt0 = port++; -+ srxx_spi4_calx.s.prt1 = port++; -+ srxx_spi4_calx.s.prt2 = port++; -+ srxx_spi4_calx.s.prt3 = port++; -+ srxx_spi4_calx.s.oddpar = -+ ~(cvmx_dpop(srxx_spi4_calx.u64) & 1); -+ cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface), -+ srxx_spi4_calx.u64); -+ index++; -+ } -+ srxx_spi4_stat.u64 = 0; -+ srxx_spi4_stat.s.len = num_ports; -+ srxx_spi4_stat.s.m = 1; -+ cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface), -+ srxx_spi4_stat.u64); -+ } -+ -+ if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { -+ union cvmx_stxx_arb_ctl stxx_arb_ctl; -+ union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max; -+ union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh; -+ union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl; -+ union cvmx_stxx_spi4_stat stxx_spi4_stat; -+ union cvmx_stxx_spi4_dat stxx_spi4_dat; -+ -+ /* STX0 Config */ -+ stxx_arb_ctl.u64 = 0; -+ stxx_arb_ctl.s.igntpa = 0; -+ stxx_arb_ctl.s.mintrn = 0; -+ cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64); -+ -+ gmxx_tx_spi_max.u64 = 0; -+ gmxx_tx_spi_max.s.max1 = 8; -+ gmxx_tx_spi_max.s.max2 = 4; -+ gmxx_tx_spi_max.s.slice = 0; -+ cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface), -+ gmxx_tx_spi_max.u64); -+ -+ gmxx_tx_spi_thresh.u64 = 0; -+ gmxx_tx_spi_thresh.s.thresh = 4; -+ cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface), -+ gmxx_tx_spi_thresh.u64); -+ -+ gmxx_tx_spi_ctl.u64 = 0; -+ gmxx_tx_spi_ctl.s.tpa_clr = 0; -+ gmxx_tx_spi_ctl.s.cont_pkt = 0; -+ cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface), -+ gmxx_tx_spi_ctl.u64); -+ -+ /* STX0 Training Control */ -+ stxx_spi4_dat.u64 = 0; -+ /*Minimum needed by dynamic alignment */ -+ stxx_spi4_dat.s.alpha = 32; -+ stxx_spi4_dat.s.max_t = 0xFFFF; /*Minimum interval is 0x20 */ -+ cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface), -+ stxx_spi4_dat.u64); -+ -+ /* STX0 Calendar Table. This round robbins through all ports */ -+ port = 0; -+ index = 0; -+ while (port < num_ports) { -+ union cvmx_stxx_spi4_calx stxx_spi4_calx; -+ stxx_spi4_calx.u64 = 0; -+ stxx_spi4_calx.s.prt0 = port++; -+ stxx_spi4_calx.s.prt1 = port++; -+ stxx_spi4_calx.s.prt2 = port++; -+ stxx_spi4_calx.s.prt3 = port++; -+ stxx_spi4_calx.s.oddpar = -+ ~(cvmx_dpop(stxx_spi4_calx.u64) & 1); -+ cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface), -+ stxx_spi4_calx.u64); -+ index++; -+ } -+ stxx_spi4_stat.u64 = 0; -+ stxx_spi4_stat.s.len = num_ports; -+ stxx_spi4_stat.s.m = 1; -+ cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface), -+ stxx_spi4_stat.u64); -+ } -+ -+ return 0; -+} -+ -+/** -+ * Callback to perform clock detection -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for clock synchronization in seconds -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode, int timeout) -+{ -+ int clock_transitions; -+ union cvmx_spxx_clk_stat stat; -+ uint64_t timeout_time; -+ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; -+ -+ /* -+ * Regardless of operating mode, both Tx and Rx clocks must be -+ * present for the SPI interface to operate. -+ */ -+ cvmx_dprintf("SPI%d: Waiting to see TsClk...\n", interface); -+ timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; -+ /* -+ * Require 100 clock transitions in order to avoid any noise -+ * in the beginning. -+ */ -+ clock_transitions = 100; -+ do { -+ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); -+ if (stat.s.s4clk0 && stat.s.s4clk1 && clock_transitions) { -+ /* -+ * We've seen a clock transition, so decrement -+ * the number we still need. -+ */ -+ clock_transitions--; -+ cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64); -+ stat.s.s4clk0 = 0; -+ stat.s.s4clk1 = 0; -+ } -+ if (cvmx_get_cycle() > timeout_time) { -+ cvmx_dprintf("SPI%d: Timeout\n", interface); -+ return -1; -+ } -+ } while (stat.s.s4clk0 == 0 || stat.s.s4clk1 == 0); -+ -+ cvmx_dprintf("SPI%d: Waiting to see RsClk...\n", interface); -+ timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; -+ /* -+ * Require 100 clock transitions in order to avoid any noise in the -+ * beginning. -+ */ -+ clock_transitions = 100; -+ do { -+ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); -+ if (stat.s.d4clk0 && stat.s.d4clk1 && clock_transitions) { -+ /* -+ * We've seen a clock transition, so decrement -+ * the number we still need -+ */ -+ clock_transitions--; -+ cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64); -+ stat.s.d4clk0 = 0; -+ stat.s.d4clk1 = 0; -+ } -+ if (cvmx_get_cycle() > timeout_time) { -+ cvmx_dprintf("SPI%d: Timeout\n", interface); -+ return -1; -+ } -+ } while (stat.s.d4clk0 == 0 || stat.s.d4clk1 == 0); -+ -+ return 0; -+} -+ -+/** -+ * Callback to perform link training -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for link to be trained (in seconds) -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout) -+{ -+ union cvmx_spxx_trn4_ctl spxx_trn4_ctl; -+ union cvmx_spxx_clk_stat stat; -+ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; -+ uint64_t timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; -+ int rx_training_needed; -+ -+ /* SRX0 & STX0 Inf0 Links are configured - begin training */ -+ union cvmx_spxx_clk_ctl spxx_clk_ctl; -+ spxx_clk_ctl.u64 = 0; -+ spxx_clk_ctl.s.seetrn = 0; -+ spxx_clk_ctl.s.clkdly = 0x10; -+ spxx_clk_ctl.s.runbist = 0; -+ spxx_clk_ctl.s.statdrv = 0; -+ /* This should always be on the opposite edge as statdrv */ -+ spxx_clk_ctl.s.statrcv = 1; -+ spxx_clk_ctl.s.sndtrn = 1; -+ spxx_clk_ctl.s.drptrn = 1; -+ spxx_clk_ctl.s.rcvtrn = 1; -+ spxx_clk_ctl.s.srxdlck = 1; -+ cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); -+ cvmx_wait(1000 * MS); -+ -+ /* SRX0 clear the boot bit */ -+ spxx_trn4_ctl.u64 = cvmx_read_csr(CVMX_SPXX_TRN4_CTL(interface)); -+ spxx_trn4_ctl.s.clr_boot = 1; -+ cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64); -+ -+ /* Wait for the training sequence to complete */ -+ cvmx_dprintf("SPI%d: Waiting for training\n", interface); -+ cvmx_wait(1000 * MS); -+ /* Wait a really long time here */ -+ timeout_time = cvmx_get_cycle() + 1000ull * MS * 600; -+ /* -+ * The HRM says we must wait for 34 + 16 * MAXDIST training sequences. -+ * We'll be pessimistic and wait for a lot more. -+ */ -+ rx_training_needed = 500; -+ do { -+ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); -+ if (stat.s.srxtrn && rx_training_needed) { -+ rx_training_needed--; -+ cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64); -+ stat.s.srxtrn = 0; -+ } -+ if (cvmx_get_cycle() > timeout_time) { -+ cvmx_dprintf("SPI%d: Timeout\n", interface); -+ return -1; -+ } -+ } while (stat.s.srxtrn == 0); -+ -+ return 0; -+} -+ -+/** -+ * Callback to perform calendar data synchronization -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for calendar data in seconds -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, int timeout) -+{ -+ uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000; -+ if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { -+ /* SRX0 interface should be good, send calendar data */ -+ union cvmx_srxx_com_ctl srxx_com_ctl; -+ cvmx_dprintf -+ ("SPI%d: Rx is synchronized, start sending calendar data\n", -+ interface); -+ srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface)); -+ srxx_com_ctl.s.inf_en = 1; -+ srxx_com_ctl.s.st_en = 1; -+ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); -+ } -+ -+ if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { -+ /* STX0 has achieved sync */ -+ /* The corespondant board should be sending calendar data */ -+ /* Enable the STX0 STAT receiver. */ -+ union cvmx_spxx_clk_stat stat; -+ uint64_t timeout_time; -+ union cvmx_stxx_com_ctl stxx_com_ctl; -+ stxx_com_ctl.u64 = 0; -+ stxx_com_ctl.s.st_en = 1; -+ cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64); -+ -+ /* Waiting for calendar sync on STX0 STAT */ -+ cvmx_dprintf("SPI%d: Waiting to sync on STX[%d] STAT\n", -+ interface, interface); -+ timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout; -+ /* SPX0_CLK_STAT - SPX0_CLK_STAT[STXCAL] should be 1 (bit10) */ -+ do { -+ stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface)); -+ if (cvmx_get_cycle() > timeout_time) { -+ cvmx_dprintf("SPI%d: Timeout\n", interface); -+ return -1; -+ } -+ } while (stat.s.stxcal == 0); -+ } -+ -+ return 0; -+} -+ -+/** -+ * Callback to handle interface up -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode) -+{ -+ union cvmx_gmxx_rxx_frm_min gmxx_rxx_frm_min; -+ union cvmx_gmxx_rxx_frm_max gmxx_rxx_frm_max; -+ union cvmx_gmxx_rxx_jabber gmxx_rxx_jabber; -+ -+ if (mode & CVMX_SPI_MODE_RX_HALFPLEX) { -+ union cvmx_srxx_com_ctl srxx_com_ctl; -+ srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface)); -+ srxx_com_ctl.s.inf_en = 1; -+ cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64); -+ cvmx_dprintf("SPI%d: Rx is now up\n", interface); -+ } -+ -+ if (mode & CVMX_SPI_MODE_TX_HALFPLEX) { -+ union cvmx_stxx_com_ctl stxx_com_ctl; -+ stxx_com_ctl.u64 = cvmx_read_csr(CVMX_STXX_COM_CTL(interface)); -+ stxx_com_ctl.s.inf_en = 1; -+ cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64); -+ cvmx_dprintf("SPI%d: Tx is now up\n", interface); -+ } -+ -+ gmxx_rxx_frm_min.u64 = 0; -+ gmxx_rxx_frm_min.s.len = 64; -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MIN(0, interface), -+ gmxx_rxx_frm_min.u64); -+ gmxx_rxx_frm_max.u64 = 0; -+ gmxx_rxx_frm_max.s.len = 64 * 1024 - 4; -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(0, interface), -+ gmxx_rxx_frm_max.u64); -+ gmxx_rxx_jabber.u64 = 0; -+ gmxx_rxx_jabber.s.cnt = 64 * 1024 - 4; -+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER(0, interface), gmxx_rxx_jabber.u64); -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-spi.h -@@ -0,0 +1,269 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/* -+ * -+ * This file contains defines for the SPI interface -+ */ -+#ifndef __CVMX_SPI_H__ -+#define __CVMX_SPI_H__ -+ -+#include "cvmx-gmxx-defs.h" -+ -+/* CSR typedefs have been moved to cvmx-csr-*.h */ -+ -+typedef enum { -+ CVMX_SPI_MODE_UNKNOWN = 0, -+ CVMX_SPI_MODE_TX_HALFPLEX = 1, -+ CVMX_SPI_MODE_RX_HALFPLEX = 2, -+ CVMX_SPI_MODE_DUPLEX = 3 -+} cvmx_spi_mode_t; -+ -+/** Callbacks structure to customize SPI4 initialization sequence */ -+typedef struct { -+ /** Called to reset SPI4 DLL */ -+ int (*reset_cb) (int interface, cvmx_spi_mode_t mode); -+ -+ /** Called to setup calendar */ -+ int (*calendar_setup_cb) (int interface, cvmx_spi_mode_t mode, -+ int num_ports); -+ -+ /** Called for Tx and Rx clock detection */ -+ int (*clock_detect_cb) (int interface, cvmx_spi_mode_t mode, -+ int timeout); -+ -+ /** Called to perform link training */ -+ int (*training_cb) (int interface, cvmx_spi_mode_t mode, int timeout); -+ -+ /** Called for calendar data synchronization */ -+ int (*calendar_sync_cb) (int interface, cvmx_spi_mode_t mode, -+ int timeout); -+ -+ /** Called when interface is up */ -+ int (*interface_up_cb) (int interface, cvmx_spi_mode_t mode); -+ -+} cvmx_spi_callbacks_t; -+ -+/** -+ * Return true if the supplied interface is configured for SPI -+ * -+ * @interface: Interface to check -+ * Returns True if interface is SPI -+ */ -+static inline int cvmx_spi_is_spi_interface(int interface) -+{ -+ uint64_t gmxState = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); -+ return (gmxState & 0x2) && (gmxState & 0x1); -+} -+ -+/** -+ * Initialize and start the SPI interface. -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for clock synchronization in seconds -+ * @num_ports: Number of SPI ports to configure -+ * -+ * Returns Zero on success, negative of failure. -+ */ -+extern int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode, -+ int timeout, int num_ports); -+ -+/** -+ * This routine restarts the SPI interface after it has lost synchronization -+ * with its corespondant system. -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for clock synchronization in seconds -+ * Returns Zero on success, negative of failure. -+ */ -+extern int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, -+ int timeout); -+ -+/** -+ * Return non-zero if the SPI interface has a SPI4000 attached -+ * -+ * @interface: SPI interface the SPI4000 is connected to -+ * -+ * Returns -+ */ -+static inline int cvmx_spi4000_is_present(int interface) -+{ -+ return 0; -+} -+ -+/** -+ * Initialize the SPI4000 for use -+ * -+ * @interface: SPI interface the SPI4000 is connected to -+ */ -+static inline int cvmx_spi4000_initialize(int interface) -+{ -+ return 0; -+} -+ -+/** -+ * Poll all the SPI4000 port and check its speed -+ * -+ * @interface: Interface the SPI4000 is on -+ * @port: Port to poll (0-9) -+ * Returns Status of the port. 0=down. All other values the port is up. -+ */ -+static inline union cvmx_gmxx_rxx_rx_inbnd cvmx_spi4000_check_speed( -+ int interface, -+ int port) -+{ -+ union cvmx_gmxx_rxx_rx_inbnd r; -+ r.u64 = 0; -+ return r; -+} -+ -+/** -+ * Get current SPI4 initialization callbacks -+ * -+ * @callbacks: Pointer to the callbacks structure.to fill -+ * -+ * Returns Pointer to cvmx_spi_callbacks_t structure. -+ */ -+extern void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks); -+ -+/** -+ * Set new SPI4 initialization callbacks -+ * -+ * @new_callbacks: Pointer to an updated callbacks structure. -+ */ -+extern void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks); -+ -+/** -+ * Callback to perform SPI4 reset -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+extern int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode); -+ -+/** -+ * Callback to setup calendar and miscellaneous settings before clock -+ * detection -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @num_ports: Number of ports to configure on SPI -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+extern int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode, -+ int num_ports); -+ -+/** -+ * Callback to perform clock detection -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for clock synchronization in seconds -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+extern int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode, -+ int timeout); -+ -+/** -+ * Callback to perform link training -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for link to be trained (in seconds) -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+extern int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, -+ int timeout); -+ -+/** -+ * Callback to perform calendar data synchronization -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * @timeout: Timeout to wait for calendar data in seconds -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+extern int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, -+ int timeout); -+ -+/** -+ * Callback to handle interface up -+ * -+ * @interface: The identifier of the packet interface to configure and -+ * use as a SPI interface. -+ * @mode: The operating mode for the SPI interface. The interface -+ * can operate as a full duplex (both Tx and Rx data paths -+ * active) or as a halfplex (either the Tx data path is -+ * active or the Rx data path is active, but not both). -+ * -+ * Returns Zero on success, non-zero error code on failure (will cause -+ * SPI initialization to abort) -+ */ -+extern int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode); -+ -+#endif /* __CVMX_SPI_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-spxx-defs.h -@@ -0,0 +1,347 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_SPXX_DEFS_H__ -+#define __CVMX_SPXX_DEFS_H__ -+ -+#define CVMX_SPXX_BCKPRS_CNT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000340ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_BIST_STAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800900007F8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_CLK_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000348ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_CLK_STAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000350ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_DBG_DESKEW_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000368ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_DBG_DESKEW_STATE(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000370ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_DRV_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000358ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_ERR_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000320ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_INT_DAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000318ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_INT_MSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000308ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_INT_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000300ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_INT_SYNC(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000310ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_TPA_ACC(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000338ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_TPA_MAX(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000330ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_TPA_SEL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000328ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SPXX_TRN4_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000360ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_spxx_bckprs_cnt { -+ uint64_t u64; -+ struct cvmx_spxx_bckprs_cnt_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_spxx_bckprs_cnt_s cn38xx; -+ struct cvmx_spxx_bckprs_cnt_s cn38xxp2; -+ struct cvmx_spxx_bckprs_cnt_s cn58xx; -+ struct cvmx_spxx_bckprs_cnt_s cn58xxp1; -+}; -+ -+union cvmx_spxx_bist_stat { -+ uint64_t u64; -+ struct cvmx_spxx_bist_stat_s { -+ uint64_t reserved_3_63:61; -+ uint64_t stat2:1; -+ uint64_t stat1:1; -+ uint64_t stat0:1; -+ } s; -+ struct cvmx_spxx_bist_stat_s cn38xx; -+ struct cvmx_spxx_bist_stat_s cn38xxp2; -+ struct cvmx_spxx_bist_stat_s cn58xx; -+ struct cvmx_spxx_bist_stat_s cn58xxp1; -+}; -+ -+union cvmx_spxx_clk_ctl { -+ uint64_t u64; -+ struct cvmx_spxx_clk_ctl_s { -+ uint64_t reserved_17_63:47; -+ uint64_t seetrn:1; -+ uint64_t reserved_12_15:4; -+ uint64_t clkdly:5; -+ uint64_t runbist:1; -+ uint64_t statdrv:1; -+ uint64_t statrcv:1; -+ uint64_t sndtrn:1; -+ uint64_t drptrn:1; -+ uint64_t rcvtrn:1; -+ uint64_t srxdlck:1; -+ } s; -+ struct cvmx_spxx_clk_ctl_s cn38xx; -+ struct cvmx_spxx_clk_ctl_s cn38xxp2; -+ struct cvmx_spxx_clk_ctl_s cn58xx; -+ struct cvmx_spxx_clk_ctl_s cn58xxp1; -+}; -+ -+union cvmx_spxx_clk_stat { -+ uint64_t u64; -+ struct cvmx_spxx_clk_stat_s { -+ uint64_t reserved_11_63:53; -+ uint64_t stxcal:1; -+ uint64_t reserved_9_9:1; -+ uint64_t srxtrn:1; -+ uint64_t s4clk1:1; -+ uint64_t s4clk0:1; -+ uint64_t d4clk1:1; -+ uint64_t d4clk0:1; -+ uint64_t reserved_0_3:4; -+ } s; -+ struct cvmx_spxx_clk_stat_s cn38xx; -+ struct cvmx_spxx_clk_stat_s cn38xxp2; -+ struct cvmx_spxx_clk_stat_s cn58xx; -+ struct cvmx_spxx_clk_stat_s cn58xxp1; -+}; -+ -+union cvmx_spxx_dbg_deskew_ctl { -+ uint64_t u64; -+ struct cvmx_spxx_dbg_deskew_ctl_s { -+ uint64_t reserved_30_63:34; -+ uint64_t fallnop:1; -+ uint64_t fall8:1; -+ uint64_t reserved_26_27:2; -+ uint64_t sstep_go:1; -+ uint64_t sstep:1; -+ uint64_t reserved_22_23:2; -+ uint64_t clrdly:1; -+ uint64_t dec:1; -+ uint64_t inc:1; -+ uint64_t mux:1; -+ uint64_t offset:5; -+ uint64_t bitsel:5; -+ uint64_t offdly:6; -+ uint64_t dllfrc:1; -+ uint64_t dlldis:1; -+ } s; -+ struct cvmx_spxx_dbg_deskew_ctl_s cn38xx; -+ struct cvmx_spxx_dbg_deskew_ctl_s cn38xxp2; -+ struct cvmx_spxx_dbg_deskew_ctl_s cn58xx; -+ struct cvmx_spxx_dbg_deskew_ctl_s cn58xxp1; -+}; -+ -+union cvmx_spxx_dbg_deskew_state { -+ uint64_t u64; -+ struct cvmx_spxx_dbg_deskew_state_s { -+ uint64_t reserved_9_63:55; -+ uint64_t testres:1; -+ uint64_t unxterm:1; -+ uint64_t muxsel:2; -+ uint64_t offset:5; -+ } s; -+ struct cvmx_spxx_dbg_deskew_state_s cn38xx; -+ struct cvmx_spxx_dbg_deskew_state_s cn38xxp2; -+ struct cvmx_spxx_dbg_deskew_state_s cn58xx; -+ struct cvmx_spxx_dbg_deskew_state_s cn58xxp1; -+}; -+ -+union cvmx_spxx_drv_ctl { -+ uint64_t u64; -+ struct cvmx_spxx_drv_ctl_s { -+ uint64_t reserved_0_63:64; -+ } s; -+ struct cvmx_spxx_drv_ctl_cn38xx { -+ uint64_t reserved_16_63:48; -+ uint64_t stx4ncmp:4; -+ uint64_t stx4pcmp:4; -+ uint64_t srx4cmp:8; -+ } cn38xx; -+ struct cvmx_spxx_drv_ctl_cn38xx cn38xxp2; -+ struct cvmx_spxx_drv_ctl_cn58xx { -+ uint64_t reserved_24_63:40; -+ uint64_t stx4ncmp:4; -+ uint64_t stx4pcmp:4; -+ uint64_t reserved_10_15:6; -+ uint64_t srx4cmp:10; -+ } cn58xx; -+ struct cvmx_spxx_drv_ctl_cn58xx cn58xxp1; -+}; -+ -+union cvmx_spxx_err_ctl { -+ uint64_t u64; -+ struct cvmx_spxx_err_ctl_s { -+ uint64_t reserved_9_63:55; -+ uint64_t prtnxa:1; -+ uint64_t dipcls:1; -+ uint64_t dippay:1; -+ uint64_t reserved_4_5:2; -+ uint64_t errcnt:4; -+ } s; -+ struct cvmx_spxx_err_ctl_s cn38xx; -+ struct cvmx_spxx_err_ctl_s cn38xxp2; -+ struct cvmx_spxx_err_ctl_s cn58xx; -+ struct cvmx_spxx_err_ctl_s cn58xxp1; -+}; -+ -+union cvmx_spxx_int_dat { -+ uint64_t u64; -+ struct cvmx_spxx_int_dat_s { -+ uint64_t reserved_32_63:32; -+ uint64_t mul:1; -+ uint64_t reserved_14_30:17; -+ uint64_t calbnk:2; -+ uint64_t rsvop:4; -+ uint64_t prt:8; -+ } s; -+ struct cvmx_spxx_int_dat_s cn38xx; -+ struct cvmx_spxx_int_dat_s cn38xxp2; -+ struct cvmx_spxx_int_dat_s cn58xx; -+ struct cvmx_spxx_int_dat_s cn58xxp1; -+}; -+ -+union cvmx_spxx_int_msk { -+ uint64_t u64; -+ struct cvmx_spxx_int_msk_s { -+ uint64_t reserved_12_63:52; -+ uint64_t calerr:1; -+ uint64_t syncerr:1; -+ uint64_t diperr:1; -+ uint64_t tpaovr:1; -+ uint64_t rsverr:1; -+ uint64_t drwnng:1; -+ uint64_t clserr:1; -+ uint64_t spiovr:1; -+ uint64_t reserved_2_3:2; -+ uint64_t abnorm:1; -+ uint64_t prtnxa:1; -+ } s; -+ struct cvmx_spxx_int_msk_s cn38xx; -+ struct cvmx_spxx_int_msk_s cn38xxp2; -+ struct cvmx_spxx_int_msk_s cn58xx; -+ struct cvmx_spxx_int_msk_s cn58xxp1; -+}; -+ -+union cvmx_spxx_int_reg { -+ uint64_t u64; -+ struct cvmx_spxx_int_reg_s { -+ uint64_t reserved_32_63:32; -+ uint64_t spf:1; -+ uint64_t reserved_12_30:19; -+ uint64_t calerr:1; -+ uint64_t syncerr:1; -+ uint64_t diperr:1; -+ uint64_t tpaovr:1; -+ uint64_t rsverr:1; -+ uint64_t drwnng:1; -+ uint64_t clserr:1; -+ uint64_t spiovr:1; -+ uint64_t reserved_2_3:2; -+ uint64_t abnorm:1; -+ uint64_t prtnxa:1; -+ } s; -+ struct cvmx_spxx_int_reg_s cn38xx; -+ struct cvmx_spxx_int_reg_s cn38xxp2; -+ struct cvmx_spxx_int_reg_s cn58xx; -+ struct cvmx_spxx_int_reg_s cn58xxp1; -+}; -+ -+union cvmx_spxx_int_sync { -+ uint64_t u64; -+ struct cvmx_spxx_int_sync_s { -+ uint64_t reserved_12_63:52; -+ uint64_t calerr:1; -+ uint64_t syncerr:1; -+ uint64_t diperr:1; -+ uint64_t tpaovr:1; -+ uint64_t rsverr:1; -+ uint64_t drwnng:1; -+ uint64_t clserr:1; -+ uint64_t spiovr:1; -+ uint64_t reserved_2_3:2; -+ uint64_t abnorm:1; -+ uint64_t prtnxa:1; -+ } s; -+ struct cvmx_spxx_int_sync_s cn38xx; -+ struct cvmx_spxx_int_sync_s cn38xxp2; -+ struct cvmx_spxx_int_sync_s cn58xx; -+ struct cvmx_spxx_int_sync_s cn58xxp1; -+}; -+ -+union cvmx_spxx_tpa_acc { -+ uint64_t u64; -+ struct cvmx_spxx_tpa_acc_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_spxx_tpa_acc_s cn38xx; -+ struct cvmx_spxx_tpa_acc_s cn38xxp2; -+ struct cvmx_spxx_tpa_acc_s cn58xx; -+ struct cvmx_spxx_tpa_acc_s cn58xxp1; -+}; -+ -+union cvmx_spxx_tpa_max { -+ uint64_t u64; -+ struct cvmx_spxx_tpa_max_s { -+ uint64_t reserved_32_63:32; -+ uint64_t max:32; -+ } s; -+ struct cvmx_spxx_tpa_max_s cn38xx; -+ struct cvmx_spxx_tpa_max_s cn38xxp2; -+ struct cvmx_spxx_tpa_max_s cn58xx; -+ struct cvmx_spxx_tpa_max_s cn58xxp1; -+}; -+ -+union cvmx_spxx_tpa_sel { -+ uint64_t u64; -+ struct cvmx_spxx_tpa_sel_s { -+ uint64_t reserved_4_63:60; -+ uint64_t prtsel:4; -+ } s; -+ struct cvmx_spxx_tpa_sel_s cn38xx; -+ struct cvmx_spxx_tpa_sel_s cn38xxp2; -+ struct cvmx_spxx_tpa_sel_s cn58xx; -+ struct cvmx_spxx_tpa_sel_s cn58xxp1; -+}; -+ -+union cvmx_spxx_trn4_ctl { -+ uint64_t u64; -+ struct cvmx_spxx_trn4_ctl_s { -+ uint64_t reserved_13_63:51; -+ uint64_t trntest:1; -+ uint64_t jitter:3; -+ uint64_t clr_boot:1; -+ uint64_t set_boot:1; -+ uint64_t maxdist:5; -+ uint64_t macro_en:1; -+ uint64_t mux_en:1; -+ } s; -+ struct cvmx_spxx_trn4_ctl_s cn38xx; -+ struct cvmx_spxx_trn4_ctl_s cn38xxp2; -+ struct cvmx_spxx_trn4_ctl_s cn58xx; -+ struct cvmx_spxx_trn4_ctl_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-srxx-defs.h -@@ -0,0 +1,126 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_SRXX_DEFS_H__ -+#define __CVMX_SRXX_DEFS_H__ -+ -+#define CVMX_SRXX_COM_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000200ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SRXX_IGN_RX_FULL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000218ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SRXX_SPI4_CALX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000000ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SRXX_SPI4_STAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000208ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SRXX_SW_TICK_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000220ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_SRXX_SW_TICK_DAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000228ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_srxx_com_ctl { -+ uint64_t u64; -+ struct cvmx_srxx_com_ctl_s { -+ uint64_t reserved_8_63:56; -+ uint64_t prts:4; -+ uint64_t st_en:1; -+ uint64_t reserved_1_2:2; -+ uint64_t inf_en:1; -+ } s; -+ struct cvmx_srxx_com_ctl_s cn38xx; -+ struct cvmx_srxx_com_ctl_s cn38xxp2; -+ struct cvmx_srxx_com_ctl_s cn58xx; -+ struct cvmx_srxx_com_ctl_s cn58xxp1; -+}; -+ -+union cvmx_srxx_ign_rx_full { -+ uint64_t u64; -+ struct cvmx_srxx_ign_rx_full_s { -+ uint64_t reserved_16_63:48; -+ uint64_t ignore:16; -+ } s; -+ struct cvmx_srxx_ign_rx_full_s cn38xx; -+ struct cvmx_srxx_ign_rx_full_s cn38xxp2; -+ struct cvmx_srxx_ign_rx_full_s cn58xx; -+ struct cvmx_srxx_ign_rx_full_s cn58xxp1; -+}; -+ -+union cvmx_srxx_spi4_calx { -+ uint64_t u64; -+ struct cvmx_srxx_spi4_calx_s { -+ uint64_t reserved_17_63:47; -+ uint64_t oddpar:1; -+ uint64_t prt3:4; -+ uint64_t prt2:4; -+ uint64_t prt1:4; -+ uint64_t prt0:4; -+ } s; -+ struct cvmx_srxx_spi4_calx_s cn38xx; -+ struct cvmx_srxx_spi4_calx_s cn38xxp2; -+ struct cvmx_srxx_spi4_calx_s cn58xx; -+ struct cvmx_srxx_spi4_calx_s cn58xxp1; -+}; -+ -+union cvmx_srxx_spi4_stat { -+ uint64_t u64; -+ struct cvmx_srxx_spi4_stat_s { -+ uint64_t reserved_16_63:48; -+ uint64_t m:8; -+ uint64_t reserved_7_7:1; -+ uint64_t len:7; -+ } s; -+ struct cvmx_srxx_spi4_stat_s cn38xx; -+ struct cvmx_srxx_spi4_stat_s cn38xxp2; -+ struct cvmx_srxx_spi4_stat_s cn58xx; -+ struct cvmx_srxx_spi4_stat_s cn58xxp1; -+}; -+ -+union cvmx_srxx_sw_tick_ctl { -+ uint64_t u64; -+ struct cvmx_srxx_sw_tick_ctl_s { -+ uint64_t reserved_14_63:50; -+ uint64_t eop:1; -+ uint64_t sop:1; -+ uint64_t mod:4; -+ uint64_t opc:4; -+ uint64_t adr:4; -+ } s; -+ struct cvmx_srxx_sw_tick_ctl_s cn38xx; -+ struct cvmx_srxx_sw_tick_ctl_s cn58xx; -+ struct cvmx_srxx_sw_tick_ctl_s cn58xxp1; -+}; -+ -+union cvmx_srxx_sw_tick_dat { -+ uint64_t u64; -+ struct cvmx_srxx_sw_tick_dat_s { -+ uint64_t dat:64; -+ } s; -+ struct cvmx_srxx_sw_tick_dat_s cn38xx; -+ struct cvmx_srxx_sw_tick_dat_s cn58xx; -+ struct cvmx_srxx_sw_tick_dat_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-stxx-defs.h -@@ -0,0 +1,292 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_STXX_DEFS_H__ -+#define __CVMX_STXX_DEFS_H__ -+ -+#define CVMX_STXX_ARB_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000608ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_BCKPRS_CNT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000688ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_COM_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000600ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_DIP_CNT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000690ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_IGN_CAL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000610ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_INT_MSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800900006A0ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_INT_REG(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000698ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_INT_SYNC(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800900006A8ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_MIN_BST(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000618ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_SPI4_CALX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000400ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_SPI4_DAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000628ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_SPI4_STAT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000630ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_STAT_BYTES_HI(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000648ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_STAT_BYTES_LO(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000680ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_STAT_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000638ull + (((block_id) & 1) * 0x8000000ull)) -+#define CVMX_STXX_STAT_PKT_XMT(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180090000640ull + (((block_id) & 1) * 0x8000000ull)) -+ -+union cvmx_stxx_arb_ctl { -+ uint64_t u64; -+ struct cvmx_stxx_arb_ctl_s { -+ uint64_t reserved_6_63:58; -+ uint64_t mintrn:1; -+ uint64_t reserved_4_4:1; -+ uint64_t igntpa:1; -+ uint64_t reserved_0_2:3; -+ } s; -+ struct cvmx_stxx_arb_ctl_s cn38xx; -+ struct cvmx_stxx_arb_ctl_s cn38xxp2; -+ struct cvmx_stxx_arb_ctl_s cn58xx; -+ struct cvmx_stxx_arb_ctl_s cn58xxp1; -+}; -+ -+union cvmx_stxx_bckprs_cnt { -+ uint64_t u64; -+ struct cvmx_stxx_bckprs_cnt_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_stxx_bckprs_cnt_s cn38xx; -+ struct cvmx_stxx_bckprs_cnt_s cn38xxp2; -+ struct cvmx_stxx_bckprs_cnt_s cn58xx; -+ struct cvmx_stxx_bckprs_cnt_s cn58xxp1; -+}; -+ -+union cvmx_stxx_com_ctl { -+ uint64_t u64; -+ struct cvmx_stxx_com_ctl_s { -+ uint64_t reserved_4_63:60; -+ uint64_t st_en:1; -+ uint64_t reserved_1_2:2; -+ uint64_t inf_en:1; -+ } s; -+ struct cvmx_stxx_com_ctl_s cn38xx; -+ struct cvmx_stxx_com_ctl_s cn38xxp2; -+ struct cvmx_stxx_com_ctl_s cn58xx; -+ struct cvmx_stxx_com_ctl_s cn58xxp1; -+}; -+ -+union cvmx_stxx_dip_cnt { -+ uint64_t u64; -+ struct cvmx_stxx_dip_cnt_s { -+ uint64_t reserved_8_63:56; -+ uint64_t frmmax:4; -+ uint64_t dipmax:4; -+ } s; -+ struct cvmx_stxx_dip_cnt_s cn38xx; -+ struct cvmx_stxx_dip_cnt_s cn38xxp2; -+ struct cvmx_stxx_dip_cnt_s cn58xx; -+ struct cvmx_stxx_dip_cnt_s cn58xxp1; -+}; -+ -+union cvmx_stxx_ign_cal { -+ uint64_t u64; -+ struct cvmx_stxx_ign_cal_s { -+ uint64_t reserved_16_63:48; -+ uint64_t igntpa:16; -+ } s; -+ struct cvmx_stxx_ign_cal_s cn38xx; -+ struct cvmx_stxx_ign_cal_s cn38xxp2; -+ struct cvmx_stxx_ign_cal_s cn58xx; -+ struct cvmx_stxx_ign_cal_s cn58xxp1; -+}; -+ -+union cvmx_stxx_int_msk { -+ uint64_t u64; -+ struct cvmx_stxx_int_msk_s { -+ uint64_t reserved_8_63:56; -+ uint64_t frmerr:1; -+ uint64_t unxfrm:1; -+ uint64_t nosync:1; -+ uint64_t diperr:1; -+ uint64_t datovr:1; -+ uint64_t ovrbst:1; -+ uint64_t calpar1:1; -+ uint64_t calpar0:1; -+ } s; -+ struct cvmx_stxx_int_msk_s cn38xx; -+ struct cvmx_stxx_int_msk_s cn38xxp2; -+ struct cvmx_stxx_int_msk_s cn58xx; -+ struct cvmx_stxx_int_msk_s cn58xxp1; -+}; -+ -+union cvmx_stxx_int_reg { -+ uint64_t u64; -+ struct cvmx_stxx_int_reg_s { -+ uint64_t reserved_9_63:55; -+ uint64_t syncerr:1; -+ uint64_t frmerr:1; -+ uint64_t unxfrm:1; -+ uint64_t nosync:1; -+ uint64_t diperr:1; -+ uint64_t datovr:1; -+ uint64_t ovrbst:1; -+ uint64_t calpar1:1; -+ uint64_t calpar0:1; -+ } s; -+ struct cvmx_stxx_int_reg_s cn38xx; -+ struct cvmx_stxx_int_reg_s cn38xxp2; -+ struct cvmx_stxx_int_reg_s cn58xx; -+ struct cvmx_stxx_int_reg_s cn58xxp1; -+}; -+ -+union cvmx_stxx_int_sync { -+ uint64_t u64; -+ struct cvmx_stxx_int_sync_s { -+ uint64_t reserved_8_63:56; -+ uint64_t frmerr:1; -+ uint64_t unxfrm:1; -+ uint64_t nosync:1; -+ uint64_t diperr:1; -+ uint64_t datovr:1; -+ uint64_t ovrbst:1; -+ uint64_t calpar1:1; -+ uint64_t calpar0:1; -+ } s; -+ struct cvmx_stxx_int_sync_s cn38xx; -+ struct cvmx_stxx_int_sync_s cn38xxp2; -+ struct cvmx_stxx_int_sync_s cn58xx; -+ struct cvmx_stxx_int_sync_s cn58xxp1; -+}; -+ -+union cvmx_stxx_min_bst { -+ uint64_t u64; -+ struct cvmx_stxx_min_bst_s { -+ uint64_t reserved_9_63:55; -+ uint64_t minb:9; -+ } s; -+ struct cvmx_stxx_min_bst_s cn38xx; -+ struct cvmx_stxx_min_bst_s cn38xxp2; -+ struct cvmx_stxx_min_bst_s cn58xx; -+ struct cvmx_stxx_min_bst_s cn58xxp1; -+}; -+ -+union cvmx_stxx_spi4_calx { -+ uint64_t u64; -+ struct cvmx_stxx_spi4_calx_s { -+ uint64_t reserved_17_63:47; -+ uint64_t oddpar:1; -+ uint64_t prt3:4; -+ uint64_t prt2:4; -+ uint64_t prt1:4; -+ uint64_t prt0:4; -+ } s; -+ struct cvmx_stxx_spi4_calx_s cn38xx; -+ struct cvmx_stxx_spi4_calx_s cn38xxp2; -+ struct cvmx_stxx_spi4_calx_s cn58xx; -+ struct cvmx_stxx_spi4_calx_s cn58xxp1; -+}; -+ -+union cvmx_stxx_spi4_dat { -+ uint64_t u64; -+ struct cvmx_stxx_spi4_dat_s { -+ uint64_t reserved_32_63:32; -+ uint64_t alpha:16; -+ uint64_t max_t:16; -+ } s; -+ struct cvmx_stxx_spi4_dat_s cn38xx; -+ struct cvmx_stxx_spi4_dat_s cn38xxp2; -+ struct cvmx_stxx_spi4_dat_s cn58xx; -+ struct cvmx_stxx_spi4_dat_s cn58xxp1; -+}; -+ -+union cvmx_stxx_spi4_stat { -+ uint64_t u64; -+ struct cvmx_stxx_spi4_stat_s { -+ uint64_t reserved_16_63:48; -+ uint64_t m:8; -+ uint64_t reserved_7_7:1; -+ uint64_t len:7; -+ } s; -+ struct cvmx_stxx_spi4_stat_s cn38xx; -+ struct cvmx_stxx_spi4_stat_s cn38xxp2; -+ struct cvmx_stxx_spi4_stat_s cn58xx; -+ struct cvmx_stxx_spi4_stat_s cn58xxp1; -+}; -+ -+union cvmx_stxx_stat_bytes_hi { -+ uint64_t u64; -+ struct cvmx_stxx_stat_bytes_hi_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_stxx_stat_bytes_hi_s cn38xx; -+ struct cvmx_stxx_stat_bytes_hi_s cn38xxp2; -+ struct cvmx_stxx_stat_bytes_hi_s cn58xx; -+ struct cvmx_stxx_stat_bytes_hi_s cn58xxp1; -+}; -+ -+union cvmx_stxx_stat_bytes_lo { -+ uint64_t u64; -+ struct cvmx_stxx_stat_bytes_lo_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_stxx_stat_bytes_lo_s cn38xx; -+ struct cvmx_stxx_stat_bytes_lo_s cn38xxp2; -+ struct cvmx_stxx_stat_bytes_lo_s cn58xx; -+ struct cvmx_stxx_stat_bytes_lo_s cn58xxp1; -+}; -+ -+union cvmx_stxx_stat_ctl { -+ uint64_t u64; -+ struct cvmx_stxx_stat_ctl_s { -+ uint64_t reserved_5_63:59; -+ uint64_t clr:1; -+ uint64_t bckprs:4; -+ } s; -+ struct cvmx_stxx_stat_ctl_s cn38xx; -+ struct cvmx_stxx_stat_ctl_s cn38xxp2; -+ struct cvmx_stxx_stat_ctl_s cn58xx; -+ struct cvmx_stxx_stat_ctl_s cn58xxp1; -+}; -+ -+union cvmx_stxx_stat_pkt_xmt { -+ uint64_t u64; -+ struct cvmx_stxx_stat_pkt_xmt_s { -+ uint64_t reserved_32_63:32; -+ uint64_t cnt:32; -+ } s; -+ struct cvmx_stxx_stat_pkt_xmt_s cn38xx; -+ struct cvmx_stxx_stat_pkt_xmt_s cn38xxp2; -+ struct cvmx_stxx_stat_pkt_xmt_s cn58xx; -+ struct cvmx_stxx_stat_pkt_xmt_s cn58xxp1; -+}; -+ -+#endif ---- /dev/null -+++ b/drivers/staging/octeon/cvmx-wqe.h -@@ -0,0 +1,397 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+/** -+ * -+ * This header file defines the work queue entry (wqe) data structure. -+ * Since this is a commonly used structure that depends on structures -+ * from several hardware blocks, those definitions have been placed -+ * in this file to create a single point of definition of the wqe -+ * format. -+ * Data structures are still named according to the block that they -+ * relate to. -+ * -+ */ -+ -+#ifndef __CVMX_WQE_H__ -+#define __CVMX_WQE_H__ -+ -+#include "cvmx-packet.h" -+ -+ -+#define OCT_TAG_TYPE_STRING(x) \ -+ (((x) == CVMX_POW_TAG_TYPE_ORDERED) ? "ORDERED" : \ -+ (((x) == CVMX_POW_TAG_TYPE_ATOMIC) ? "ATOMIC" : \ -+ (((x) == CVMX_POW_TAG_TYPE_NULL) ? "NULL" : \ -+ "NULL_NULL"))) -+ -+/** -+ * HW decode / err_code in work queue entry -+ */ -+typedef union { -+ uint64_t u64; -+ -+ /* Use this struct if the hardware determines that the packet is IP */ -+ struct { -+ /* HW sets this to the number of buffers used by this packet */ -+ uint64_t bufs:8; -+ /* HW sets to the number of L2 bytes prior to the IP */ -+ uint64_t ip_offset:8; -+ /* set to 1 if we found DSA/VLAN in the L2 */ -+ uint64_t vlan_valid:1; -+ /* Set to 1 if the DSA/VLAN tag is stacked */ -+ uint64_t vlan_stacked:1; -+ uint64_t unassigned:1; -+ /* HW sets to the DSA/VLAN CFI flag (valid when vlan_valid) */ -+ uint64_t vlan_cfi:1; -+ /* HW sets to the DSA/VLAN_ID field (valid when vlan_valid) */ -+ uint64_t vlan_id:12; -+ /* Ring Identifier (if PCIe). Requires PIP_GBL_CTL[RING_EN]=1 */ -+ uint64_t pr:4; -+ uint64_t unassigned2:8; -+ /* the packet needs to be decompressed */ -+ uint64_t dec_ipcomp:1; -+ /* the packet is either TCP or UDP */ -+ uint64_t tcp_or_udp:1; -+ /* the packet needs to be decrypted (ESP or AH) */ -+ uint64_t dec_ipsec:1; -+ /* the packet is IPv6 */ -+ uint64_t is_v6:1; -+ -+ /* -+ * (rcv_error, not_IP, IP_exc, is_frag, L4_error, -+ * software, etc.). -+ */ -+ -+ /* -+ * reserved for software use, hardware will clear on -+ * packet creation. -+ */ -+ uint64_t software:1; -+ /* exceptional conditions below */ -+ /* the receive interface hardware detected an L4 error -+ * (only applies if !is_frag) (only applies if -+ * !rcv_error && !not_IP && !IP_exc && !is_frag) -+ * failure indicated in err_code below, decode: -+ * -+ * - 1 = Malformed L4 -+ * - 2 = L4 Checksum Error: the L4 checksum value is -+ * - 3 = UDP Length Error: The UDP length field would -+ * make the UDP data longer than what remains in -+ * the IP packet (as defined by the IP header -+ * length field). -+ * - 4 = Bad L4 Port: either the source or destination -+ * TCP/UDP port is 0. -+ * - 8 = TCP FIN Only: the packet is TCP and only the -+ * FIN flag set. -+ * - 9 = TCP No Flags: the packet is TCP and no flags -+ * are set. -+ * - 10 = TCP FIN RST: the packet is TCP and both FIN -+ * and RST are set. -+ * - 11 = TCP SYN URG: the packet is TCP and both SYN -+ * and URG are set. -+ * - 12 = TCP SYN RST: the packet is TCP and both SYN -+ * and RST are set. -+ * - 13 = TCP SYN FIN: the packet is TCP and both SYN -+ * and FIN are set. -+ */ -+ uint64_t L4_error:1; -+ /* set if the packet is a fragment */ -+ uint64_t is_frag:1; -+ /* the receive interface hardware detected an IP error -+ * / exception (only applies if !rcv_error && !not_IP) -+ * failure indicated in err_code below, decode: -+ * -+ * - 1 = Not IP: the IP version field is neither 4 nor -+ * 6. -+ * - 2 = IPv4 Header Checksum Error: the IPv4 header -+ * has a checksum violation. -+ * - 3 = IP Malformed Header: the packet is not long -+ * enough to contain the IP header. -+ * - 4 = IP Malformed: the packet is not long enough -+ * to contain the bytes indicated by the IP -+ * header. Pad is allowed. -+ * - 5 = IP TTL Hop: the IPv4 TTL field or the IPv6 -+ * Hop Count field are zero. -+ * - 6 = IP Options -+ */ -+ uint64_t IP_exc:1; -+ /* -+ * Set if the hardware determined that the packet is a -+ * broadcast. -+ */ -+ uint64_t is_bcast:1; -+ /* -+ * St if the hardware determined that the packet is a -+ * multi-cast. -+ */ -+ uint64_t is_mcast:1; -+ /* -+ * Set if the packet may not be IP (must be zero in -+ * this case). -+ */ -+ uint64_t not_IP:1; -+ /* -+ * The receive interface hardware detected a receive -+ * error (must be zero in this case). -+ */ -+ uint64_t rcv_error:1; -+ /* lower err_code = first-level descriptor of the -+ * work */ -+ /* zero for packet submitted by hardware that isn't on -+ * the slow path */ -+ /* type is cvmx_pip_err_t */ -+ uint64_t err_code:8; -+ } s; -+ -+ /* use this to get at the 16 vlan bits */ -+ struct { -+ uint64_t unused1:16; -+ uint64_t vlan:16; -+ uint64_t unused2:32; -+ } svlan; -+ -+ /* -+ * use this struct if the hardware could not determine that -+ * the packet is ip. -+ */ -+ struct { -+ /* -+ * HW sets this to the number of buffers used by this -+ * packet. -+ */ -+ uint64_t bufs:8; -+ uint64_t unused:8; -+ /* set to 1 if we found DSA/VLAN in the L2 */ -+ uint64_t vlan_valid:1; -+ /* Set to 1 if the DSA/VLAN tag is stacked */ -+ uint64_t vlan_stacked:1; -+ uint64_t unassigned:1; -+ /* -+ * HW sets to the DSA/VLAN CFI flag (valid when -+ * vlan_valid) -+ */ -+ uint64_t vlan_cfi:1; -+ /* -+ * HW sets to the DSA/VLAN_ID field (valid when -+ * vlan_valid). -+ */ -+ uint64_t vlan_id:12; -+ /* -+ * Ring Identifier (if PCIe). Requires -+ * PIP_GBL_CTL[RING_EN]=1 -+ */ -+ uint64_t pr:4; -+ uint64_t unassigned2:12; -+ /* -+ * reserved for software use, hardware will clear on -+ * packet creation. -+ */ -+ uint64_t software:1; -+ uint64_t unassigned3:1; -+ /* -+ * set if the hardware determined that the packet is -+ * rarp. -+ */ -+ uint64_t is_rarp:1; -+ /* -+ * set if the hardware determined that the packet is -+ * arp -+ */ -+ uint64_t is_arp:1; -+ /* -+ * set if the hardware determined that the packet is a -+ * broadcast. -+ */ -+ uint64_t is_bcast:1; -+ /* -+ * set if the hardware determined that the packet is a -+ * multi-cast -+ */ -+ uint64_t is_mcast:1; -+ /* -+ * set if the packet may not be IP (must be one in -+ * this case) -+ */ -+ uint64_t not_IP:1; -+ /* The receive interface hardware detected a receive -+ * error. Failure indicated in err_code below, -+ * decode: -+ * -+ * - 1 = partial error: a packet was partially -+ * received, but internal buffering / bandwidth -+ * was not adequate to receive the entire -+ * packet. -+ * - 2 = jabber error: the RGMII packet was too large -+ * and is truncated. -+ * - 3 = overrun error: the RGMII packet is longer -+ * than allowed and had an FCS error. -+ * - 4 = oversize error: the RGMII packet is longer -+ * than allowed. -+ * - 5 = alignment error: the RGMII packet is not an -+ * integer number of bytes -+ * and had an FCS error (100M and 10M only). -+ * - 6 = fragment error: the RGMII packet is shorter -+ * than allowed and had an FCS error. -+ * - 7 = GMX FCS error: the RGMII packet had an FCS -+ * error. -+ * - 8 = undersize error: the RGMII packet is shorter -+ * than allowed. -+ * - 9 = extend error: the RGMII packet had an extend -+ * error. -+ * - 10 = length mismatch error: the RGMII packet had -+ * a length that did not match the length field -+ * in the L2 HDR. -+ * - 11 = RGMII RX error/SPI4 DIP4 Error: the RGMII -+ * packet had one or more data reception errors -+ * (RXERR) or the SPI4 packet had one or more -+ * DIP4 errors. -+ * - 12 = RGMII skip error/SPI4 Abort Error: the RGMII -+ * packet was not large enough to cover the -+ * skipped bytes or the SPI4 packet was -+ * terminated with an About EOPS. -+ * - 13 = RGMII nibble error/SPI4 Port NXA Error: the -+ * RGMII packet had a studder error (data not -+ * repeated - 10/100M only) or the SPI4 packet -+ * was sent to an NXA. -+ * - 16 = FCS error: a SPI4.2 packet had an FCS error. -+ * - 17 = Skip error: a packet was not large enough to -+ * cover the skipped bytes. -+ * - 18 = L2 header malformed: the packet is not long -+ * enough to contain the L2. -+ */ -+ -+ uint64_t rcv_error:1; -+ /* -+ * lower err_code = first-level descriptor of the -+ * work -+ */ -+ /* -+ * zero for packet submitted by hardware that isn't on -+ * the slow path -+ */ -+ /* type is cvmx_pip_err_t (union, so can't use directly */ -+ uint64_t err_code:8; -+ } snoip; -+ -+} cvmx_pip_wqe_word2; -+ -+/** -+ * Work queue entry format -+ * -+ * must be 8-byte aligned -+ */ -+typedef struct { -+ -+ /***************************************************************** -+ * WORD 0 -+ * HW WRITE: the following 64 bits are filled by HW when a packet arrives -+ */ -+ -+ /** -+ * raw chksum result generated by the HW -+ */ -+ uint16_t hw_chksum; -+ /** -+ * Field unused by hardware - available for software -+ */ -+ uint8_t unused; -+ /** -+ * Next pointer used by hardware for list maintenance. -+ * May be written/read by HW before the work queue -+ * entry is scheduled to a PP -+ * (Only 36 bits used in Octeon 1) -+ */ -+ uint64_t next_ptr:40; -+ -+ /***************************************************************** -+ * WORD 1 -+ * HW WRITE: the following 64 bits are filled by HW when a packet arrives -+ */ -+ -+ /** -+ * HW sets to the total number of bytes in the packet -+ */ -+ uint64_t len:16; -+ /** -+ * HW sets this to input physical port -+ */ -+ uint64_t ipprt:6; -+ -+ /** -+ * HW sets this to what it thought the priority of the input packet was -+ */ -+ uint64_t qos:3; -+ -+ /** -+ * the group that the work queue entry will be scheduled to -+ */ -+ uint64_t grp:4; -+ /** -+ * the type of the tag (ORDERED, ATOMIC, NULL) -+ */ -+ uint64_t tag_type:3; -+ /** -+ * the synchronization/ordering tag -+ */ -+ uint64_t tag:32; -+ -+ /** -+ * WORD 2 HW WRITE: the following 64-bits are filled in by -+ * hardware when a packet arrives This indicates a variety of -+ * status and error conditions. -+ */ -+ cvmx_pip_wqe_word2 word2; -+ -+ /** -+ * Pointer to the first segment of the packet. -+ */ -+ union cvmx_buf_ptr packet_ptr; -+ -+ /** -+ * HW WRITE: octeon will fill in a programmable amount from the -+ * packet, up to (at most, but perhaps less) the amount -+ * needed to fill the work queue entry to 128 bytes -+ * -+ * If the packet is recognized to be IP, the hardware starts -+ * (except that the IPv4 header is padded for appropriate -+ * alignment) writing here where the IP header starts. If the -+ * packet is not recognized to be IP, the hardware starts -+ * writing the beginning of the packet here. -+ */ -+ uint8_t packet_data[96]; -+ -+ /** -+ * If desired, SW can make the work Q entry any length. For the -+ * purposes of discussion here, Assume 128B always, as this is all that -+ * the hardware deals with. -+ * -+ */ -+ -+} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_t; -+ -+#endif /* __CVMX_WQE_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-common.c -@@ -0,0 +1,328 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "ethernet-defines.h" -+#include "ethernet-tx.h" -+#include "ethernet-mdio.h" -+#include "ethernet-util.h" -+#include "octeon-ethernet.h" -+#include "ethernet-common.h" -+ -+#include "cvmx-pip.h" -+#include "cvmx-pko.h" -+#include "cvmx-fau.h" -+#include "cvmx-helper.h" -+ -+#include "cvmx-gmxx-defs.h" -+ -+/** -+ * Get the low level ethernet statistics -+ * -+ * @dev: Device to get the statistics from -+ * Returns Pointer to the statistics -+ */ -+static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) -+{ -+ cvmx_pip_port_status_t rx_status; -+ cvmx_pko_port_status_t tx_status; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ -+ if (priv->port < CVMX_PIP_NUM_INPUT_PORTS) { -+ if (octeon_is_simulation()) { -+ /* The simulator doesn't support statistics */ -+ memset(&rx_status, 0, sizeof(rx_status)); -+ memset(&tx_status, 0, sizeof(tx_status)); -+ } else { -+ cvmx_pip_get_port_status(priv->port, 1, &rx_status); -+ cvmx_pko_get_port_status(priv->port, 1, &tx_status); -+ } -+ -+ priv->stats.rx_packets += rx_status.inb_packets; -+ priv->stats.tx_packets += tx_status.packets; -+ priv->stats.rx_bytes += rx_status.inb_octets; -+ priv->stats.tx_bytes += tx_status.octets; -+ priv->stats.multicast += rx_status.multicast_packets; -+ priv->stats.rx_crc_errors += rx_status.inb_errors; -+ priv->stats.rx_frame_errors += rx_status.fcs_align_err_packets; -+ -+ /* -+ * The drop counter must be incremented atomically -+ * since the RX tasklet also increments it. -+ */ -+#ifdef CONFIG_64BIT -+ atomic64_add(rx_status.dropped_packets, -+ (atomic64_t *)&priv->stats.rx_dropped); -+#else -+ atomic_add(rx_status.dropped_packets, -+ (atomic_t *)&priv->stats.rx_dropped); -+#endif -+ } -+ -+ return &priv->stats; -+} -+ -+/** -+ * Set the multicast list. Currently unimplemented. -+ * -+ * @dev: Device to work on -+ */ -+static void cvm_oct_common_set_multicast_list(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ if ((interface < 2) -+ && (cvmx_helper_interface_get_mode(interface) != -+ CVMX_HELPER_INTERFACE_MODE_SPI)) { -+ union cvmx_gmxx_rxx_adr_ctl control; -+ control.u64 = 0; -+ control.s.bcst = 1; /* Allow broadcast MAC addresses */ -+ -+ if (dev->mc_list || (dev->flags & IFF_ALLMULTI) || -+ (dev->flags & IFF_PROMISC)) -+ /* Force accept multicast packets */ -+ control.s.mcst = 2; -+ else -+ /* Force reject multicat packets */ -+ control.s.mcst = 1; -+ -+ if (dev->flags & IFF_PROMISC) -+ /* -+ * Reject matches if promisc. Since CAM is -+ * shut off, should accept everything. -+ */ -+ control.s.cam_mode = 0; -+ else -+ /* Filter packets based on the CAM */ -+ control.s.cam_mode = 1; -+ -+ gmx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), -+ gmx_cfg.u64 & ~1ull); -+ -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), -+ control.u64); -+ if (dev->flags & IFF_PROMISC) -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN -+ (index, interface), 0); -+ else -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN -+ (index, interface), 1); -+ -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), -+ gmx_cfg.u64); -+ } -+} -+ -+/** -+ * Set the hardware MAC address for a device -+ * -+ * @dev: Device to change the MAC address for -+ * @addr: Address structure to change it too. MAC address is addr + 2. -+ * Returns Zero on success -+ */ -+static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ memcpy(dev->dev_addr, addr + 2, 6); -+ -+ if ((interface < 2) -+ && (cvmx_helper_interface_get_mode(interface) != -+ CVMX_HELPER_INTERFACE_MODE_SPI)) { -+ int i; -+ uint8_t *ptr = addr; -+ uint64_t mac = 0; -+ for (i = 0; i < 6; i++) -+ mac = (mac << 8) | (uint64_t) (ptr[i + 2]); -+ -+ gmx_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), -+ gmx_cfg.u64 & ~1ull); -+ -+ cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), -+ ptr[2]); -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), -+ ptr[3]); -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), -+ ptr[4]); -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), -+ ptr[5]); -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), -+ ptr[6]); -+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), -+ ptr[7]); -+ cvm_oct_common_set_multicast_list(dev); -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), -+ gmx_cfg.u64); -+ } -+ return 0; -+} -+ -+/** -+ * Change the link MTU. Unimplemented -+ * -+ * @dev: Device to change -+ * @new_mtu: The new MTU -+ * -+ * Returns Zero on success -+ */ -+static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ int vlan_bytes = 4; -+#else -+ int vlan_bytes = 0; -+#endif -+ -+ /* -+ * Limit the MTU to make sure the ethernet packets are between -+ * 64 bytes and 65535 bytes. -+ */ -+ if ((new_mtu + 14 + 4 + vlan_bytes < 64) -+ || (new_mtu + 14 + 4 + vlan_bytes > 65392)) { -+ pr_err("MTU must be between %d and %d.\n", -+ 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); -+ return -EINVAL; -+ } -+ dev->mtu = new_mtu; -+ -+ if ((interface < 2) -+ && (cvmx_helper_interface_get_mode(interface) != -+ CVMX_HELPER_INTERFACE_MODE_SPI)) { -+ /* Add ethernet header and FCS, and VLAN if configured. */ -+ int max_packet = new_mtu + 14 + 4 + vlan_bytes; -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX) -+ || OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ /* Signal errors on packets larger than the MTU */ -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), -+ max_packet); -+ } else { -+ /* -+ * Set the hardware to truncate packets larger -+ * than the MTU and smaller the 64 bytes. -+ */ -+ union cvmx_pip_frm_len_chkx frm_len_chk; -+ frm_len_chk.u64 = 0; -+ frm_len_chk.s.minlen = 64; -+ frm_len_chk.s.maxlen = max_packet; -+ cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), -+ frm_len_chk.u64); -+ } -+ /* -+ * Set the hardware to truncate packets larger than -+ * the MTU. The jabber register must be set to a -+ * multiple of 8 bytes, so round up. -+ */ -+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), -+ (max_packet + 7) & ~7u); -+ } -+ return 0; -+} -+ -+/** -+ * Per network device initialization -+ * -+ * @dev: Device to initialize -+ * Returns Zero on success -+ */ -+int cvm_oct_common_init(struct net_device *dev) -+{ -+ static int count; -+ char mac[8] = { 0x00, 0x00, -+ octeon_bootinfo->mac_addr_base[0], -+ octeon_bootinfo->mac_addr_base[1], -+ octeon_bootinfo->mac_addr_base[2], -+ octeon_bootinfo->mac_addr_base[3], -+ octeon_bootinfo->mac_addr_base[4], -+ octeon_bootinfo->mac_addr_base[5] + count -+ }; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ -+ /* -+ * Force the interface to use the POW send if always_use_pow -+ * was specified or it is in the pow send list. -+ */ -+ if ((pow_send_group != -1) -+ && (always_use_pow || strstr(pow_send_list, dev->name))) -+ priv->queue = -1; -+ -+ if (priv->queue != -1) { -+ dev->hard_start_xmit = cvm_oct_xmit; -+ if (USE_HW_TCPUDP_CHECKSUM) -+ dev->features |= NETIF_F_IP_CSUM; -+ } else -+ dev->hard_start_xmit = cvm_oct_xmit_pow; -+ count++; -+ -+ dev->get_stats = cvm_oct_common_get_stats; -+ dev->set_mac_address = cvm_oct_common_set_mac_address; -+ dev->set_multicast_list = cvm_oct_common_set_multicast_list; -+ dev->change_mtu = cvm_oct_common_change_mtu; -+ dev->do_ioctl = cvm_oct_ioctl; -+ /* We do our own locking, Linux doesn't need to */ -+ dev->features |= NETIF_F_LLTX; -+ SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); -+#ifdef CONFIG_NET_POLL_CONTROLLER -+ dev->poll_controller = cvm_oct_poll_controller; -+#endif -+ -+ cvm_oct_mdio_setup_device(dev); -+ dev->set_mac_address(dev, mac); -+ dev->change_mtu(dev, dev->mtu); -+ -+ /* -+ * Zero out stats for port so we won't mistakenly show -+ * counters from the bootloader. -+ */ -+ memset(dev->get_stats(dev), 0, sizeof(struct net_device_stats)); -+ -+ return 0; -+} -+ -+void cvm_oct_common_uninit(struct net_device *dev) -+{ -+ /* Currently nothing to do */ -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-common.h -@@ -0,0 +1,29 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+ -+int cvm_oct_common_init(struct net_device *dev); -+void cvm_oct_common_uninit(struct net_device *dev); ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-defines.h -@@ -0,0 +1,134 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+ -+/* -+ * A few defines are used to control the operation of this driver: -+ * CONFIG_CAVIUM_RESERVE32 -+ * This kernel config options controls the amount of memory configured -+ * in a wired TLB entry for all processes to share. If this is set, the -+ * driver will use this memory instead of kernel memory for pools. This -+ * allows 32bit userspace application to access the buffers, but also -+ * requires all received packets to be copied. -+ * CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS -+ * This kernel config option allows the user to control the number of -+ * packet and work queue buffers allocated by the driver. If this is zero, -+ * the driver uses the default from below. -+ * USE_SKBUFFS_IN_HW -+ * Tells the driver to populate the packet buffers with kernel skbuffs. -+ * This allows the driver to receive packets without copying them. It also -+ * means that 32bit userspace can't access the packet buffers. -+ * USE_32BIT_SHARED -+ * This define tells the driver to allocate memory for buffers from the -+ * 32bit sahred region instead of the kernel memory space. -+ * USE_HW_TCPUDP_CHECKSUM -+ * Controls if the Octeon TCP/UDP checksum engine is used for packet -+ * output. If this is zero, the kernel will perform the checksum in -+ * software. -+ * USE_MULTICORE_RECEIVE -+ * Process receive interrupts on multiple cores. This spreads the network -+ * load across the first 8 processors. If ths is zero, only one core -+ * processes incomming packets. -+ * USE_ASYNC_IOBDMA -+ * Use asynchronous IO access to hardware. This uses Octeon's asynchronous -+ * IOBDMAs to issue IO accesses without stalling. Set this to zero -+ * to disable this. Note that IOBDMAs require CVMSEG. -+ * REUSE_SKBUFFS_WITHOUT_FREE -+ * Allows the TX path to free an skbuff into the FPA hardware pool. This -+ * can significantly improve performance for forwarding and bridging, but -+ * may be somewhat dangerous. Checks are made, but if any buffer is reused -+ * without the proper Linux cleanup, the networking stack may have very -+ * bizarre bugs. -+ */ -+#ifndef __ETHERNET_DEFINES_H__ -+#define __ETHERNET_DEFINES_H__ -+ -+#include "cvmx-config.h" -+ -+ -+#define OCTEON_ETHERNET_VERSION "1.9" -+ -+#ifndef CONFIG_CAVIUM_RESERVE32 -+#define CONFIG_CAVIUM_RESERVE32 0 -+#endif -+ -+#if CONFIG_CAVIUM_RESERVE32 -+#define USE_32BIT_SHARED 1 -+#define USE_SKBUFFS_IN_HW 0 -+#define REUSE_SKBUFFS_WITHOUT_FREE 0 -+#else -+#define USE_32BIT_SHARED 0 -+#define USE_SKBUFFS_IN_HW 1 -+#ifdef CONFIG_NETFILTER -+#define REUSE_SKBUFFS_WITHOUT_FREE 0 -+#else -+#define REUSE_SKBUFFS_WITHOUT_FREE 1 -+#endif -+#endif -+ -+/* Max interrupts per second per core */ -+#define INTERRUPT_LIMIT 10000 -+ -+/* Don't limit the number of interrupts */ -+/*#define INTERRUPT_LIMIT 0 */ -+#define USE_HW_TCPUDP_CHECKSUM 1 -+ -+#define USE_MULTICORE_RECEIVE 1 -+ -+/* Enable Random Early Dropping under load */ -+#define USE_RED 1 -+#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) -+ -+/* -+ * Allow SW based preamble removal at 10Mbps to workaround PHYs giving -+ * us bad preambles. -+ */ -+#define USE_10MBPS_PREAMBLE_WORKAROUND 1 -+/* -+ * Use this to have all FPA frees also tell the L2 not to write data -+ * to memory. -+ */ -+#define DONT_WRITEBACK(x) (x) -+/* Use this to not have FPA frees control L2 */ -+/*#define DONT_WRITEBACK(x) 0 */ -+ -+/* Maximum number of packets to process per interrupt. */ -+#define MAX_RX_PACKETS 120 -+#define MAX_OUT_QUEUE_DEPTH 1000 -+ -+#ifndef CONFIG_SMP -+#undef USE_MULTICORE_RECEIVE -+#define USE_MULTICORE_RECEIVE 0 -+#endif -+ -+#define IP_PROTOCOL_TCP 6 -+#define IP_PROTOCOL_UDP 0x11 -+ -+#define FAU_NUM_PACKET_BUFFERS_TO_FREE (CVMX_FAU_REG_END - sizeof(uint32_t)) -+#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS+1) -+ -+ -+#endif /* __ETHERNET_DEFINES_H__ */ ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-mdio.c -@@ -0,0 +1,231 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-mdio.h" -+ -+#include "cvmx-helper-board.h" -+ -+#include "cvmx-smix-defs.h" -+ -+DECLARE_MUTEX(mdio_sem); -+ -+/** -+ * Perform an MII read. Called by the generic MII routines -+ * -+ * @dev: Device to perform read for -+ * @phy_id: The MII phy id -+ * @location: Register location to read -+ * Returns Result from the read or zero on failure -+ */ -+static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_rd_dat smi_rd; -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = 1; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = location; -+ cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); -+ -+ do { -+ if (!in_interrupt()) -+ yield(); -+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); -+ } while (smi_rd.s.pending); -+ -+ if (smi_rd.s.val) -+ return smi_rd.s.dat; -+ else -+ return 0; -+} -+ -+static int cvm_oct_mdio_dummy_read(struct net_device *dev, int phy_id, -+ int location) -+{ -+ return 0xffff; -+} -+ -+/** -+ * Perform an MII write. Called by the generic MII routines -+ * -+ * @dev: Device to perform write for -+ * @phy_id: The MII phy id -+ * @location: Register location to write -+ * @val: Value to write -+ */ -+static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location, -+ int val) -+{ -+ union cvmx_smix_cmd smi_cmd; -+ union cvmx_smix_wr_dat smi_wr; -+ -+ smi_wr.u64 = 0; -+ smi_wr.s.dat = val; -+ cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); -+ -+ smi_cmd.u64 = 0; -+ smi_cmd.s.phy_op = 0; -+ smi_cmd.s.phy_adr = phy_id; -+ smi_cmd.s.reg_adr = location; -+ cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); -+ -+ do { -+ if (!in_interrupt()) -+ yield(); -+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); -+ } while (smi_wr.s.pending); -+} -+ -+static void cvm_oct_mdio_dummy_write(struct net_device *dev, int phy_id, -+ int location, int val) -+{ -+} -+ -+static void cvm_oct_get_drvinfo(struct net_device *dev, -+ struct ethtool_drvinfo *info) -+{ -+ strcpy(info->driver, "cavium-ethernet"); -+ strcpy(info->version, OCTEON_ETHERNET_VERSION); -+ strcpy(info->bus_info, "Builtin"); -+} -+ -+static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int ret; -+ -+ down(&mdio_sem); -+ ret = mii_ethtool_gset(&priv->mii_info, cmd); -+ up(&mdio_sem); -+ -+ return ret; -+} -+ -+static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int ret; -+ -+ down(&mdio_sem); -+ ret = mii_ethtool_sset(&priv->mii_info, cmd); -+ up(&mdio_sem); -+ -+ return ret; -+} -+ -+static int cvm_oct_nway_reset(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int ret; -+ -+ down(&mdio_sem); -+ ret = mii_nway_restart(&priv->mii_info); -+ up(&mdio_sem); -+ -+ return ret; -+} -+ -+static u32 cvm_oct_get_link(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ u32 ret; -+ -+ down(&mdio_sem); -+ ret = mii_link_ok(&priv->mii_info); -+ up(&mdio_sem); -+ -+ return ret; -+} -+ -+struct ethtool_ops cvm_oct_ethtool_ops = { -+ .get_drvinfo = cvm_oct_get_drvinfo, -+ .get_settings = cvm_oct_get_settings, -+ .set_settings = cvm_oct_set_settings, -+ .nway_reset = cvm_oct_nway_reset, -+ .get_link = cvm_oct_get_link, -+ .get_sg = ethtool_op_get_sg, -+ .get_tx_csum = ethtool_op_get_tx_csum, -+}; -+ -+/** -+ * IOCTL support for PHY control -+ * -+ * @dev: Device to change -+ * @rq: the request -+ * @cmd: the command -+ * Returns Zero on success -+ */ -+int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ struct mii_ioctl_data *data = if_mii(rq); -+ unsigned int duplex_chg; -+ int ret; -+ -+ down(&mdio_sem); -+ ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg); -+ up(&mdio_sem); -+ -+ return ret; -+} -+ -+/** -+ * Setup the MDIO device structures -+ * -+ * @dev: Device to setup -+ * -+ * Returns Zero on success, negative on failure -+ */ -+int cvm_oct_mdio_setup_device(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int phy_id = cvmx_helper_board_get_mii_address(priv->port); -+ if (phy_id != -1) { -+ priv->mii_info.dev = dev; -+ priv->mii_info.phy_id = phy_id; -+ priv->mii_info.phy_id_mask = 0xff; -+ priv->mii_info.supports_gmii = 1; -+ priv->mii_info.reg_num_mask = 0x1f; -+ priv->mii_info.mdio_read = cvm_oct_mdio_read; -+ priv->mii_info.mdio_write = cvm_oct_mdio_write; -+ } else { -+ /* Supply dummy MDIO routines so the kernel won't crash -+ if the user tries to read them */ -+ priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read; -+ priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write; -+ } -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-mdio.h -@@ -0,0 +1,46 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_XFRM -+#include -+#include -+#endif /* CONFIG_XFRM */ -+ -+extern struct ethtool_ops cvm_oct_ethtool_ops; -+int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -+int cvm_oct_mdio_setup_device(struct net_device *dev); ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-mem.c -@@ -0,0 +1,198 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+ -+#include "cvmx-fpa.h" -+ -+/** -+ * Fill the supplied hardware pool with skbuffs -+ * -+ * @pool: Pool to allocate an skbuff for -+ * @size: Size of the buffer needed for the pool -+ * @elements: Number of buffers to allocate -+ */ -+static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements) -+{ -+ int freed = elements; -+ while (freed) { -+ -+ struct sk_buff *skb = dev_alloc_skb(size + 128); -+ if (unlikely(skb == NULL)) { -+ pr_warning -+ ("Failed to allocate skb for hardware pool %d\n", -+ pool); -+ break; -+ } -+ -+ skb_reserve(skb, 128 - (((unsigned long)skb->data) & 0x7f)); -+ *(struct sk_buff **)(skb->data - sizeof(void *)) = skb; -+ cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128)); -+ freed--; -+ } -+ return elements - freed; -+} -+ -+/** -+ * Free the supplied hardware pool of skbuffs -+ * -+ * @pool: Pool to allocate an skbuff for -+ * @size: Size of the buffer needed for the pool -+ * @elements: Number of buffers to allocate -+ */ -+static void cvm_oct_free_hw_skbuff(int pool, int size, int elements) -+{ -+ char *memory; -+ -+ do { -+ memory = cvmx_fpa_alloc(pool); -+ if (memory) { -+ struct sk_buff *skb = -+ *(struct sk_buff **)(memory - sizeof(void *)); -+ elements--; -+ dev_kfree_skb(skb); -+ } -+ } while (memory); -+ -+ if (elements < 0) -+ pr_warning("Freeing of pool %u had too many skbuffs (%d)\n", -+ pool, elements); -+ else if (elements > 0) -+ pr_warning("Freeing of pool %u is missing %d skbuffs\n", -+ pool, elements); -+} -+ -+/** -+ * This function fills a hardware pool with memory. Depending -+ * on the config defines, this memory might come from the -+ * kernel or global 32bit memory allocated with -+ * cvmx_bootmem_alloc. -+ * -+ * @pool: Pool to populate -+ * @size: Size of each buffer in the pool -+ * @elements: Number of buffers to allocate -+ */ -+static int cvm_oct_fill_hw_memory(int pool, int size, int elements) -+{ -+ char *memory; -+ int freed = elements; -+ -+ if (USE_32BIT_SHARED) { -+ extern uint64_t octeon_reserve32_memory; -+ -+ memory = -+ cvmx_bootmem_alloc_range(elements * size, 128, -+ octeon_reserve32_memory, -+ octeon_reserve32_memory + -+ (CONFIG_CAVIUM_RESERVE32 << 20) - -+ 1); -+ if (memory == NULL) -+ panic("Unable to allocate %u bytes for FPA pool %d\n", -+ elements * size, pool); -+ -+ pr_notice("Memory range %p - %p reserved for " -+ "hardware\n", memory, -+ memory + elements * size - 1); -+ -+ while (freed) { -+ cvmx_fpa_free(memory, pool, 0); -+ memory += size; -+ freed--; -+ } -+ } else { -+ while (freed) { -+ /* We need to force alignment to 128 bytes here */ -+ memory = kmalloc(size + 127, GFP_ATOMIC); -+ if (unlikely(memory == NULL)) { -+ pr_warning("Unable to allocate %u bytes for " -+ "FPA pool %d\n", -+ elements * size, pool); -+ break; -+ } -+ memory = (char *)(((unsigned long)memory + 127) & -128); -+ cvmx_fpa_free(memory, pool, 0); -+ freed--; -+ } -+ } -+ return elements - freed; -+} -+ -+/** -+ * Free memory previously allocated with cvm_oct_fill_hw_memory -+ * -+ * @pool: FPA pool to free -+ * @size: Size of each buffer in the pool -+ * @elements: Number of buffers that should be in the pool -+ */ -+static void cvm_oct_free_hw_memory(int pool, int size, int elements) -+{ -+ if (USE_32BIT_SHARED) { -+ pr_warning("Warning: 32 shared memory is not freeable\n"); -+ } else { -+ char *memory; -+ do { -+ memory = cvmx_fpa_alloc(pool); -+ if (memory) { -+ elements--; -+ kfree(phys_to_virt(cvmx_ptr_to_phys(memory))); -+ } -+ } while (memory); -+ -+ if (elements < 0) -+ pr_warning("Freeing of pool %u had too many " -+ "buffers (%d)\n", -+ pool, elements); -+ else if (elements > 0) -+ pr_warning("Warning: Freeing of pool %u is " -+ "missing %d buffers\n", -+ pool, elements); -+ } -+} -+ -+int cvm_oct_mem_fill_fpa(int pool, int size, int elements) -+{ -+ int freed; -+ if (USE_SKBUFFS_IN_HW) -+ freed = cvm_oct_fill_hw_skbuff(pool, size, elements); -+ else -+ freed = cvm_oct_fill_hw_memory(pool, size, elements); -+ return freed; -+} -+ -+void cvm_oct_mem_empty_fpa(int pool, int size, int elements) -+{ -+ if (USE_SKBUFFS_IN_HW) -+ cvm_oct_free_hw_skbuff(pool, size, elements); -+ else -+ cvm_oct_free_hw_memory(pool, size, elements); -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-mem.h -@@ -0,0 +1,29 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+********************************************************************/ -+ -+int cvm_oct_mem_fill_fpa(int pool, int size, int elements); -+void cvm_oct_mem_empty_fpa(int pool, int size, int elements); ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-proc.c -@@ -0,0 +1,256 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "octeon-ethernet.h" -+#include "ethernet-defines.h" -+ -+#include "cvmx-helper.h" -+#include "cvmx-pip.h" -+ -+static unsigned long long cvm_oct_stats_read_switch(struct net_device *dev, -+ int phy_id, int offset) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ -+ priv->mii_info.mdio_write(dev, phy_id, 0x1d, 0xcc00 | offset); -+ return ((uint64_t) priv->mii_info. -+ mdio_read(dev, phy_id, -+ 0x1e) << 16) | (uint64_t) priv->mii_info. -+ mdio_read(dev, phy_id, 0x1f); -+} -+ -+static int cvm_oct_stats_switch_show(struct seq_file *m, void *v) -+{ -+ static const int ports[] = { 0, 1, 2, 3, 9, -1 }; -+ struct net_device *dev = cvm_oct_device[0]; -+ int index = 0; -+ -+ while (ports[index] != -1) { -+ -+ /* Latch port */ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ -+ priv->mii_info.mdio_write(dev, 0x1b, 0x1d, -+ 0xdc00 | ports[index]); -+ seq_printf(m, "\nSwitch Port %d\n", ports[index]); -+ seq_printf(m, "InGoodOctets: %12llu\t" -+ "OutOctets: %12llu\t" -+ "64 Octets: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, -+ 0x00) | -+ (cvm_oct_stats_read_switch(dev, 0x1b, 0x01) << 32), -+ cvm_oct_stats_read_switch(dev, 0x1b, -+ 0x0E) | -+ (cvm_oct_stats_read_switch(dev, 0x1b, 0x0F) << 32), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x08)); -+ -+ seq_printf(m, "InBadOctets: %12llu\t" -+ "OutUnicast: %12llu\t" -+ "65-127 Octets: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x02), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x10), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x09)); -+ -+ seq_printf(m, "InUnicast: %12llu\t" -+ "OutBroadcasts: %12llu\t" -+ "128-255 Octets: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x04), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x13), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x0A)); -+ -+ seq_printf(m, "InBroadcasts: %12llu\t" -+ "OutMulticasts: %12llu\t" -+ "256-511 Octets: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x06), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x12), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x0B)); -+ -+ seq_printf(m, "InMulticasts: %12llu\t" -+ "OutPause: %12llu\t" -+ "512-1023 Octets:%12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x07), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x15), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x0C)); -+ -+ seq_printf(m, "InPause: %12llu\t" -+ "Excessive: %12llu\t" -+ "1024-Max Octets:%12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x16), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x11), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x0D)); -+ -+ seq_printf(m, "InUndersize: %12llu\t" -+ "Collisions: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x18), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x1E)); -+ -+ seq_printf(m, "InFragments: %12llu\t" -+ "Deferred: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x19), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x05)); -+ -+ seq_printf(m, "InOversize: %12llu\t" -+ "Single: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x1A), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x14)); -+ -+ seq_printf(m, "InJabber: %12llu\t" -+ "Multiple: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x1B), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x17)); -+ -+ seq_printf(m, "In RxErr: %12llu\t" -+ "OutFCSErr: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x1C), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x03)); -+ -+ seq_printf(m, "InFCSErr: %12llu\t" -+ "Late: %12llu\n", -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x1D), -+ cvm_oct_stats_read_switch(dev, 0x1b, 0x1F)); -+ index++; -+ } -+ return 0; -+} -+ -+/** -+ * User is reading /proc/octeon_ethernet_stats -+ * -+ * @m: -+ * @v: -+ * Returns -+ */ -+static int cvm_oct_stats_show(struct seq_file *m, void *v) -+{ -+ struct octeon_ethernet *priv; -+ int port; -+ -+ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { -+ -+ if (cvm_oct_device[port]) { -+ priv = netdev_priv(cvm_oct_device[port]); -+ -+ seq_printf(m, "\nOcteon Port %d (%s)\n", port, -+ cvm_oct_device[port]->name); -+ seq_printf(m, -+ "rx_packets: %12lu\t" -+ "tx_packets: %12lu\n", -+ priv->stats.rx_packets, -+ priv->stats.tx_packets); -+ seq_printf(m, -+ "rx_bytes: %12lu\t" -+ "tx_bytes: %12lu\n", -+ priv->stats.rx_bytes, priv->stats.tx_bytes); -+ seq_printf(m, -+ "rx_errors: %12lu\t" -+ "tx_errors: %12lu\n", -+ priv->stats.rx_errors, -+ priv->stats.tx_errors); -+ seq_printf(m, -+ "rx_dropped: %12lu\t" -+ "tx_dropped: %12lu\n", -+ priv->stats.rx_dropped, -+ priv->stats.tx_dropped); -+ seq_printf(m, -+ "rx_length_errors: %12lu\t" -+ "tx_aborted_errors: %12lu\n", -+ priv->stats.rx_length_errors, -+ priv->stats.tx_aborted_errors); -+ seq_printf(m, -+ "rx_over_errors: %12lu\t" -+ "tx_carrier_errors: %12lu\n", -+ priv->stats.rx_over_errors, -+ priv->stats.tx_carrier_errors); -+ seq_printf(m, -+ "rx_crc_errors: %12lu\t" -+ "tx_fifo_errors: %12lu\n", -+ priv->stats.rx_crc_errors, -+ priv->stats.tx_fifo_errors); -+ seq_printf(m, -+ "rx_frame_errors: %12lu\t" -+ "tx_heartbeat_errors: %12lu\n", -+ priv->stats.rx_frame_errors, -+ priv->stats.tx_heartbeat_errors); -+ seq_printf(m, -+ "rx_fifo_errors: %12lu\t" -+ "tx_window_errors: %12lu\n", -+ priv->stats.rx_fifo_errors, -+ priv->stats.tx_window_errors); -+ seq_printf(m, -+ "rx_missed_errors: %12lu\t" -+ "multicast: %12lu\n", -+ priv->stats.rx_missed_errors, -+ priv->stats.multicast); -+ } -+ } -+ -+ if (cvm_oct_device[0]) { -+ priv = netdev_priv(cvm_oct_device[0]); -+ if (priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) -+ cvm_oct_stats_switch_show(m, v); -+ } -+ return 0; -+} -+ -+/** -+ * /proc/octeon_ethernet_stats was openned. Use the single_open iterator -+ * -+ * @inode: -+ * @file: -+ * Returns -+ */ -+static int cvm_oct_stats_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, cvm_oct_stats_show, NULL); -+} -+ -+static const struct file_operations cvm_oct_stats_operations = { -+ .open = cvm_oct_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+void cvm_oct_proc_initialize(void) -+{ -+ struct proc_dir_entry *entry = -+ create_proc_entry("octeon_ethernet_stats", 0, NULL); -+ if (entry) -+ entry->proc_fops = &cvm_oct_stats_operations; -+} -+ -+void cvm_oct_proc_shutdown(void) -+{ -+ remove_proc_entry("octeon_ethernet_stats", NULL); -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-proc.h -@@ -0,0 +1,29 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+ -+void cvm_oct_proc_initialize(void); -+void cvm_oct_proc_shutdown(void); ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-rgmii.c -@@ -0,0 +1,397 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-common.h" -+#include "ethernet-util.h" -+ -+#include "cvmx-helper.h" -+ -+#include -+#include -+#include "cvmx-gmxx-defs.h" -+ -+DEFINE_SPINLOCK(global_register_lock); -+ -+static int number_rgmii_ports; -+ -+static void cvm_oct_rgmii_poll(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ unsigned long flags; -+ cvmx_helper_link_info_t link_info; -+ -+ /* -+ * Take the global register lock since we are going to touch -+ * registers that affect more than one port. -+ */ -+ spin_lock_irqsave(&global_register_lock, flags); -+ -+ link_info = cvmx_helper_link_get(priv->port); -+ if (link_info.u64 == priv->link_info) { -+ -+ /* -+ * If the 10Mbps preamble workaround is supported and we're -+ * at 10Mbps we may need to do some special checking. -+ */ -+ if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) { -+ -+ /* -+ * Read the GMXX_RXX_INT_REG[PCTERR] bit and -+ * see if we are getting preamble errors. -+ */ -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; -+ gmxx_rxx_int_reg.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG -+ (index, interface)); -+ if (gmxx_rxx_int_reg.s.pcterr) { -+ -+ /* -+ * We are getting preamble errors at -+ * 10Mbps. Most likely the PHY is -+ * giving us packets with mis aligned -+ * preambles. In order to get these -+ * packets we need to disable preamble -+ * checking and do it in software. -+ */ -+ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; -+ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; -+ -+ /* Disable preamble checking */ -+ gmxx_rxx_frm_ctl.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL -+ (index, interface)); -+ gmxx_rxx_frm_ctl.s.pre_chk = 0; -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL -+ (index, interface), -+ gmxx_rxx_frm_ctl.u64); -+ -+ /* Disable FCS stripping */ -+ ipd_sub_port_fcs.u64 = -+ cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); -+ ipd_sub_port_fcs.s.port_bit &= -+ 0xffffffffull ^ (1ull << priv->port); -+ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, -+ ipd_sub_port_fcs.u64); -+ -+ /* Clear any error bits */ -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG -+ (index, interface), -+ gmxx_rxx_int_reg.u64); -+ DEBUGPRINT("%s: Using 10Mbps with software " -+ "preamble removal\n", -+ dev->name); -+ } -+ } -+ spin_unlock_irqrestore(&global_register_lock, flags); -+ return; -+ } -+ -+ /* If the 10Mbps preamble workaround is allowed we need to on -+ preamble checking, FCS stripping, and clear error bits on -+ every speed change. If errors occur during 10Mbps operation -+ the above code will change this stuff */ -+ if (USE_10MBPS_PREAMBLE_WORKAROUND) { -+ -+ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; -+ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; -+ union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ /* Enable preamble checking */ -+ gmxx_rxx_frm_ctl.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); -+ gmxx_rxx_frm_ctl.s.pre_chk = 1; -+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), -+ gmxx_rxx_frm_ctl.u64); -+ /* Enable FCS stripping */ -+ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); -+ ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; -+ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); -+ /* Clear any error bits */ -+ gmxx_rxx_int_reg.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface)); -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), -+ gmxx_rxx_int_reg.u64); -+ } -+ -+ link_info = cvmx_helper_link_autoconf(priv->port); -+ priv->link_info = link_info.u64; -+ spin_unlock_irqrestore(&global_register_lock, flags); -+ -+ /* Tell Linux */ -+ if (link_info.s.link_up) { -+ -+ if (!netif_carrier_ok(dev)) -+ netif_carrier_on(dev); -+ if (priv->queue != -1) -+ DEBUGPRINT -+ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", -+ dev->name, link_info.s.speed, -+ (link_info.s.full_duplex) ? "Full" : "Half", -+ priv->port, priv->queue); -+ else -+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", -+ dev->name, link_info.s.speed, -+ (link_info.s.full_duplex) ? "Full" : "Half", -+ priv->port); -+ } else { -+ -+ if (netif_carrier_ok(dev)) -+ netif_carrier_off(dev); -+ DEBUGPRINT("%s: Link down\n", dev->name); -+ } -+} -+ -+static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) -+{ -+ union cvmx_npi_rsl_int_blocks rsl_int_blocks; -+ int index; -+ irqreturn_t return_status = IRQ_NONE; -+ -+ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); -+ -+ /* Check and see if this interrupt was caused by the GMX0 block */ -+ if (rsl_int_blocks.s.gmx0) { -+ -+ int interface = 0; -+ /* Loop through every port of this interface */ -+ for (index = 0; -+ index < cvmx_helper_ports_on_interface(interface); -+ index++) { -+ -+ /* Read the GMX interrupt status bits */ -+ union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; -+ gmx_rx_int_reg.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG -+ (index, interface)); -+ gmx_rx_int_reg.u64 &= -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN -+ (index, interface)); -+ /* Poll the port if inband status changed */ -+ if (gmx_rx_int_reg.s.phy_dupx -+ || gmx_rx_int_reg.s.phy_link -+ || gmx_rx_int_reg.s.phy_spd) { -+ -+ struct net_device *dev = -+ cvm_oct_device[cvmx_helper_get_ipd_port -+ (interface, index)]; -+ if (dev) -+ cvm_oct_rgmii_poll(dev); -+ gmx_rx_int_reg.u64 = 0; -+ gmx_rx_int_reg.s.phy_dupx = 1; -+ gmx_rx_int_reg.s.phy_link = 1; -+ gmx_rx_int_reg.s.phy_spd = 1; -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG -+ (index, interface), -+ gmx_rx_int_reg.u64); -+ return_status = IRQ_HANDLED; -+ } -+ } -+ } -+ -+ /* Check and see if this interrupt was caused by the GMX1 block */ -+ if (rsl_int_blocks.s.gmx1) { -+ -+ int interface = 1; -+ /* Loop through every port of this interface */ -+ for (index = 0; -+ index < cvmx_helper_ports_on_interface(interface); -+ index++) { -+ -+ /* Read the GMX interrupt status bits */ -+ union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; -+ gmx_rx_int_reg.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_REG -+ (index, interface)); -+ gmx_rx_int_reg.u64 &= -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN -+ (index, interface)); -+ /* Poll the port if inband status changed */ -+ if (gmx_rx_int_reg.s.phy_dupx -+ || gmx_rx_int_reg.s.phy_link -+ || gmx_rx_int_reg.s.phy_spd) { -+ -+ struct net_device *dev = -+ cvm_oct_device[cvmx_helper_get_ipd_port -+ (interface, index)]; -+ if (dev) -+ cvm_oct_rgmii_poll(dev); -+ gmx_rx_int_reg.u64 = 0; -+ gmx_rx_int_reg.s.phy_dupx = 1; -+ gmx_rx_int_reg.s.phy_link = 1; -+ gmx_rx_int_reg.s.phy_spd = 1; -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG -+ (index, interface), -+ gmx_rx_int_reg.u64); -+ return_status = IRQ_HANDLED; -+ } -+ } -+ } -+ return return_status; -+} -+ -+static int cvm_oct_rgmii_open(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ cvmx_helper_link_info_t link_info; -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ -+ if (!octeon_is_simulation()) { -+ link_info = cvmx_helper_link_get(priv->port); -+ if (!link_info.s.link_up) -+ netif_carrier_off(dev); -+ } -+ -+ return 0; -+} -+ -+static int cvm_oct_rgmii_stop(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ return 0; -+} -+ -+int cvm_oct_rgmii_init(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int r; -+ -+ cvm_oct_common_init(dev); -+ dev->open = cvm_oct_rgmii_open; -+ dev->stop = cvm_oct_rgmii_stop; -+ dev->stop(dev); -+ -+ /* -+ * Due to GMX errata in CN3XXX series chips, it is necessary -+ * to take the link down immediately whne the PHY changes -+ * state. In order to do this we call the poll function every -+ * time the RGMII inband status changes. This may cause -+ * problems if the PHY doesn't implement inband status -+ * properly. -+ */ -+ if (number_rgmii_ports == 0) { -+ r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt, -+ IRQF_SHARED, "RGMII", &number_rgmii_ports); -+ } -+ number_rgmii_ports++; -+ -+ /* -+ * Only true RGMII ports need to be polled. In GMII mode, port -+ * 0 is really a RGMII port. -+ */ -+ if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) -+ && (priv->port == 0)) -+ || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { -+ -+ if (!octeon_is_simulation()) { -+ -+ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ /* -+ * Enable interrupts on inband status changes -+ * for this port. -+ */ -+ gmx_rx_int_en.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN -+ (index, interface)); -+ gmx_rx_int_en.s.phy_dupx = 1; -+ gmx_rx_int_en.s.phy_link = 1; -+ gmx_rx_int_en.s.phy_spd = 1; -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), -+ gmx_rx_int_en.u64); -+ priv->poll = cvm_oct_rgmii_poll; -+ } -+ } -+ -+ return 0; -+} -+ -+void cvm_oct_rgmii_uninit(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ cvm_oct_common_uninit(dev); -+ -+ /* -+ * Only true RGMII ports need to be polled. In GMII mode, port -+ * 0 is really a RGMII port. -+ */ -+ if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) -+ && (priv->port == 0)) -+ || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { -+ -+ if (!octeon_is_simulation()) { -+ -+ union cvmx_gmxx_rxx_int_en gmx_rx_int_en; -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ /* -+ * Disable interrupts on inband status changes -+ * for this port. -+ */ -+ gmx_rx_int_en.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_INT_EN -+ (index, interface)); -+ gmx_rx_int_en.s.phy_dupx = 0; -+ gmx_rx_int_en.s.phy_link = 0; -+ gmx_rx_int_en.s.phy_spd = 0; -+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), -+ gmx_rx_int_en.u64); -+ } -+ } -+ -+ /* Remove the interrupt handler when the last port is removed. */ -+ number_rgmii_ports--; -+ if (number_rgmii_ports == 0) -+ free_irq(OCTEON_IRQ_RML, &number_rgmii_ports); -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-rx.c -@@ -0,0 +1,505 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_XFRM -+#include -+#include -+#endif /* CONFIG_XFRM */ -+ -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-mem.h" -+#include "ethernet-util.h" -+ -+#include "cvmx-helper.h" -+#include "cvmx-wqe.h" -+#include "cvmx-fau.h" -+#include "cvmx-pow.h" -+#include "cvmx-pip.h" -+#include "cvmx-scratch.h" -+ -+#include "cvmx-gmxx-defs.h" -+ -+struct cvm_tasklet_wrapper { -+ struct tasklet_struct t; -+}; -+ -+/* -+ * Aligning the tasklet_struct on cachline boundries seems to decrease -+ * throughput even though in theory it would reduce contantion on the -+ * cache lines containing the locks. -+ */ -+ -+static struct cvm_tasklet_wrapper cvm_oct_tasklet[NR_CPUS]; -+ -+/** -+ * Interrupt handler. The interrupt occurs whenever the POW -+ * transitions from 0->1 packets in our group. -+ * -+ * @cpl: -+ * @dev_id: -+ * @regs: -+ * Returns -+ */ -+irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id) -+{ -+ /* Acknowledge the interrupt */ -+ if (INTERRUPT_LIMIT) -+ cvmx_write_csr(CVMX_POW_WQ_INT, 1 << pow_receive_group); -+ else -+ cvmx_write_csr(CVMX_POW_WQ_INT, 0x10001 << pow_receive_group); -+ preempt_disable(); -+ tasklet_schedule(&cvm_oct_tasklet[smp_processor_id()].t); -+ preempt_enable(); -+ return IRQ_HANDLED; -+} -+ -+#ifdef CONFIG_NET_POLL_CONTROLLER -+/** -+ * This is called when the kernel needs to manually poll the -+ * device. For Octeon, this is simply calling the interrupt -+ * handler. We actually poll all the devices, not just the -+ * one supplied. -+ * -+ * @dev: Device to poll. Unused -+ */ -+void cvm_oct_poll_controller(struct net_device *dev) -+{ -+ preempt_disable(); -+ tasklet_schedule(&cvm_oct_tasklet[smp_processor_id()].t); -+ preempt_enable(); -+} -+#endif -+ -+/** -+ * This is called on receive errors, and determines if the packet -+ * can be dropped early-on in cvm_oct_tasklet_rx(). -+ * -+ * @work: Work queue entry pointing to the packet. -+ * Returns Non-zero if the packet can be dropped, zero otherwise. -+ */ -+static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) -+{ -+ if ((work->word2.snoip.err_code == 10) && (work->len <= 64)) { -+ /* -+ * Ignore length errors on min size packets. Some -+ * equipment incorrectly pads packets to 64+4FCS -+ * instead of 60+4FCS. Note these packets still get -+ * counted as frame errors. -+ */ -+ } else -+ if (USE_10MBPS_PREAMBLE_WORKAROUND -+ && ((work->word2.snoip.err_code == 5) -+ || (work->word2.snoip.err_code == 7))) { -+ -+ /* -+ * We received a packet with either an alignment error -+ * or a FCS error. This may be signalling that we are -+ * running 10Mbps with GMXX_RXX_FRM_CTL[PRE_CHK} -+ * off. If this is the case we need to parse the -+ * packet to determine if we can remove a non spec -+ * preamble and generate a correct packet. -+ */ -+ int interface = cvmx_helper_get_interface_num(work->ipprt); -+ int index = cvmx_helper_get_interface_index_num(work->ipprt); -+ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; -+ gmxx_rxx_frm_ctl.u64 = -+ cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); -+ if (gmxx_rxx_frm_ctl.s.pre_chk == 0) { -+ -+ uint8_t *ptr = -+ cvmx_phys_to_ptr(work->packet_ptr.s.addr); -+ int i = 0; -+ -+ while (i < work->len - 1) { -+ if (*ptr != 0x55) -+ break; -+ ptr++; -+ i++; -+ } -+ -+ if (*ptr == 0xd5) { -+ /* -+ DEBUGPRINT("Port %d received 0xd5 preamble\n", work->ipprt); -+ */ -+ work->packet_ptr.s.addr += i + 1; -+ work->len -= i + 5; -+ } else if ((*ptr & 0xf) == 0xd) { -+ /* -+ DEBUGPRINT("Port %d received 0x?d preamble\n", work->ipprt); -+ */ -+ work->packet_ptr.s.addr += i; -+ work->len -= i + 4; -+ for (i = 0; i < work->len; i++) { -+ *ptr = -+ ((*ptr & 0xf0) >> 4) | -+ ((*(ptr + 1) & 0xf) << 4); -+ ptr++; -+ } -+ } else { -+ DEBUGPRINT("Port %d unknown preamble, packet " -+ "dropped\n", -+ work->ipprt); -+ /* -+ cvmx_helper_dump_packet(work); -+ */ -+ cvm_oct_free_work(work); -+ return 1; -+ } -+ } -+ } else { -+ DEBUGPRINT("Port %d receive error code %d, packet dropped\n", -+ work->ipprt, work->word2.snoip.err_code); -+ cvm_oct_free_work(work); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/** -+ * Tasklet function that is scheduled on a core when an interrupt occurs. -+ * -+ * @unused: -+ */ -+void cvm_oct_tasklet_rx(unsigned long unused) -+{ -+ const int coreid = cvmx_get_core_num(); -+ uint64_t old_group_mask; -+ uint64_t old_scratch; -+ int rx_count = 0; -+ int number_to_free; -+ int num_freed; -+ int packet_not_copied; -+ -+ /* Prefetch cvm_oct_device since we know we need it soon */ -+ prefetch(cvm_oct_device); -+ -+ if (USE_ASYNC_IOBDMA) { -+ /* Save scratch in case userspace is using it */ -+ CVMX_SYNCIOBDMA; -+ old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); -+ } -+ -+ /* Only allow work for our group (and preserve priorities) */ -+ old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid)); -+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), -+ (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group); -+ -+ if (USE_ASYNC_IOBDMA) -+ cvmx_pow_work_request_async(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT); -+ -+ while (1) { -+ struct sk_buff *skb = NULL; -+ int skb_in_hw; -+ cvmx_wqe_t *work; -+ -+ if (USE_ASYNC_IOBDMA) { -+ work = cvmx_pow_work_response_async(CVMX_SCR_SCRATCH); -+ } else { -+ if ((INTERRUPT_LIMIT == 0) -+ || likely(rx_count < MAX_RX_PACKETS)) -+ work = -+ cvmx_pow_work_request_sync -+ (CVMX_POW_NO_WAIT); -+ else -+ work = NULL; -+ } -+ prefetch(work); -+ if (work == NULL) -+ break; -+ -+ /* -+ * Limit each core to processing MAX_RX_PACKETS -+ * packets without a break. This way the RX can't -+ * starve the TX task. -+ */ -+ if (USE_ASYNC_IOBDMA) { -+ -+ if ((INTERRUPT_LIMIT == 0) -+ || likely(rx_count < MAX_RX_PACKETS)) -+ cvmx_pow_work_request_async_nocheck -+ (CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT); -+ else { -+ cvmx_scratch_write64(CVMX_SCR_SCRATCH, -+ 0x8000000000000000ull); -+ cvmx_pow_tag_sw_null_nocheck(); -+ } -+ } -+ -+ skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1; -+ if (likely(skb_in_hw)) { -+ skb = -+ *(struct sk_buff -+ **)(cvm_oct_get_buffer_ptr(work->packet_ptr) - -+ sizeof(void *)); -+ prefetch(&skb->head); -+ prefetch(&skb->len); -+ } -+ prefetch(cvm_oct_device[work->ipprt]); -+ -+ rx_count++; -+ /* Immediately throw away all packets with receive errors */ -+ if (unlikely(work->word2.snoip.rcv_error)) { -+ if (cvm_oct_check_rcv_error(work)) -+ continue; -+ } -+ -+ /* -+ * We can only use the zero copy path if skbuffs are -+ * in the FPA pool and the packet fits in a single -+ * buffer. -+ */ -+ if (likely(skb_in_hw)) { -+ /* -+ * This calculation was changed in case the -+ * skb header is using a different address -+ * aliasing type than the buffer. It doesn't -+ * make any differnece now, but the new one is -+ * more correct. -+ */ -+ skb->data = -+ skb->head + work->packet_ptr.s.addr - -+ cvmx_ptr_to_phys(skb->head); -+ prefetch(skb->data); -+ skb->len = work->len; -+ skb_set_tail_pointer(skb, skb->len); -+ packet_not_copied = 1; -+ } else { -+ -+ /* -+ * We have to copy the packet. First allocate -+ * an skbuff for it. -+ */ -+ skb = dev_alloc_skb(work->len); -+ if (!skb) { -+ DEBUGPRINT("Port %d failed to allocate " -+ "skbuff, packet dropped\n", -+ work->ipprt); -+ cvm_oct_free_work(work); -+ continue; -+ } -+ -+ /* -+ * Check if we've received a packet that was -+ * entirely stored in the work entry. This is -+ * untested. -+ */ -+ if (unlikely(work->word2.s.bufs == 0)) { -+ uint8_t *ptr = work->packet_data; -+ -+ if (likely(!work->word2.s.not_IP)) { -+ /* -+ * The beginning of the packet -+ * moves for IP packets. -+ */ -+ if (work->word2.s.is_v6) -+ ptr += 2; -+ else -+ ptr += 6; -+ } -+ memcpy(skb_put(skb, work->len), ptr, work->len); -+ /* No packet buffers to free */ -+ } else { -+ int segments = work->word2.s.bufs; -+ union cvmx_buf_ptr segment_ptr = -+ work->packet_ptr; -+ int len = work->len; -+ -+ while (segments--) { -+ union cvmx_buf_ptr next_ptr = -+ *(union cvmx_buf_ptr *) -+ cvmx_phys_to_ptr(segment_ptr.s. -+ addr - 8); -+ /* -+ * Octeon Errata PKI-100: The segment size is -+ * wrong. Until it is fixed, calculate the -+ * segment size based on the packet pool -+ * buffer size. When it is fixed, the -+ * following line should be replaced with this -+ * one: int segment_size = -+ * segment_ptr.s.size; -+ */ -+ int segment_size = -+ CVMX_FPA_PACKET_POOL_SIZE - -+ (segment_ptr.s.addr - -+ (((segment_ptr.s.addr >> 7) - -+ segment_ptr.s.back) << 7)); -+ /* Don't copy more than what is left -+ in the packet */ -+ if (segment_size > len) -+ segment_size = len; -+ /* Copy the data into the packet */ -+ memcpy(skb_put(skb, segment_size), -+ cvmx_phys_to_ptr(segment_ptr.s. -+ addr), -+ segment_size); -+ /* Reduce the amount of bytes left -+ to copy */ -+ len -= segment_size; -+ segment_ptr = next_ptr; -+ } -+ } -+ packet_not_copied = 0; -+ } -+ -+ if (likely((work->ipprt < TOTAL_NUMBER_OF_PORTS) && -+ cvm_oct_device[work->ipprt])) { -+ struct net_device *dev = cvm_oct_device[work->ipprt]; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ -+ /* Only accept packets for devices -+ that are currently up */ -+ if (likely(dev->flags & IFF_UP)) { -+ skb->protocol = eth_type_trans(skb, dev); -+ skb->dev = dev; -+ -+ if (unlikely -+ (work->word2.s.not_IP -+ || work->word2.s.IP_exc -+ || work->word2.s.L4_error)) -+ skb->ip_summed = CHECKSUM_NONE; -+ else -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ -+ /* Increment RX stats for virtual ports */ -+ if (work->ipprt >= CVMX_PIP_NUM_INPUT_PORTS) { -+#ifdef CONFIG_64BIT -+ atomic64_add(1, (atomic64_t *)&priv->stats.rx_packets); -+ atomic64_add(skb->len, (atomic64_t *)&priv->stats.rx_bytes); -+#else -+ atomic_add(1, (atomic_t *)&priv->stats.rx_packets); -+ atomic_add(skb->len, (atomic_t *)&priv->stats.rx_bytes); -+#endif -+ } -+ netif_receive_skb(skb); -+ } else { -+ /* -+ * Drop any packet received for a -+ * device that isn't up. -+ */ -+ /* -+ DEBUGPRINT("%s: Device not up, packet dropped\n", -+ dev->name); -+ */ -+#ifdef CONFIG_64BIT -+ atomic64_add(1, (atomic64_t *)&priv->stats.rx_dropped); -+#else -+ atomic_add(1, (atomic_t *)&priv->stats.rx_dropped); -+#endif -+ dev_kfree_skb_irq(skb); -+ } -+ } else { -+ /* -+ * Drop any packet received for a device that -+ * doesn't exist. -+ */ -+ DEBUGPRINT("Port %d not controlled by Linux, packet " -+ "dropped\n", -+ work->ipprt); -+ dev_kfree_skb_irq(skb); -+ } -+ /* -+ * Check to see if the skbuff and work share the same -+ * packet buffer. -+ */ -+ if (USE_SKBUFFS_IN_HW && likely(packet_not_copied)) { -+ /* -+ * This buffer needs to be replaced, increment -+ * the number of buffers we need to free by -+ * one. -+ */ -+ cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, -+ 1); -+ -+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, -+ DONT_WRITEBACK(1)); -+ } else { -+ cvm_oct_free_work(work); -+ } -+ } -+ -+ /* Restore the original POW group mask */ -+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask); -+ if (USE_ASYNC_IOBDMA) { -+ /* Restore the scratch area */ -+ cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); -+ } -+ -+ if (USE_SKBUFFS_IN_HW) { -+ /* Refill the packet buffer pool */ -+ number_to_free = -+ cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); -+ -+ if (number_to_free > 0) { -+ cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, -+ -number_to_free); -+ num_freed = -+ cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, -+ CVMX_FPA_PACKET_POOL_SIZE, -+ number_to_free); -+ if (num_freed != number_to_free) { -+ cvmx_fau_atomic_add32 -+ (FAU_NUM_PACKET_BUFFERS_TO_FREE, -+ number_to_free - num_freed); -+ } -+ } -+ } -+} -+ -+void cvm_oct_rx_initialize(void) -+{ -+ int i; -+ /* Initialize all of the tasklets */ -+ for (i = 0; i < NR_CPUS; i++) -+ tasklet_init(&cvm_oct_tasklet[i].t, cvm_oct_tasklet_rx, 0); -+} -+ -+void cvm_oct_rx_shutdown(void) -+{ -+ int i; -+ /* Shutdown all of the tasklets */ -+ for (i = 0; i < NR_CPUS; i++) -+ tasklet_kill(&cvm_oct_tasklet[i].t); -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-rx.h -@@ -0,0 +1,33 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+ -+irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id); -+void cvm_oct_poll_controller(struct net_device *dev); -+void cvm_oct_tasklet_rx(unsigned long unused); -+ -+void cvm_oct_rx_initialize(void); -+void cvm_oct_rx_shutdown(void); ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-sgmii.c -@@ -0,0 +1,129 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-util.h" -+#include "ethernet-common.h" -+ -+#include "cvmx-helper.h" -+ -+#include "cvmx-gmxx-defs.h" -+ -+static int cvm_oct_sgmii_open(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ cvmx_helper_link_info_t link_info; -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ -+ if (!octeon_is_simulation()) { -+ link_info = cvmx_helper_link_get(priv->port); -+ if (!link_info.s.link_up) -+ netif_carrier_off(dev); -+ } -+ -+ return 0; -+} -+ -+static int cvm_oct_sgmii_stop(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ return 0; -+} -+ -+static void cvm_oct_sgmii_poll(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ cvmx_helper_link_info_t link_info; -+ -+ link_info = cvmx_helper_link_get(priv->port); -+ if (link_info.u64 == priv->link_info) -+ return; -+ -+ link_info = cvmx_helper_link_autoconf(priv->port); -+ priv->link_info = link_info.u64; -+ -+ /* Tell Linux */ -+ if (link_info.s.link_up) { -+ -+ if (!netif_carrier_ok(dev)) -+ netif_carrier_on(dev); -+ if (priv->queue != -1) -+ DEBUGPRINT -+ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", -+ dev->name, link_info.s.speed, -+ (link_info.s.full_duplex) ? "Full" : "Half", -+ priv->port, priv->queue); -+ else -+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", -+ dev->name, link_info.s.speed, -+ (link_info.s.full_duplex) ? "Full" : "Half", -+ priv->port); -+ } else { -+ if (netif_carrier_ok(dev)) -+ netif_carrier_off(dev); -+ DEBUGPRINT("%s: Link down\n", dev->name); -+ } -+} -+ -+int cvm_oct_sgmii_init(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ cvm_oct_common_init(dev); -+ dev->open = cvm_oct_sgmii_open; -+ dev->stop = cvm_oct_sgmii_stop; -+ dev->stop(dev); -+ if (!octeon_is_simulation()) -+ priv->poll = cvm_oct_sgmii_poll; -+ -+ /* FIXME: Need autoneg logic */ -+ return 0; -+} -+ -+void cvm_oct_sgmii_uninit(struct net_device *dev) -+{ -+ cvm_oct_common_uninit(dev); -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-spi.c -@@ -0,0 +1,323 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-common.h" -+#include "ethernet-util.h" -+ -+#include "cvmx-spi.h" -+ -+#include -+#include "cvmx-spxx-defs.h" -+#include "cvmx-stxx-defs.h" -+ -+static int number_spi_ports; -+static int need_retrain[2] = { 0, 0 }; -+ -+static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) -+{ -+ irqreturn_t return_status = IRQ_NONE; -+ union cvmx_npi_rsl_int_blocks rsl_int_blocks; -+ -+ /* Check and see if this interrupt was caused by the GMX block */ -+ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); -+ if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */ -+ -+ union cvmx_spxx_int_reg spx_int_reg; -+ union cvmx_stxx_int_reg stx_int_reg; -+ -+ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1)); -+ cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64); -+ if (!need_retrain[1]) { -+ -+ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1)); -+ if (spx_int_reg.s.spf) -+ pr_err("SPI1: SRX Spi4 interface down\n"); -+ if (spx_int_reg.s.calerr) -+ pr_err("SPI1: SRX Spi4 Calendar table " -+ "parity error\n"); -+ if (spx_int_reg.s.syncerr) -+ pr_err("SPI1: SRX Consecutive Spi4 DIP4 " -+ "errors have exceeded " -+ "SPX_ERR_CTL[ERRCNT]\n"); -+ if (spx_int_reg.s.diperr) -+ pr_err("SPI1: SRX Spi4 DIP4 error\n"); -+ if (spx_int_reg.s.tpaovr) -+ pr_err("SPI1: SRX Selected port has hit " -+ "TPA overflow\n"); -+ if (spx_int_reg.s.rsverr) -+ pr_err("SPI1: SRX Spi4 reserved control " -+ "word detected\n"); -+ if (spx_int_reg.s.drwnng) -+ pr_err("SPI1: SRX Spi4 receive FIFO " -+ "drowning/overflow\n"); -+ if (spx_int_reg.s.clserr) -+ pr_err("SPI1: SRX Spi4 packet closed on " -+ "non-16B alignment without EOP\n"); -+ if (spx_int_reg.s.spiovr) -+ pr_err("SPI1: SRX Spi4 async FIFO overflow\n"); -+ if (spx_int_reg.s.abnorm) -+ pr_err("SPI1: SRX Abnormal packet " -+ "termination (ERR bit)\n"); -+ if (spx_int_reg.s.prtnxa) -+ pr_err("SPI1: SRX Port out of range\n"); -+ } -+ -+ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1)); -+ cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64); -+ if (!need_retrain[1]) { -+ -+ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1)); -+ if (stx_int_reg.s.syncerr) -+ pr_err("SPI1: STX Interface encountered a " -+ "fatal error\n"); -+ if (stx_int_reg.s.frmerr) -+ pr_err("SPI1: STX FRMCNT has exceeded " -+ "STX_DIP_CNT[MAXFRM]\n"); -+ if (stx_int_reg.s.unxfrm) -+ pr_err("SPI1: STX Unexpected framing " -+ "sequence\n"); -+ if (stx_int_reg.s.nosync) -+ pr_err("SPI1: STX ERRCNT has exceeded " -+ "STX_DIP_CNT[MAXDIP]\n"); -+ if (stx_int_reg.s.diperr) -+ pr_err("SPI1: STX DIP2 error on the Spi4 " -+ "Status channel\n"); -+ if (stx_int_reg.s.datovr) -+ pr_err("SPI1: STX Spi4 FIFO overflow error\n"); -+ if (stx_int_reg.s.ovrbst) -+ pr_err("SPI1: STX Transmit packet burst " -+ "too big\n"); -+ if (stx_int_reg.s.calpar1) -+ pr_err("SPI1: STX Calendar Table Parity " -+ "Error Bank1\n"); -+ if (stx_int_reg.s.calpar0) -+ pr_err("SPI1: STX Calendar Table Parity " -+ "Error Bank0\n"); -+ } -+ -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0); -+ cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0); -+ need_retrain[1] = 1; -+ return_status = IRQ_HANDLED; -+ } -+ -+ if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */ -+ union cvmx_spxx_int_reg spx_int_reg; -+ union cvmx_stxx_int_reg stx_int_reg; -+ -+ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0)); -+ cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64); -+ if (!need_retrain[0]) { -+ -+ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0)); -+ if (spx_int_reg.s.spf) -+ pr_err("SPI0: SRX Spi4 interface down\n"); -+ if (spx_int_reg.s.calerr) -+ pr_err("SPI0: SRX Spi4 Calendar table " -+ "parity error\n"); -+ if (spx_int_reg.s.syncerr) -+ pr_err("SPI0: SRX Consecutive Spi4 DIP4 " -+ "errors have exceeded " -+ "SPX_ERR_CTL[ERRCNT]\n"); -+ if (spx_int_reg.s.diperr) -+ pr_err("SPI0: SRX Spi4 DIP4 error\n"); -+ if (spx_int_reg.s.tpaovr) -+ pr_err("SPI0: SRX Selected port has hit " -+ "TPA overflow\n"); -+ if (spx_int_reg.s.rsverr) -+ pr_err("SPI0: SRX Spi4 reserved control " -+ "word detected\n"); -+ if (spx_int_reg.s.drwnng) -+ pr_err("SPI0: SRX Spi4 receive FIFO " -+ "drowning/overflow\n"); -+ if (spx_int_reg.s.clserr) -+ pr_err("SPI0: SRX Spi4 packet closed on " -+ "non-16B alignment without EOP\n"); -+ if (spx_int_reg.s.spiovr) -+ pr_err("SPI0: SRX Spi4 async FIFO overflow\n"); -+ if (spx_int_reg.s.abnorm) -+ pr_err("SPI0: SRX Abnormal packet " -+ "termination (ERR bit)\n"); -+ if (spx_int_reg.s.prtnxa) -+ pr_err("SPI0: SRX Port out of range\n"); -+ } -+ -+ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0)); -+ cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64); -+ if (!need_retrain[0]) { -+ -+ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0)); -+ if (stx_int_reg.s.syncerr) -+ pr_err("SPI0: STX Interface encountered a " -+ "fatal error\n"); -+ if (stx_int_reg.s.frmerr) -+ pr_err("SPI0: STX FRMCNT has exceeded " -+ "STX_DIP_CNT[MAXFRM]\n"); -+ if (stx_int_reg.s.unxfrm) -+ pr_err("SPI0: STX Unexpected framing " -+ "sequence\n"); -+ if (stx_int_reg.s.nosync) -+ pr_err("SPI0: STX ERRCNT has exceeded " -+ "STX_DIP_CNT[MAXDIP]\n"); -+ if (stx_int_reg.s.diperr) -+ pr_err("SPI0: STX DIP2 error on the Spi4 " -+ "Status channel\n"); -+ if (stx_int_reg.s.datovr) -+ pr_err("SPI0: STX Spi4 FIFO overflow error\n"); -+ if (stx_int_reg.s.ovrbst) -+ pr_err("SPI0: STX Transmit packet burst " -+ "too big\n"); -+ if (stx_int_reg.s.calpar1) -+ pr_err("SPI0: STX Calendar Table Parity " -+ "Error Bank1\n"); -+ if (stx_int_reg.s.calpar0) -+ pr_err("SPI0: STX Calendar Table Parity " -+ "Error Bank0\n"); -+ } -+ -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0); -+ cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0); -+ need_retrain[0] = 1; -+ return_status = IRQ_HANDLED; -+ } -+ -+ return return_status; -+} -+ -+static void cvm_oct_spi_enable_error_reporting(int interface) -+{ -+ union cvmx_spxx_int_msk spxx_int_msk; -+ union cvmx_stxx_int_msk stxx_int_msk; -+ -+ spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); -+ spxx_int_msk.s.calerr = 1; -+ spxx_int_msk.s.syncerr = 1; -+ spxx_int_msk.s.diperr = 1; -+ spxx_int_msk.s.tpaovr = 1; -+ spxx_int_msk.s.rsverr = 1; -+ spxx_int_msk.s.drwnng = 1; -+ spxx_int_msk.s.clserr = 1; -+ spxx_int_msk.s.spiovr = 1; -+ spxx_int_msk.s.abnorm = 1; -+ spxx_int_msk.s.prtnxa = 1; -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); -+ -+ stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); -+ stxx_int_msk.s.frmerr = 1; -+ stxx_int_msk.s.unxfrm = 1; -+ stxx_int_msk.s.nosync = 1; -+ stxx_int_msk.s.diperr = 1; -+ stxx_int_msk.s.datovr = 1; -+ stxx_int_msk.s.ovrbst = 1; -+ stxx_int_msk.s.calpar1 = 1; -+ stxx_int_msk.s.calpar0 = 1; -+ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); -+} -+ -+static void cvm_oct_spi_poll(struct net_device *dev) -+{ -+ static int spi4000_port; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface; -+ -+ for (interface = 0; interface < 2; interface++) { -+ -+ if ((priv->port == interface * 16) && need_retrain[interface]) { -+ -+ if (cvmx_spi_restart_interface -+ (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) { -+ need_retrain[interface] = 0; -+ cvm_oct_spi_enable_error_reporting(interface); -+ } -+ } -+ -+ /* -+ * The SPI4000 TWSI interface is very slow. In order -+ * not to bring the system to a crawl, we only poll a -+ * single port every second. This means negotiation -+ * speed changes take up to 10 seconds, but at least -+ * we don't waste absurd amounts of time waiting for -+ * TWSI. -+ */ -+ if (priv->port == spi4000_port) { -+ /* -+ * This function does nothing if it is called on an -+ * interface without a SPI4000. -+ */ -+ cvmx_spi4000_check_speed(interface, priv->port); -+ /* -+ * Normal ordering increments. By decrementing -+ * we only match once per iteration. -+ */ -+ spi4000_port--; -+ if (spi4000_port < 0) -+ spi4000_port = 10; -+ } -+ } -+} -+ -+int cvm_oct_spi_init(struct net_device *dev) -+{ -+ int r; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ -+ if (number_spi_ports == 0) { -+ r = request_irq(OCTEON_IRQ_RML, cvm_oct_spi_rml_interrupt, -+ IRQF_SHARED, "SPI", &number_spi_ports); -+ } -+ number_spi_ports++; -+ -+ if ((priv->port == 0) || (priv->port == 16)) { -+ cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port)); -+ priv->poll = cvm_oct_spi_poll; -+ } -+ cvm_oct_common_init(dev); -+ return 0; -+} -+ -+void cvm_oct_spi_uninit(struct net_device *dev) -+{ -+ int interface; -+ -+ cvm_oct_common_uninit(dev); -+ number_spi_ports--; -+ if (number_spi_ports == 0) { -+ for (interface = 0; interface < 2; interface++) { -+ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); -+ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); -+ } -+ free_irq(8 + 46, &number_spi_ports); -+ } -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-tx.c -@@ -0,0 +1,634 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_XFRM -+#include -+#include -+#endif /* CONFIG_XFRM */ -+ -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-util.h" -+ -+#include "cvmx-wqe.h" -+#include "cvmx-fau.h" -+#include "cvmx-pko.h" -+#include "cvmx-helper.h" -+ -+#include "cvmx-gmxx-defs.h" -+ -+/* -+ * You can define GET_SKBUFF_QOS() to override how the skbuff output -+ * function determines which output queue is used. The default -+ * implementation always uses the base queue for the port. If, for -+ * example, you wanted to use the skb->priority fieid, define -+ * GET_SKBUFF_QOS as: #define GET_SKBUFF_QOS(skb) ((skb)->priority) -+ */ -+#ifndef GET_SKBUFF_QOS -+#define GET_SKBUFF_QOS(skb) 0 -+#endif -+ -+/** -+ * Packet transmit -+ * -+ * @skb: Packet to send -+ * @dev: Device info structure -+ * Returns Always returns zero -+ */ -+int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ cvmx_pko_command_word0_t pko_command; -+ union cvmx_buf_ptr hw_buffer; -+ uint64_t old_scratch; -+ uint64_t old_scratch2; -+ int dropped; -+ int qos; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int32_t in_use; -+ int32_t buffers_to_free; -+#if REUSE_SKBUFFS_WITHOUT_FREE -+ unsigned char *fpa_head; -+#endif -+ -+ /* -+ * Prefetch the private data structure. It is larger that one -+ * cache line. -+ */ -+ prefetch(priv); -+ -+ /* Start off assuming no drop */ -+ dropped = 0; -+ -+ /* -+ * The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to -+ * completely remove "qos" in the event neither interface -+ * supports multiple queues per port. -+ */ -+ if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) || -+ (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) { -+ qos = GET_SKBUFF_QOS(skb); -+ if (qos <= 0) -+ qos = 0; -+ else if (qos >= cvmx_pko_get_num_queues(priv->port)) -+ qos = 0; -+ } else -+ qos = 0; -+ -+ if (USE_ASYNC_IOBDMA) { -+ /* Save scratch in case userspace is using it */ -+ CVMX_SYNCIOBDMA; -+ old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); -+ old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); -+ -+ /* -+ * Assume we're going to be able t osend this -+ * packet. Fetch and increment the number of pending -+ * packets for output. -+ */ -+ cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH + 8, -+ FAU_NUM_PACKET_BUFFERS_TO_FREE, -+ 0); -+ cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, -+ priv->fau + qos * 4, 1); -+ } -+ -+ /* -+ * The CN3XXX series of parts has an errata (GMX-401) which -+ * causes the GMX block to hang if a collision occurs towards -+ * the end of a <68 byte packet. As a workaround for this, we -+ * pad packets to be 68 bytes whenever we are in half duplex -+ * mode. We don't handle the case of having a small packet but -+ * no room to add the padding. The kernel should always give -+ * us at least a cache line -+ */ -+ if ((skb->len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ union cvmx_gmxx_prtx_cfg gmx_prt_cfg; -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ if (interface < 2) { -+ /* We only need to pad packet in half duplex mode */ -+ gmx_prt_cfg.u64 = -+ cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ if (gmx_prt_cfg.s.duplex == 0) { -+ int add_bytes = 64 - skb->len; -+ if ((skb_tail_pointer(skb) + add_bytes) <= -+ skb_end_pointer(skb)) -+ memset(__skb_put(skb, add_bytes), 0, -+ add_bytes); -+ } -+ } -+ } -+ -+ /* Build the PKO buffer pointer */ -+ hw_buffer.u64 = 0; -+ hw_buffer.s.addr = cvmx_ptr_to_phys(skb->data); -+ hw_buffer.s.pool = 0; -+ hw_buffer.s.size = -+ (unsigned long)skb_end_pointer(skb) - (unsigned long)skb->head; -+ -+ /* Build the PKO command */ -+ pko_command.u64 = 0; -+ pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ -+ pko_command.s.segs = 1; -+ pko_command.s.total_bytes = skb->len; -+ pko_command.s.size0 = CVMX_FAU_OP_SIZE_32; -+ pko_command.s.subone0 = 1; -+ -+ pko_command.s.dontfree = 1; -+ pko_command.s.reg0 = priv->fau + qos * 4; -+ /* -+ * See if we can put this skb in the FPA pool. Any strange -+ * behavior from the Linux networking stack will most likely -+ * be caused by a bug in the following code. If some field is -+ * in use by the network stack and get carried over when a -+ * buffer is reused, bad thing may happen. If in doubt and -+ * you dont need the absolute best performance, disable the -+ * define REUSE_SKBUFFS_WITHOUT_FREE. The reuse of buffers has -+ * shown a 25% increase in performance under some loads. -+ */ -+#if REUSE_SKBUFFS_WITHOUT_FREE -+ fpa_head = skb->head + 128 - ((unsigned long)skb->head & 0x7f); -+ if (unlikely(skb->data < fpa_head)) { -+ /* -+ * printk("TX buffer beginning can't meet FPA -+ * alignment constraints\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely -+ ((skb_end_pointer(skb) - fpa_head) < CVMX_FPA_PACKET_POOL_SIZE)) { -+ /* -+ printk("TX buffer isn't large enough for the FPA\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely(skb_shared(skb))) { -+ /* -+ printk("TX buffer sharing data with someone else\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely(skb_cloned(skb))) { -+ /* -+ printk("TX buffer has been cloned\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely(skb_header_cloned(skb))) { -+ /* -+ printk("TX buffer header has been cloned\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely(skb->destructor)) { -+ /* -+ printk("TX buffer has a destructor\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely(skb_shinfo(skb)->nr_frags)) { -+ /* -+ printk("TX buffer has fragments\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ if (unlikely -+ (skb->truesize != -+ sizeof(*skb) + skb_end_pointer(skb) - skb->head)) { -+ /* -+ printk("TX buffer truesize has been changed\n"); -+ */ -+ goto dont_put_skbuff_in_hw; -+ } -+ -+ /* -+ * We can use this buffer in the FPA. We don't need the FAU -+ * update anymore -+ */ -+ pko_command.s.reg0 = 0; -+ pko_command.s.dontfree = 0; -+ -+ hw_buffer.s.back = (skb->data - fpa_head) >> 7; -+ *(struct sk_buff **)(fpa_head - sizeof(void *)) = skb; -+ -+ /* -+ * The skbuff will be reused without ever being freed. We must -+ * cleanup a bunch of Linux stuff. -+ */ -+ dst_release(skb->dst); -+ skb->dst = NULL; -+#ifdef CONFIG_XFRM -+ secpath_put(skb->sp); -+ skb->sp = NULL; -+#endif -+ nf_reset(skb); -+ -+#ifdef CONFIG_NET_SCHED -+ skb->tc_index = 0; -+#ifdef CONFIG_NET_CLS_ACT -+ skb->tc_verd = 0; -+#endif /* CONFIG_NET_CLS_ACT */ -+#endif /* CONFIG_NET_SCHED */ -+ -+dont_put_skbuff_in_hw: -+#endif /* REUSE_SKBUFFS_WITHOUT_FREE */ -+ -+ /* Check if we can use the hardware checksumming */ -+ if (USE_HW_TCPUDP_CHECKSUM && (skb->protocol == htons(ETH_P_IP)) && -+ (ip_hdr(skb)->version == 4) && (ip_hdr(skb)->ihl == 5) && -+ ((ip_hdr(skb)->frag_off == 0) || (ip_hdr(skb)->frag_off == 1 << 14)) -+ && ((ip_hdr(skb)->protocol == IP_PROTOCOL_TCP) -+ || (ip_hdr(skb)->protocol == IP_PROTOCOL_UDP))) { -+ /* Use hardware checksum calc */ -+ pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; -+ } -+ -+ if (USE_ASYNC_IOBDMA) { -+ /* Get the number of skbuffs in use by the hardware */ -+ CVMX_SYNCIOBDMA; -+ in_use = cvmx_scratch_read64(CVMX_SCR_SCRATCH); -+ buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); -+ } else { -+ /* Get the number of skbuffs in use by the hardware */ -+ in_use = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, 1); -+ buffers_to_free = -+ cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); -+ } -+ -+ /* -+ * If we're sending faster than the receive can free them then -+ * don't do the HW free. -+ */ -+ if ((buffers_to_free < -100) && !pko_command.s.dontfree) { -+ pko_command.s.dontfree = 1; -+ pko_command.s.reg0 = priv->fau + qos * 4; -+ } -+ -+ cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, -+ CVMX_PKO_LOCK_CMD_QUEUE); -+ -+ /* Drop this packet if we have too many already queued to the HW */ -+ if (unlikely -+ (skb_queue_len(&priv->tx_free_list[qos]) >= MAX_OUT_QUEUE_DEPTH)) { -+ /* -+ DEBUGPRINT("%s: Tx dropped. Too many queued\n", dev->name); -+ */ -+ dropped = 1; -+ } -+ /* Send the packet to the output queue */ -+ else if (unlikely -+ (cvmx_pko_send_packet_finish -+ (priv->port, priv->queue + qos, pko_command, hw_buffer, -+ CVMX_PKO_LOCK_CMD_QUEUE))) { -+ DEBUGPRINT("%s: Failed to send the packet\n", dev->name); -+ dropped = 1; -+ } -+ -+ if (USE_ASYNC_IOBDMA) { -+ /* Restore the scratch area */ -+ cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); -+ cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); -+ } -+ -+ if (unlikely(dropped)) { -+ dev_kfree_skb_any(skb); -+ cvmx_fau_atomic_add32(priv->fau + qos * 4, -1); -+ priv->stats.tx_dropped++; -+ } else { -+ if (USE_SKBUFFS_IN_HW) { -+ /* Put this packet on the queue to be freed later */ -+ if (pko_command.s.dontfree) -+ skb_queue_tail(&priv->tx_free_list[qos], skb); -+ else { -+ cvmx_fau_atomic_add32 -+ (FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); -+ cvmx_fau_atomic_add32(priv->fau + qos * 4, -1); -+ } -+ } else { -+ /* Put this packet on the queue to be freed later */ -+ skb_queue_tail(&priv->tx_free_list[qos], skb); -+ } -+ } -+ -+ /* Free skbuffs not in use by the hardware, possibly two at a time */ -+ if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) { -+ spin_lock(&priv->tx_free_list[qos].lock); -+ /* -+ * Check again now that we have the lock. It might -+ * have changed. -+ */ -+ if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) -+ dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); -+ if (skb_queue_len(&priv->tx_free_list[qos]) > in_use) -+ dev_kfree_skb(__skb_dequeue(&priv->tx_free_list[qos])); -+ spin_unlock(&priv->tx_free_list[qos].lock); -+ } -+ -+ return 0; -+} -+ -+/** -+ * Packet transmit to the POW -+ * -+ * @skb: Packet to send -+ * @dev: Device info structure -+ * Returns Always returns zero -+ */ -+int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ void *packet_buffer; -+ void *copy_location; -+ -+ /* Get a work queue entry */ -+ cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL); -+ if (unlikely(work == NULL)) { -+ DEBUGPRINT("%s: Failed to allocate a work queue entry\n", -+ dev->name); -+ priv->stats.tx_dropped++; -+ dev_kfree_skb(skb); -+ return 0; -+ } -+ -+ /* Get a packet buffer */ -+ packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); -+ if (unlikely(packet_buffer == NULL)) { -+ DEBUGPRINT("%s: Failed to allocate a packet buffer\n", -+ dev->name); -+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); -+ priv->stats.tx_dropped++; -+ dev_kfree_skb(skb); -+ return 0; -+ } -+ -+ /* -+ * Calculate where we need to copy the data to. We need to -+ * leave 8 bytes for a next pointer (unused). We also need to -+ * include any configure skip. Then we need to align the IP -+ * packet src and dest into the same 64bit word. The below -+ * calculation may add a little extra, but that doesn't -+ * hurt. -+ */ -+ copy_location = packet_buffer + sizeof(uint64_t); -+ copy_location += ((CVMX_HELPER_FIRST_MBUFF_SKIP + 7) & 0xfff8) + 6; -+ -+ /* -+ * We have to copy the packet since whoever processes this -+ * packet will free it to a hardware pool. We can't use the -+ * trick of counting outstanding packets like in -+ * cvm_oct_xmit. -+ */ -+ memcpy(copy_location, skb->data, skb->len); -+ -+ /* -+ * Fill in some of the work queue fields. We may need to add -+ * more if the software at the other end needs them. -+ */ -+ work->hw_chksum = skb->csum; -+ work->len = skb->len; -+ work->ipprt = priv->port; -+ work->qos = priv->port & 0x7; -+ work->grp = pow_send_group; -+ work->tag_type = CVMX_HELPER_INPUT_TAG_TYPE; -+ work->tag = pow_send_group; /* FIXME */ -+ /* Default to zero. Sets of zero later are commented out */ -+ work->word2.u64 = 0; -+ work->word2.s.bufs = 1; -+ work->packet_ptr.u64 = 0; -+ work->packet_ptr.s.addr = cvmx_ptr_to_phys(copy_location); -+ work->packet_ptr.s.pool = CVMX_FPA_PACKET_POOL; -+ work->packet_ptr.s.size = CVMX_FPA_PACKET_POOL_SIZE; -+ work->packet_ptr.s.back = (copy_location - packet_buffer) >> 7; -+ -+ if (skb->protocol == htons(ETH_P_IP)) { -+ work->word2.s.ip_offset = 14; -+#if 0 -+ work->word2.s.vlan_valid = 0; /* FIXME */ -+ work->word2.s.vlan_cfi = 0; /* FIXME */ -+ work->word2.s.vlan_id = 0; /* FIXME */ -+ work->word2.s.dec_ipcomp = 0; /* FIXME */ -+#endif -+ work->word2.s.tcp_or_udp = -+ (ip_hdr(skb)->protocol == IP_PROTOCOL_TCP) -+ || (ip_hdr(skb)->protocol == IP_PROTOCOL_UDP); -+#if 0 -+ /* FIXME */ -+ work->word2.s.dec_ipsec = 0; -+ /* We only support IPv4 right now */ -+ work->word2.s.is_v6 = 0; -+ /* Hardware would set to zero */ -+ work->word2.s.software = 0; -+ /* No error, packet is internal */ -+ work->word2.s.L4_error = 0; -+#endif -+ work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) -+ || (ip_hdr(skb)->frag_off == -+ 1 << 14)); -+#if 0 -+ /* Assume Linux is sending a good packet */ -+ work->word2.s.IP_exc = 0; -+#endif -+ work->word2.s.is_bcast = (skb->pkt_type == PACKET_BROADCAST); -+ work->word2.s.is_mcast = (skb->pkt_type == PACKET_MULTICAST); -+#if 0 -+ /* This is an IP packet */ -+ work->word2.s.not_IP = 0; -+ /* No error, packet is internal */ -+ work->word2.s.rcv_error = 0; -+ /* No error, packet is internal */ -+ work->word2.s.err_code = 0; -+#endif -+ -+ /* -+ * When copying the data, include 4 bytes of the -+ * ethernet header to align the same way hardware -+ * does. -+ */ -+ memcpy(work->packet_data, skb->data + 10, -+ sizeof(work->packet_data)); -+ } else { -+#if 0 -+ work->word2.snoip.vlan_valid = 0; /* FIXME */ -+ work->word2.snoip.vlan_cfi = 0; /* FIXME */ -+ work->word2.snoip.vlan_id = 0; /* FIXME */ -+ work->word2.snoip.software = 0; /* Hardware would set to zero */ -+#endif -+ work->word2.snoip.is_rarp = skb->protocol == htons(ETH_P_RARP); -+ work->word2.snoip.is_arp = skb->protocol == htons(ETH_P_ARP); -+ work->word2.snoip.is_bcast = -+ (skb->pkt_type == PACKET_BROADCAST); -+ work->word2.snoip.is_mcast = -+ (skb->pkt_type == PACKET_MULTICAST); -+ work->word2.snoip.not_IP = 1; /* IP was done up above */ -+#if 0 -+ /* No error, packet is internal */ -+ work->word2.snoip.rcv_error = 0; -+ /* No error, packet is internal */ -+ work->word2.snoip.err_code = 0; -+#endif -+ memcpy(work->packet_data, skb->data, sizeof(work->packet_data)); -+ } -+ -+ /* Submit the packet to the POW */ -+ cvmx_pow_work_submit(work, work->tag, work->tag_type, work->qos, -+ work->grp); -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += skb->len; -+ dev_kfree_skb(skb); -+ return 0; -+} -+ -+/** -+ * Transmit a work queue entry out of the ethernet port. Both -+ * the work queue entry and the packet data can optionally be -+ * freed. The work will be freed on error as well. -+ * -+ * @dev: Device to transmit out. -+ * @work_queue_entry: -+ * Work queue entry to send -+ * @do_free: True if the work queue entry and packet data should be -+ * freed. If false, neither will be freed. -+ * @qos: Index into the queues for this port to transmit on. This -+ * is used to implement QoS if their are multiple queues per -+ * port. This parameter must be between 0 and the number of -+ * queues per port minus 1. Values outside of this range will -+ * be change to zero. -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, -+ int do_free, int qos) -+{ -+ unsigned long flags; -+ union cvmx_buf_ptr hw_buffer; -+ cvmx_pko_command_word0_t pko_command; -+ int dropped; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ cvmx_wqe_t *work = work_queue_entry; -+ -+ if (!(dev->flags & IFF_UP)) { -+ DEBUGPRINT("%s: Device not up\n", dev->name); -+ if (do_free) -+ cvm_oct_free_work(work); -+ return -1; -+ } -+ -+ /* The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to completely -+ remove "qos" in the event neither interface supports -+ multiple queues per port */ -+ if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) || -+ (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) { -+ if (qos <= 0) -+ qos = 0; -+ else if (qos >= cvmx_pko_get_num_queues(priv->port)) -+ qos = 0; -+ } else -+ qos = 0; -+ -+ /* Start off assuming no drop */ -+ dropped = 0; -+ -+ local_irq_save(flags); -+ cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, -+ CVMX_PKO_LOCK_CMD_QUEUE); -+ -+ /* Build the PKO buffer pointer */ -+ hw_buffer.u64 = 0; -+ hw_buffer.s.addr = work->packet_ptr.s.addr; -+ hw_buffer.s.pool = CVMX_FPA_PACKET_POOL; -+ hw_buffer.s.size = CVMX_FPA_PACKET_POOL_SIZE; -+ hw_buffer.s.back = work->packet_ptr.s.back; -+ -+ /* Build the PKO command */ -+ pko_command.u64 = 0; -+ pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ -+ pko_command.s.dontfree = !do_free; -+ pko_command.s.segs = work->word2.s.bufs; -+ pko_command.s.total_bytes = work->len; -+ -+ /* Check if we can use the hardware checksumming */ -+ if (unlikely(work->word2.s.not_IP || work->word2.s.IP_exc)) -+ pko_command.s.ipoffp1 = 0; -+ else -+ pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; -+ -+ /* Send the packet to the output queue */ -+ if (unlikely -+ (cvmx_pko_send_packet_finish -+ (priv->port, priv->queue + qos, pko_command, hw_buffer, -+ CVMX_PKO_LOCK_CMD_QUEUE))) { -+ DEBUGPRINT("%s: Failed to send the packet\n", dev->name); -+ dropped = -1; -+ } -+ local_irq_restore(flags); -+ -+ if (unlikely(dropped)) { -+ if (do_free) -+ cvm_oct_free_work(work); -+ priv->stats.tx_dropped++; -+ } else if (do_free) -+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); -+ -+ return dropped; -+} -+EXPORT_SYMBOL(cvm_oct_transmit_qos); -+ -+/** -+ * This function frees all skb that are currenty queued for TX. -+ * -+ * @dev: Device being shutdown -+ */ -+void cvm_oct_tx_shutdown(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ unsigned long flags; -+ int qos; -+ -+ for (qos = 0; qos < 16; qos++) { -+ spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); -+ while (skb_queue_len(&priv->tx_free_list[qos])) -+ dev_kfree_skb_any(__skb_dequeue -+ (&priv->tx_free_list[qos])); -+ spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); -+ } -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-tx.h -@@ -0,0 +1,32 @@ -+/********************************************************************* -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+ -+int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev); -+int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev); -+int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, -+ int do_free, int qos); -+void cvm_oct_tx_shutdown(struct net_device *dev); ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-util.h -@@ -0,0 +1,81 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+*********************************************************************/ -+ -+#define DEBUGPRINT(format, ...) do { if (printk_ratelimit()) \ -+ printk(format, ##__VA_ARGS__); \ -+ } while (0) -+ -+/** -+ * Given a packet data address, return a pointer to the -+ * beginning of the packet buffer. -+ * -+ * @packet_ptr: Packet data hardware address -+ * Returns Packet buffer pointer -+ */ -+static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr) -+{ -+ return cvmx_phys_to_ptr(((packet_ptr.s.addr >> 7) - packet_ptr.s.back) -+ << 7); -+} -+ -+/** -+ * Given an IPD/PKO port number, return the logical interface it is -+ * on. -+ * -+ * @ipd_port: Port to check -+ * -+ * Returns Logical interface -+ */ -+static inline int INTERFACE(int ipd_port) -+{ -+ if (ipd_port < 32) /* Interface 0 or 1 for RGMII,GMII,SPI, etc */ -+ return ipd_port >> 4; -+ else if (ipd_port < 36) /* Interface 2 for NPI */ -+ return 2; -+ else if (ipd_port < 40) /* Interface 3 for loopback */ -+ return 3; -+ else if (ipd_port == 40) /* Non existant interface for POW0 */ -+ return 4; -+ else -+ panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port); -+} -+ -+/** -+ * Given an IPD/PKO port number, return the port's index on a -+ * logical interface. -+ * -+ * @ipd_port: Port to check -+ * -+ * Returns Index into interface port list -+ */ -+static inline int INDEX(int ipd_port) -+{ -+ if (ipd_port < 32) -+ return ipd_port & 15; -+ else -+ return ipd_port & 3; -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet-xaui.c -@@ -0,0 +1,127 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "octeon-ethernet.h" -+#include "ethernet-common.h" -+#include "ethernet-util.h" -+ -+#include "cvmx-helper.h" -+ -+#include "cvmx-gmxx-defs.h" -+ -+static int cvm_oct_xaui_open(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ cvmx_helper_link_info_t link_info; -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmx_cfg.s.en = 1; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ -+ if (!octeon_is_simulation()) { -+ link_info = cvmx_helper_link_get(priv->port); -+ if (!link_info.s.link_up) -+ netif_carrier_off(dev); -+ } -+ return 0; -+} -+ -+static int cvm_oct_xaui_stop(struct net_device *dev) -+{ -+ union cvmx_gmxx_prtx_cfg gmx_cfg; -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ int interface = INTERFACE(priv->port); -+ int index = INDEX(priv->port); -+ -+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); -+ gmx_cfg.s.en = 0; -+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); -+ return 0; -+} -+ -+static void cvm_oct_xaui_poll(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ cvmx_helper_link_info_t link_info; -+ -+ link_info = cvmx_helper_link_get(priv->port); -+ if (link_info.u64 == priv->link_info) -+ return; -+ -+ link_info = cvmx_helper_link_autoconf(priv->port); -+ priv->link_info = link_info.u64; -+ -+ /* Tell Linux */ -+ if (link_info.s.link_up) { -+ -+ if (!netif_carrier_ok(dev)) -+ netif_carrier_on(dev); -+ if (priv->queue != -1) -+ DEBUGPRINT -+ ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", -+ dev->name, link_info.s.speed, -+ (link_info.s.full_duplex) ? "Full" : "Half", -+ priv->port, priv->queue); -+ else -+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", -+ dev->name, link_info.s.speed, -+ (link_info.s.full_duplex) ? "Full" : "Half", -+ priv->port); -+ } else { -+ if (netif_carrier_ok(dev)) -+ netif_carrier_off(dev); -+ DEBUGPRINT("%s: Link down\n", dev->name); -+ } -+} -+ -+int cvm_oct_xaui_init(struct net_device *dev) -+{ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ cvm_oct_common_init(dev); -+ dev->open = cvm_oct_xaui_open; -+ dev->stop = cvm_oct_xaui_stop; -+ dev->stop(dev); -+ if (!octeon_is_simulation()) -+ priv->poll = cvm_oct_xaui_poll; -+ -+ return 0; -+} -+ -+void cvm_oct_xaui_uninit(struct net_device *dev) -+{ -+ cvm_oct_common_uninit(dev); -+} ---- /dev/null -+++ b/drivers/staging/octeon/ethernet.c -@@ -0,0 +1,507 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+#include "ethernet-defines.h" -+#include "ethernet-mem.h" -+#include "ethernet-rx.h" -+#include "ethernet-tx.h" -+#include "ethernet-util.h" -+#include "ethernet-proc.h" -+#include "ethernet-common.h" -+#include "octeon-ethernet.h" -+ -+#include "cvmx-pip.h" -+#include "cvmx-pko.h" -+#include "cvmx-fau.h" -+#include "cvmx-ipd.h" -+#include "cvmx-helper.h" -+ -+#include "cvmx-smix-defs.h" -+ -+#if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \ -+ && CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS -+int num_packet_buffers = CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS; -+#else -+int num_packet_buffers = 1024; -+#endif -+module_param(num_packet_buffers, int, 0444); -+MODULE_PARM_DESC(num_packet_buffers, "\n" -+ "\tNumber of packet buffers to allocate and store in the\n" -+ "\tFPA. By default, 1024 packet buffers are used unless\n" -+ "\tCONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS is defined."); -+ -+int pow_receive_group = 15; -+module_param(pow_receive_group, int, 0444); -+MODULE_PARM_DESC(pow_receive_group, "\n" -+ "\tPOW group to receive packets from. All ethernet hardware\n" -+ "\twill be configured to send incomming packets to this POW\n" -+ "\tgroup. Also any other software can submit packets to this\n" -+ "\tgroup for the kernel to process."); -+ -+int pow_send_group = -1; -+module_param(pow_send_group, int, 0644); -+MODULE_PARM_DESC(pow_send_group, "\n" -+ "\tPOW group to send packets to other software on. This\n" -+ "\tcontrols the creation of the virtual device pow0.\n" -+ "\talways_use_pow also depends on this value."); -+ -+int always_use_pow; -+module_param(always_use_pow, int, 0444); -+MODULE_PARM_DESC(always_use_pow, "\n" -+ "\tWhen set, always send to the pow group. This will cause\n" -+ "\tpackets sent to real ethernet devices to be sent to the\n" -+ "\tPOW group instead of the hardware. Unless some other\n" -+ "\tapplication changes the config, packets will still be\n" -+ "\treceived from the low level hardware. Use this option\n" -+ "\tto allow a CVMX app to intercept all packets from the\n" -+ "\tlinux kernel. You must specify pow_send_group along with\n" -+ "\tthis option."); -+ -+char pow_send_list[128] = ""; -+module_param_string(pow_send_list, pow_send_list, sizeof(pow_send_list), 0444); -+MODULE_PARM_DESC(pow_send_list, "\n" -+ "\tComma separated list of ethernet devices that should use the\n" -+ "\tPOW for transmit instead of the actual ethernet hardware. This\n" -+ "\tis a per port version of always_use_pow. always_use_pow takes\n" -+ "\tprecedence over this list. For example, setting this to\n" -+ "\t\"eth2,spi3,spi7\" would cause these three devices to transmit\n" -+ "\tusing the pow_send_group."); -+ -+static int disable_core_queueing = 1; -+module_param(disable_core_queueing, int, 0444); -+MODULE_PARM_DESC(disable_core_queueing, "\n" -+ "\tWhen set the networking core's tx_queue_len is set to zero. This\n" -+ "\tallows packets to be sent without lock contention in the packet\n" -+ "\tscheduler resulting in some cases in improved throughput.\n"); -+ -+/** -+ * Periodic timer to check auto negotiation -+ */ -+static struct timer_list cvm_oct_poll_timer; -+ -+/** -+ * Array of every ethernet device owned by this driver indexed by -+ * the ipd input port number. -+ */ -+struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS]; -+ -+extern struct semaphore mdio_sem; -+ -+/** -+ * Periodic timer tick for slow management operations -+ * -+ * @arg: Device to check -+ */ -+static void cvm_do_timer(unsigned long arg) -+{ -+ static int port; -+ if (port < CVMX_PIP_NUM_INPUT_PORTS) { -+ if (cvm_oct_device[port]) { -+ int queues_per_port; -+ int qos; -+ struct octeon_ethernet *priv = -+ netdev_priv(cvm_oct_device[port]); -+ if (priv->poll) { -+ /* skip polling if we don't get the lock */ -+ if (!down_trylock(&mdio_sem)) { -+ priv->poll(cvm_oct_device[port]); -+ up(&mdio_sem); -+ } -+ } -+ -+ queues_per_port = cvmx_pko_get_num_queues(port); -+ /* Drain any pending packets in the free list */ -+ for (qos = 0; qos < queues_per_port; qos++) { -+ if (skb_queue_len(&priv->tx_free_list[qos])) { -+ spin_lock(&priv->tx_free_list[qos]. -+ lock); -+ while (skb_queue_len -+ (&priv->tx_free_list[qos]) > -+ cvmx_fau_fetch_and_add32(priv-> -+ fau + -+ qos * 4, -+ 0)) -+ dev_kfree_skb(__skb_dequeue -+ (&priv-> -+ tx_free_list -+ [qos])); -+ spin_unlock(&priv->tx_free_list[qos]. -+ lock); -+ } -+ } -+ cvm_oct_device[port]->get_stats(cvm_oct_device[port]); -+ } -+ port++; -+ /* Poll the next port in a 50th of a second. -+ This spreads the polling of ports out a little bit */ -+ mod_timer(&cvm_oct_poll_timer, jiffies + HZ / 50); -+ } else { -+ port = 0; -+ /* All ports have been polled. Start the next iteration through -+ the ports in one second */ -+ mod_timer(&cvm_oct_poll_timer, jiffies + HZ); -+ } -+} -+ -+/** -+ * Configure common hardware for all interfaces -+ */ -+static __init void cvm_oct_configure_common_hw(void) -+{ -+ int r; -+ /* Setup the FPA */ -+ cvmx_fpa_enable(); -+ cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, -+ num_packet_buffers); -+ cvm_oct_mem_fill_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, -+ num_packet_buffers); -+ if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) -+ cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, -+ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); -+ -+ if (USE_RED) -+ cvmx_helper_setup_red(num_packet_buffers / 4, -+ num_packet_buffers / 8); -+ -+ /* Enable the MII interface */ -+ if (!octeon_is_simulation()) -+ cvmx_write_csr(CVMX_SMIX_EN(0), 1); -+ -+ /* Register an IRQ hander for to receive POW interrupts */ -+ r = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, -+ cvm_oct_do_interrupt, IRQF_SHARED, "Ethernet", -+ cvm_oct_device); -+ -+#if defined(CONFIG_SMP) && 0 -+ if (USE_MULTICORE_RECEIVE) { -+ irq_set_affinity(OCTEON_IRQ_WORKQ0 + pow_receive_group, -+ cpu_online_mask); -+ } -+#endif -+} -+ -+/** -+ * Free a work queue entry received in a intercept callback. -+ * -+ * @work_queue_entry: -+ * Work queue entry to free -+ * Returns Zero on success, Negative on failure. -+ */ -+int cvm_oct_free_work(void *work_queue_entry) -+{ -+ cvmx_wqe_t *work = work_queue_entry; -+ -+ int segments = work->word2.s.bufs; -+ union cvmx_buf_ptr segment_ptr = work->packet_ptr; -+ -+ while (segments--) { -+ union cvmx_buf_ptr next_ptr = *(union cvmx_buf_ptr *) -+ cvmx_phys_to_ptr(segment_ptr.s.addr - 8); -+ if (unlikely(!segment_ptr.s.i)) -+ cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr), -+ segment_ptr.s.pool, -+ DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE / -+ 128)); -+ segment_ptr = next_ptr; -+ } -+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cvm_oct_free_work); -+ -+/** -+ * Module/ driver initialization. Creates the linux network -+ * devices. -+ * -+ * Returns Zero on success -+ */ -+static int __init cvm_oct_init_module(void) -+{ -+ int num_interfaces; -+ int interface; -+ int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; -+ int qos; -+ -+ pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); -+ -+ cvm_oct_proc_initialize(); -+ cvm_oct_rx_initialize(); -+ cvm_oct_configure_common_hw(); -+ -+ cvmx_helper_initialize_packet_io_global(); -+ -+ /* Change the input group for all ports before input is enabled */ -+ num_interfaces = cvmx_helper_get_number_of_interfaces(); -+ for (interface = 0; interface < num_interfaces; interface++) { -+ int num_ports = cvmx_helper_ports_on_interface(interface); -+ int port; -+ -+ for (port = cvmx_helper_get_ipd_port(interface, 0); -+ port < cvmx_helper_get_ipd_port(interface, num_ports); -+ port++) { -+ union cvmx_pip_prt_tagx pip_prt_tagx; -+ pip_prt_tagx.u64 = -+ cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); -+ pip_prt_tagx.s.grp = pow_receive_group; -+ cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), -+ pip_prt_tagx.u64); -+ } -+ } -+ -+ cvmx_helper_ipd_and_packet_input_enable(); -+ -+ memset(cvm_oct_device, 0, sizeof(cvm_oct_device)); -+ -+ /* -+ * Initialize the FAU used for counting packet buffers that -+ * need to be freed. -+ */ -+ cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); -+ -+ if ((pow_send_group != -1)) { -+ struct net_device *dev; -+ pr_info("\tConfiguring device for POW only access\n"); -+ dev = alloc_etherdev(sizeof(struct octeon_ethernet)); -+ if (dev) { -+ /* Initialize the device private structure. */ -+ struct octeon_ethernet *priv = netdev_priv(dev); -+ memset(priv, 0, sizeof(struct octeon_ethernet)); -+ -+ dev->init = cvm_oct_common_init; -+ priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; -+ priv->port = CVMX_PIP_NUM_INPUT_PORTS; -+ priv->queue = -1; -+ strcpy(dev->name, "pow%d"); -+ for (qos = 0; qos < 16; qos++) -+ skb_queue_head_init(&priv->tx_free_list[qos]); -+ -+ if (register_netdev(dev) < 0) { -+ pr_err("Failed to register ethernet " -+ "device for POW\n"); -+ kfree(dev); -+ } else { -+ cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev; -+ pr_info("%s: POW send group %d, receive " -+ "group %d\n", -+ dev->name, pow_send_group, -+ pow_receive_group); -+ } -+ } else { -+ pr_err("Failed to allocate ethernet device " -+ "for POW\n"); -+ } -+ } -+ -+ num_interfaces = cvmx_helper_get_number_of_interfaces(); -+ for (interface = 0; interface < num_interfaces; interface++) { -+ cvmx_helper_interface_mode_t imode = -+ cvmx_helper_interface_get_mode(interface); -+ int num_ports = cvmx_helper_ports_on_interface(interface); -+ int port; -+ -+ for (port = cvmx_helper_get_ipd_port(interface, 0); -+ port < cvmx_helper_get_ipd_port(interface, num_ports); -+ port++) { -+ struct octeon_ethernet *priv; -+ struct net_device *dev = -+ alloc_etherdev(sizeof(struct octeon_ethernet)); -+ if (!dev) { -+ pr_err("Failed to allocate ethernet device " -+ "for port %d\n", port); -+ continue; -+ } -+ if (disable_core_queueing) -+ dev->tx_queue_len = 0; -+ -+ /* Initialize the device private structure. */ -+ priv = netdev_priv(dev); -+ memset(priv, 0, sizeof(struct octeon_ethernet)); -+ -+ priv->imode = imode; -+ priv->port = port; -+ priv->queue = cvmx_pko_get_base_queue(priv->port); -+ priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; -+ for (qos = 0; qos < 16; qos++) -+ skb_queue_head_init(&priv->tx_free_list[qos]); -+ for (qos = 0; qos < cvmx_pko_get_num_queues(port); -+ qos++) -+ cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); -+ -+ switch (priv->imode) { -+ -+ /* These types don't support ports to IPD/PKO */ -+ case CVMX_HELPER_INTERFACE_MODE_DISABLED: -+ case CVMX_HELPER_INTERFACE_MODE_PCIE: -+ case CVMX_HELPER_INTERFACE_MODE_PICMG: -+ break; -+ -+ case CVMX_HELPER_INTERFACE_MODE_NPI: -+ dev->init = cvm_oct_common_init; -+ dev->uninit = cvm_oct_common_uninit; -+ strcpy(dev->name, "npi%d"); -+ break; -+ -+ case CVMX_HELPER_INTERFACE_MODE_XAUI: -+ dev->init = cvm_oct_xaui_init; -+ dev->uninit = cvm_oct_xaui_uninit; -+ strcpy(dev->name, "xaui%d"); -+ break; -+ -+ case CVMX_HELPER_INTERFACE_MODE_LOOP: -+ dev->init = cvm_oct_common_init; -+ dev->uninit = cvm_oct_common_uninit; -+ strcpy(dev->name, "loop%d"); -+ break; -+ -+ case CVMX_HELPER_INTERFACE_MODE_SGMII: -+ dev->init = cvm_oct_sgmii_init; -+ dev->uninit = cvm_oct_sgmii_uninit; -+ strcpy(dev->name, "eth%d"); -+ break; -+ -+ case CVMX_HELPER_INTERFACE_MODE_SPI: -+ dev->init = cvm_oct_spi_init; -+ dev->uninit = cvm_oct_spi_uninit; -+ strcpy(dev->name, "spi%d"); -+ break; -+ -+ case CVMX_HELPER_INTERFACE_MODE_RGMII: -+ case CVMX_HELPER_INTERFACE_MODE_GMII: -+ dev->init = cvm_oct_rgmii_init; -+ dev->uninit = cvm_oct_rgmii_uninit; -+ strcpy(dev->name, "eth%d"); -+ break; -+ } -+ -+ if (!dev->init) { -+ kfree(dev); -+ } else if (register_netdev(dev) < 0) { -+ pr_err("Failed to register ethernet device " -+ "for interface %d, port %d\n", -+ interface, priv->port); -+ kfree(dev); -+ } else { -+ cvm_oct_device[priv->port] = dev; -+ fau -= -+ cvmx_pko_get_num_queues(priv->port) * -+ sizeof(uint32_t); -+ } -+ } -+ } -+ -+ if (INTERRUPT_LIMIT) { -+ /* -+ * Set the POW timer rate to give an interrupt at most -+ * INTERRUPT_LIMIT times per second. -+ */ -+ cvmx_write_csr(CVMX_POW_WQ_INT_PC, -+ octeon_bootinfo->eclock_hz / (INTERRUPT_LIMIT * -+ 16 * 256) << 8); -+ -+ /* -+ * Enable POW timer interrupt. It will count when -+ * there are packets available. -+ */ -+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), -+ 0x1ful << 24); -+ } else { -+ /* Enable POW interrupt when our port has at least one packet */ -+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0x1001); -+ } -+ -+ /* Enable the poll timer for checking RGMII status */ -+ init_timer(&cvm_oct_poll_timer); -+ cvm_oct_poll_timer.data = 0; -+ cvm_oct_poll_timer.function = cvm_do_timer; -+ mod_timer(&cvm_oct_poll_timer, jiffies + HZ); -+ -+ return 0; -+} -+ -+/** -+ * Module / driver shutdown -+ * -+ * Returns Zero on success -+ */ -+static void __exit cvm_oct_cleanup_module(void) -+{ -+ int port; -+ -+ /* Disable POW interrupt */ -+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); -+ -+ cvmx_ipd_disable(); -+ -+ /* Free the interrupt handler */ -+ free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); -+ -+ del_timer(&cvm_oct_poll_timer); -+ cvm_oct_rx_shutdown(); -+ cvmx_pko_disable(); -+ -+ /* Free the ethernet devices */ -+ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { -+ if (cvm_oct_device[port]) { -+ cvm_oct_tx_shutdown(cvm_oct_device[port]); -+ unregister_netdev(cvm_oct_device[port]); -+ kfree(cvm_oct_device[port]); -+ cvm_oct_device[port] = NULL; -+ } -+ } -+ -+ cvmx_pko_shutdown(); -+ cvm_oct_proc_shutdown(); -+ -+ cvmx_ipd_free_ptr(); -+ -+ /* Free the HW pools */ -+ cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, -+ num_packet_buffers); -+ cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, -+ num_packet_buffers); -+ if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) -+ cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, -+ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); -+} -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Cavium Networks "); -+MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver."); -+module_init(cvm_oct_init_module); -+module_exit(cvm_oct_cleanup_module); ---- /dev/null -+++ b/drivers/staging/octeon/octeon-ethernet.h -@@ -0,0 +1,127 @@ -+/********************************************************************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2007 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+**********************************************************************/ -+ -+/* -+ * External interface for the Cavium Octeon ethernet driver. -+ */ -+#ifndef OCTEON_ETHERNET_H -+#define OCTEON_ETHERNET_H -+ -+/** -+ * This is the definition of the Ethernet driver's private -+ * driver state stored in netdev_priv(dev). -+ */ -+struct octeon_ethernet { -+ /* PKO hardware output port */ -+ int port; -+ /* PKO hardware queue for the port */ -+ int queue; -+ /* Hardware fetch and add to count outstanding tx buffers */ -+ int fau; -+ /* -+ * Type of port. This is one of the enums in -+ * cvmx_helper_interface_mode_t -+ */ -+ int imode; -+ /* List of outstanding tx buffers per queue */ -+ struct sk_buff_head tx_free_list[16]; -+ /* Device statistics */ -+ struct net_device_stats stats -+; /* Generic MII info structure */ -+ struct mii_if_info mii_info; -+ /* Last negotiated link state */ -+ uint64_t link_info; -+ /* Called periodically to check link status */ -+ void (*poll) (struct net_device *dev); -+}; -+ -+/** -+ * Free a work queue entry received in a intercept callback. -+ * -+ * @work_queue_entry: -+ * Work queue entry to free -+ * Returns Zero on success, Negative on failure. -+ */ -+int cvm_oct_free_work(void *work_queue_entry); -+ -+/** -+ * Transmit a work queue entry out of the ethernet port. Both -+ * the work queue entry and the packet data can optionally be -+ * freed. The work will be freed on error as well. -+ * -+ * @dev: Device to transmit out. -+ * @work_queue_entry: -+ * Work queue entry to send -+ * @do_free: True if the work queue entry and packet data should be -+ * freed. If false, neither will be freed. -+ * @qos: Index into the queues for this port to transmit on. This -+ * is used to implement QoS if their are multiple queues per -+ * port. This parameter must be between 0 and the number of -+ * queues per port minus 1. Values outside of this range will -+ * be change to zero. -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, -+ int do_free, int qos); -+ -+/** -+ * Transmit a work queue entry out of the ethernet port. Both -+ * the work queue entry and the packet data can optionally be -+ * freed. The work will be freed on error as well. This simply -+ * wraps cvmx_oct_transmit_qos() for backwards compatability. -+ * -+ * @dev: Device to transmit out. -+ * @work_queue_entry: -+ * Work queue entry to send -+ * @do_free: True if the work queue entry and packet data should be -+ * freed. If false, neither will be freed. -+ * -+ * Returns Zero on success, negative on failure. -+ */ -+static inline int cvm_oct_transmit(struct net_device *dev, -+ void *work_queue_entry, int do_free) -+{ -+ return cvm_oct_transmit_qos(dev, work_queue_entry, do_free, 0); -+} -+ -+extern int cvm_oct_rgmii_init(struct net_device *dev); -+extern void cvm_oct_rgmii_uninit(struct net_device *dev); -+extern int cvm_oct_sgmii_init(struct net_device *dev); -+extern void cvm_oct_sgmii_uninit(struct net_device *dev); -+extern int cvm_oct_spi_init(struct net_device *dev); -+extern void cvm_oct_spi_uninit(struct net_device *dev); -+extern int cvm_oct_xaui_init(struct net_device *dev); -+extern void cvm_oct_xaui_uninit(struct net_device *dev); -+ -+extern int always_use_pow; -+extern int pow_send_group; -+extern int pow_receive_group; -+extern char pow_send_list[]; -+extern struct net_device *cvm_oct_device[]; -+ -+#endif diff --git a/target/linux/octeon/patches/012-hook_up_eth_driver.patch b/target/linux/octeon/patches/012-hook_up_eth_driver.patch deleted file mode 100644 index 1a9dc00649..0000000000 --- a/target/linux/octeon/patches/012-hook_up_eth_driver.patch +++ /dev/null @@ -1,26 +0,0 @@ -The previous patch adds the driver files for octeon-ethernet. Here we -hook them up into the main kernel build system. - -Signed-off-by: David Daney ---- - drivers/staging/Kconfig | 2 ++ - drivers/staging/Makefile | 1 + - 2 files changed, 3 insertions(+), 0 deletions(-) - ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -115,5 +115,7 @@ source "drivers/staging/line6/Kconfig" - - source "drivers/staging/serqt_usb/Kconfig" - -+source "drivers/staging/octeon/Kconfig" -+ - endif # !STAGING_EXCLUDE_BUILD - endif # STAGING ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -40,3 +40,4 @@ obj-$(CONFIG_PLAN9AUTH) += p9auth/ - obj-$(CONFIG_HECI) += heci/ - obj-$(CONFIG_LINE6_USB) += line6/ - obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb/ -+obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ diff --git a/target/linux/octeon/patches/013-compile_fixes.patch b/target/linux/octeon/patches/013-compile_fixes.patch deleted file mode 100644 index 89338f4e8f..0000000000 --- a/target/linux/octeon/patches/013-compile_fixes.patch +++ /dev/null @@ -1,85 +0,0 @@ ---- a/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c -+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c -@@ -272,6 +272,7 @@ fix_ipd_exit: - * - * Returns Zero on success, negative on failure - */ -+#if 0 - int __cvmx_helper_errata_asx_pass1(int interface, int port, int cpu_clock_hz) - { - /* Set hi water mark as per errata GMX-4 */ -@@ -289,6 +290,7 @@ int __cvmx_helper_errata_asx_pass1(int i - cpu_clock_hz); - return 0; - } -+#endif - - /** - * This function needs to be called on all Octeon chips with ---- a/arch/mips/include/asm/octeon/cvmx-helper-errata.h -+++ b/arch/mips/include/asm/octeon/cvmx-helper-errata.h -@@ -60,8 +60,8 @@ extern int __cvmx_helper_errata_fix_ipd_ - * - * Returns Zero on success, negative on failure - */ --extern int __cvmx_helper_errata_asx_pass1(int interface, int port, -- int cpu_clock_hz); -+//extern int __cvmx_helper_errata_asx_pass1(int interface, int port, -+// int cpu_clock_hz); - - /** - * This function needs to be called on all Octeon chips with ---- a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c -+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c -@@ -356,6 +356,7 @@ int cvmx_helper_get_ipd_port(int interfa - * - * Returns Interface number - */ -+#if 0 - int cvmx_helper_get_interface_num(int ipd_port) - { - if (ipd_port < 16) -@@ -372,6 +373,7 @@ int cvmx_helper_get_interface_num(int ip - - return -1; - } -+#endif - - /** - * Returns the interface index number for an IPD/PKO port -@@ -381,6 +383,7 @@ int cvmx_helper_get_interface_num(int ip - * - * Returns Interface index number - */ -+#if 0 - int cvmx_helper_get_interface_index_num(int ipd_port) - { - if (ipd_port < 32) -@@ -395,6 +398,7 @@ int cvmx_helper_get_interface_index_num( - - return -1; - } -+#endif - - /** - * Initialize the internal QLM JTAG logic to allow programming ---- a/arch/mips/include/asm/octeon/cvmx-helper-util.h -+++ b/arch/mips/include/asm/octeon/cvmx-helper-util.h -@@ -205,7 +205,7 @@ static inline void cvmx_helper_free_pack - * - * Returns Interface number - */ --extern int cvmx_helper_get_interface_num(int ipd_port); -+//extern int cvmx_helper_get_interface_num(int ipd_port); - - /** - * Returns the interface index number for an IPD/PKO port -@@ -215,7 +215,7 @@ extern int cvmx_helper_get_interface_num - * - * Returns Interface index number - */ --extern int cvmx_helper_get_interface_index_num(int ipd_port); -+//extern int cvmx_helper_get_interface_index_num(int ipd_port); - - /** - * Initialize the internal QLM JTAG logic to allow programming diff --git a/target/linux/octeon/patches/015-no_werror.patch b/target/linux/octeon/patches/015-no_werror.patch deleted file mode 100644 index 71842dd1aa..0000000000 --- a/target/linux/octeon/patches/015-no_werror.patch +++ /dev/null @@ -1,8 +0,0 @@ ---- a/arch/mips/cavium-octeon/Makefile -+++ b/arch/mips/cavium-octeon/Makefile -@@ -18,5 +18,3 @@ obj-$(CONFIG_PCI) += - obj-$(CONFIG_PCI) += pci.o - obj-$(CONFIG_PCI) += pcie.o - obj-$(CONFIG_PCI_MSI) += msi.o -- --EXTRA_CFLAGS += -Werror diff --git a/target/linux/octeon/patches/016-octeon_hw_rng.patch b/target/linux/octeon/patches/016-octeon_hw_rng.patch deleted file mode 100644 index 65afe7705a..0000000000 --- a/target/linux/octeon/patches/016-octeon_hw_rng.patch +++ /dev/null @@ -1,351 +0,0 @@ -From: David Daney -Date: Thu, 20 Aug 2009 21:10:22 +0000 (-0700) -Subject: MIPS: Octeon: Add hardware RNG platform device. -X-Git-Tag: linux-2.6.32-rc1~34 -X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=c691b963;hp=a68577bc6ce2b5e422cdb7a993b1c07cc410e02a - -MIPS: Octeon: Add hardware RNG platform device. - -Add a platform device for the Octeon Random Number Generator (RNG). - -Signed-off-by: David Daney -Acked-by: Herbert Xu -Signed-off-by: Ralf Baechle ---- - -Index: linux-2.6.30.8/arch/mips/cavium-octeon/setup.c -=================================================================== ---- linux-2.6.30.8.orig/arch/mips/cavium-octeon/setup.c 2009-09-24 17:28:02.000000000 +0200 -+++ linux-2.6.30.8/arch/mips/cavium-octeon/setup.c 2009-10-08 13:10:09.000000000 +0200 -@@ -32,6 +32,7 @@ - #include - - #include -+#include - - #ifdef CONFIG_CAVIUM_DECODE_RSL - extern void cvmx_interrupt_rsl_decode(void); -@@ -925,3 +926,45 @@ - return ret; - } - device_initcall(octeon_cf_device_init); -+ -+/* Octeon Random Number Generator. */ -+static int __init octeon_rng_device_init(void) -+{ -+ struct platform_device *pd; -+ int ret = 0; -+ -+ struct resource rng_resources[] = { -+ { -+ .flags = IORESOURCE_MEM, -+ .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), -+ .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf -+ }, { -+ .flags = IORESOURCE_MEM, -+ .start = cvmx_build_io_address(8, 0), -+ .end = cvmx_build_io_address(8, 0) + 0x7 -+ } -+ }; -+ -+ pd = platform_device_alloc("octeon_rng", -1); -+ if (!pd) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = platform_device_add_resources(pd, rng_resources, -+ ARRAY_SIZE(rng_resources)); -+ if (ret) -+ goto fail; -+ -+ ret = platform_device_add(pd); -+ if (ret) -+ goto fail; -+ -+ return ret; -+fail: -+ platform_device_put(pd); -+ -+out: -+ return ret; -+} -+device_initcall(octeon_rng_device_init); -Index: linux-2.6.30.8/arch/mips/include/asm/octeon/cvmx-rnm-defs.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.8/arch/mips/include/asm/octeon/cvmx-rnm-defs.h 2009-10-08 13:10:09.000000000 +0200 -@@ -0,0 +1,88 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_RNM_DEFS_H__ -+#define __CVMX_RNM_DEFS_H__ -+ -+#include -+ -+#define CVMX_RNM_BIST_STATUS \ -+ CVMX_ADD_IO_SEG(0x0001180040000008ull) -+#define CVMX_RNM_CTL_STATUS \ -+ CVMX_ADD_IO_SEG(0x0001180040000000ull) -+ -+union cvmx_rnm_bist_status { -+ uint64_t u64; -+ struct cvmx_rnm_bist_status_s { -+ uint64_t reserved_2_63:62; -+ uint64_t rrc:1; -+ uint64_t mem:1; -+ } s; -+ struct cvmx_rnm_bist_status_s cn30xx; -+ struct cvmx_rnm_bist_status_s cn31xx; -+ struct cvmx_rnm_bist_status_s cn38xx; -+ struct cvmx_rnm_bist_status_s cn38xxp2; -+ struct cvmx_rnm_bist_status_s cn50xx; -+ struct cvmx_rnm_bist_status_s cn52xx; -+ struct cvmx_rnm_bist_status_s cn52xxp1; -+ struct cvmx_rnm_bist_status_s cn56xx; -+ struct cvmx_rnm_bist_status_s cn56xxp1; -+ struct cvmx_rnm_bist_status_s cn58xx; -+ struct cvmx_rnm_bist_status_s cn58xxp1; -+}; -+ -+union cvmx_rnm_ctl_status { -+ uint64_t u64; -+ struct cvmx_rnm_ctl_status_s { -+ uint64_t reserved_9_63:55; -+ uint64_t ent_sel:4; -+ uint64_t exp_ent:1; -+ uint64_t rng_rst:1; -+ uint64_t rnm_rst:1; -+ uint64_t rng_en:1; -+ uint64_t ent_en:1; -+ } s; -+ struct cvmx_rnm_ctl_status_cn30xx { -+ uint64_t reserved_4_63:60; -+ uint64_t rng_rst:1; -+ uint64_t rnm_rst:1; -+ uint64_t rng_en:1; -+ uint64_t ent_en:1; -+ } cn30xx; -+ struct cvmx_rnm_ctl_status_cn30xx cn31xx; -+ struct cvmx_rnm_ctl_status_cn30xx cn38xx; -+ struct cvmx_rnm_ctl_status_cn30xx cn38xxp2; -+ struct cvmx_rnm_ctl_status_s cn50xx; -+ struct cvmx_rnm_ctl_status_s cn52xx; -+ struct cvmx_rnm_ctl_status_s cn52xxp1; -+ struct cvmx_rnm_ctl_status_s cn56xx; -+ struct cvmx_rnm_ctl_status_s cn56xxp1; -+ struct cvmx_rnm_ctl_status_s cn58xx; -+ struct cvmx_rnm_ctl_status_s cn58xxp1; -+}; -+ -+#endif -Index: linux-2.6.30.8/drivers/char/hw_random/Kconfig -=================================================================== ---- linux-2.6.30.8.orig/drivers/char/hw_random/Kconfig 2009-09-24 17:28:02.000000000 +0200 -+++ linux-2.6.30.8/drivers/char/hw_random/Kconfig 2009-10-08 13:10:09.000000000 +0200 -@@ -126,6 +126,19 @@ - - If unsure, say Y. - -+config HW_RANDOM_OCTEON -+ tristate "Octeon Random Number Generator support" -+ depends on HW_RANDOM && CPU_CAVIUM_OCTEON -+ default HW_RANDOM -+ ---help--- -+ This driver provides kernel-side support for the Random Number -+ Generator hardware found on Octeon processors. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called octeon-rng. -+ -+ If unsure, say Y. -+ - config HW_RANDOM_PASEMI - tristate "PA Semi HW Random Number Generator support" - depends on HW_RANDOM && PPC_PASEMI -Index: linux-2.6.30.8/drivers/char/hw_random/Makefile -=================================================================== ---- linux-2.6.30.8.orig/drivers/char/hw_random/Makefile 2009-09-24 17:28:02.000000000 +0200 -+++ linux-2.6.30.8/drivers/char/hw_random/Makefile 2009-10-08 13:10:23.000000000 +0200 -@@ -15,3 +15,4 @@ - obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o - obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o - obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o -+obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o -Index: linux-2.6.30.8/drivers/char/hw_random/octeon-rng.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.8/drivers/char/hw_random/octeon-rng.c 2009-10-08 13:10:09.000000000 +0200 -@@ -0,0 +1,147 @@ -+/* -+ * Hardware Random Number Generator support for Cavium Networks -+ * Octeon processor family. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2009 Cavium Networks -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+struct octeon_rng { -+ struct hwrng ops; -+ void __iomem *control_status; -+ void __iomem *result; -+}; -+ -+static int octeon_rng_init(struct hwrng *rng) -+{ -+ union cvmx_rnm_ctl_status ctl; -+ struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); -+ -+ ctl.u64 = 0; -+ ctl.s.ent_en = 1; /* Enable the entropy source. */ -+ ctl.s.rng_en = 1; /* Enable the RNG hardware. */ -+ cvmx_write_csr((u64)p->control_status, ctl.u64); -+ return 0; -+} -+ -+static void octeon_rng_cleanup(struct hwrng *rng) -+{ -+ union cvmx_rnm_ctl_status ctl; -+ struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); -+ -+ ctl.u64 = 0; -+ /* Disable everything. */ -+ cvmx_write_csr((u64)p->control_status, ctl.u64); -+} -+ -+static int octeon_rng_data_read(struct hwrng *rng, u32 *data) -+{ -+ struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); -+ -+ *data = cvmx_read64_uint32((u64)p->result); -+ return sizeof(u32); -+} -+ -+static int __devinit octeon_rng_probe(struct platform_device *pdev) -+{ -+ struct resource *res_ports; -+ struct resource *res_result; -+ struct octeon_rng *rng; -+ int ret; -+ struct hwrng ops = { -+ .name = "octeon", -+ .init = octeon_rng_init, -+ .cleanup = octeon_rng_cleanup, -+ .data_read = octeon_rng_data_read -+ }; -+ -+ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); -+ if (!rng) -+ return -ENOMEM; -+ -+ res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res_ports) -+ goto err_ports; -+ -+ res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (!res_result) -+ goto err_ports; -+ -+ -+ rng->control_status = devm_ioremap_nocache(&pdev->dev, -+ res_ports->start, -+ sizeof(u64)); -+ if (!rng->control_status) -+ goto err_ports; -+ -+ rng->result = devm_ioremap_nocache(&pdev->dev, -+ res_result->start, -+ sizeof(u64)); -+ if (!rng->result) -+ goto err_r; -+ -+ rng->ops = ops; -+ -+ dev_set_drvdata(&pdev->dev, &rng->ops); -+ ret = hwrng_register(&rng->ops); -+ if (ret) -+ goto err; -+ -+ dev_info(&pdev->dev, "Octeon Random Number Generator\n"); -+ -+ return 0; -+err: -+ devm_iounmap(&pdev->dev, rng->control_status); -+err_r: -+ devm_iounmap(&pdev->dev, rng->result); -+err_ports: -+ devm_kfree(&pdev->dev, rng); -+ return -ENOENT; -+} -+ -+static int __exit octeon_rng_remove(struct platform_device *pdev) -+{ -+ struct hwrng *rng = dev_get_drvdata(&pdev->dev); -+ -+ hwrng_unregister(rng); -+ -+ return 0; -+} -+ -+static struct platform_driver octeon_rng_driver = { -+ .driver = { -+ .name = "octeon_rng", -+ .owner = THIS_MODULE, -+ }, -+ .probe = octeon_rng_probe, -+ .remove = __exit_p(octeon_rng_remove), -+}; -+ -+static int __init octeon_rng_mod_init(void) -+{ -+ return platform_driver_register(&octeon_rng_driver); -+} -+ -+static void __exit octeon_rng_mod_exit(void) -+{ -+ platform_driver_unregister(&octeon_rng_driver); -+} -+ -+module_init(octeon_rng_mod_init); -+module_exit(octeon_rng_mod_exit); -+ -+MODULE_AUTHOR("David Daney"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/octeon/patches/017-platform_devices.patch b/target/linux/octeon/patches/017-platform_devices.patch deleted file mode 100644 index 12c2ef181f..0000000000 --- a/target/linux/octeon/patches/017-platform_devices.patch +++ /dev/null @@ -1,371 +0,0 @@ -From: David Daney -Date: Wed, 16 Sep 2009 21:54:18 +0000 (-0700) -Subject: MIPS: Octeon: Move some platform device registration to its own file. -X-Git-Tag: linux-2.6.32-rc1~29 -X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=936c111e;hp=e1302af3482d3955f5a6100160e595e792d5f1e4 - -MIPS: Octeon: Move some platform device registration to its own file. - -There is a bunch of platform device registration in -arch/mips/cavium-octeon/setup.c. We move it to its own file in -preparation for adding more platform devices. - -Signed-off-by: David Daney -Signed-off-by: Ralf Baechle ---- - -diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile -index d6903c3..1394362 100644 ---- a/arch/mips/cavium-octeon/Makefile -+++ b/arch/mips/cavium-octeon/Makefile -@@ -6,10 +6,10 @@ - # License. See the file "COPYING" in the main directory of this archive - # for more details. - # --# Copyright (C) 2005-2008 Cavium Networks -+# Copyright (C) 2005-2009 Cavium Networks - # - --obj-y := setup.o serial.o octeon-irq.o csrc-octeon.o -+obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o - obj-y += dma-octeon.o flash_setup.o - obj-y += octeon-memcpy.o - -diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c -new file mode 100644 -index 0000000..be711dd ---- /dev/null -+++ b/arch/mips/cavium-octeon/octeon-platform.c -@@ -0,0 +1,164 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2004-2009 Cavium Networks -+ * Copyright (C) 2008 Wind River Systems -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static struct octeon_cf_data octeon_cf_data; -+ -+static int __init octeon_cf_device_init(void) -+{ -+ union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; -+ unsigned long base_ptr, region_base, region_size; -+ struct platform_device *pd; -+ struct resource cf_resources[3]; -+ unsigned int num_resources; -+ int i; -+ int ret = 0; -+ -+ /* Setup octeon-cf platform device if present. */ -+ base_ptr = 0; -+ if (octeon_bootinfo->major_version == 1 -+ && octeon_bootinfo->minor_version >= 1) { -+ if (octeon_bootinfo->compact_flash_common_base_addr) -+ base_ptr = -+ octeon_bootinfo->compact_flash_common_base_addr; -+ } else { -+ base_ptr = 0x1d000800; -+ } -+ -+ if (!base_ptr) -+ return ret; -+ -+ /* Find CS0 region. */ -+ for (i = 0; i < 8; i++) { -+ mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i)); -+ region_base = mio_boot_reg_cfg.s.base << 16; -+ region_size = (mio_boot_reg_cfg.s.size + 1) << 16; -+ if (mio_boot_reg_cfg.s.en && base_ptr >= region_base -+ && base_ptr < region_base + region_size) -+ break; -+ } -+ if (i >= 7) { -+ /* i and i + 1 are CS0 and CS1, both must be less than 8. */ -+ goto out; -+ } -+ octeon_cf_data.base_region = i; -+ octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width; -+ octeon_cf_data.base_region_bias = base_ptr - region_base; -+ memset(cf_resources, 0, sizeof(cf_resources)); -+ num_resources = 0; -+ cf_resources[num_resources].flags = IORESOURCE_MEM; -+ cf_resources[num_resources].start = region_base; -+ cf_resources[num_resources].end = region_base + region_size - 1; -+ num_resources++; -+ -+ -+ if (!(base_ptr & 0xfffful)) { -+ /* -+ * Boot loader signals availability of DMA (true_ide -+ * mode) by setting low order bits of base_ptr to -+ * zero. -+ */ -+ -+ /* Asume that CS1 immediately follows. */ -+ mio_boot_reg_cfg.u64 = -+ cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1)); -+ region_base = mio_boot_reg_cfg.s.base << 16; -+ region_size = (mio_boot_reg_cfg.s.size + 1) << 16; -+ if (!mio_boot_reg_cfg.s.en) -+ goto out; -+ -+ cf_resources[num_resources].flags = IORESOURCE_MEM; -+ cf_resources[num_resources].start = region_base; -+ cf_resources[num_resources].end = region_base + region_size - 1; -+ num_resources++; -+ -+ octeon_cf_data.dma_engine = 0; -+ cf_resources[num_resources].flags = IORESOURCE_IRQ; -+ cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA; -+ cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA; -+ num_resources++; -+ } else { -+ octeon_cf_data.dma_engine = -1; -+ } -+ -+ pd = platform_device_alloc("pata_octeon_cf", -1); -+ if (!pd) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ pd->dev.platform_data = &octeon_cf_data; -+ -+ ret = platform_device_add_resources(pd, cf_resources, num_resources); -+ if (ret) -+ goto fail; -+ -+ ret = platform_device_add(pd); -+ if (ret) -+ goto fail; -+ -+ return ret; -+fail: -+ platform_device_put(pd); -+out: -+ return ret; -+} -+device_initcall(octeon_cf_device_init); -+ -+/* Octeon Random Number Generator. */ -+static int __init octeon_rng_device_init(void) -+{ -+ struct platform_device *pd; -+ int ret = 0; -+ -+ struct resource rng_resources[] = { -+ { -+ .flags = IORESOURCE_MEM, -+ .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), -+ .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf -+ }, { -+ .flags = IORESOURCE_MEM, -+ .start = cvmx_build_io_address(8, 0), -+ .end = cvmx_build_io_address(8, 0) + 0x7 -+ } -+ }; -+ -+ pd = platform_device_alloc("octeon_rng", -1); -+ if (!pd) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = platform_device_add_resources(pd, rng_resources, -+ ARRAY_SIZE(rng_resources)); -+ if (ret) -+ goto fail; -+ -+ ret = platform_device_add(pd); -+ if (ret) -+ goto fail; -+ -+ return ret; -+fail: -+ platform_device_put(pd); -+ -+out: -+ return ret; -+} -+device_initcall(octeon_rng_device_init); -+ -+MODULE_AUTHOR("David Daney "); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Platform driver for Octeon SOC"); -diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c -index 468a120..b321d3b 100644 ---- a/arch/mips/cavium-octeon/setup.c -+++ b/arch/mips/cavium-octeon/setup.c -@@ -11,7 +11,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -33,7 +32,6 @@ - #include - - #include --#include - - #ifdef CONFIG_CAVIUM_DECODE_RSL - extern void cvmx_interrupt_rsl_decode(void); -@@ -825,147 +823,3 @@ void prom_free_prom_memory(void) - CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB option is set */ - octeon_hal_setup_reserved32(); - } -- --static struct octeon_cf_data octeon_cf_data; -- --static int __init octeon_cf_device_init(void) --{ -- union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; -- unsigned long base_ptr, region_base, region_size; -- struct platform_device *pd; -- struct resource cf_resources[3]; -- unsigned int num_resources; -- int i; -- int ret = 0; -- -- /* Setup octeon-cf platform device if present. */ -- base_ptr = 0; -- if (octeon_bootinfo->major_version == 1 -- && octeon_bootinfo->minor_version >= 1) { -- if (octeon_bootinfo->compact_flash_common_base_addr) -- base_ptr = -- octeon_bootinfo->compact_flash_common_base_addr; -- } else { -- base_ptr = 0x1d000800; -- } -- -- if (!base_ptr) -- return ret; -- -- /* Find CS0 region. */ -- for (i = 0; i < 8; i++) { -- mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i)); -- region_base = mio_boot_reg_cfg.s.base << 16; -- region_size = (mio_boot_reg_cfg.s.size + 1) << 16; -- if (mio_boot_reg_cfg.s.en && base_ptr >= region_base -- && base_ptr < region_base + region_size) -- break; -- } -- if (i >= 7) { -- /* i and i + 1 are CS0 and CS1, both must be less than 8. */ -- goto out; -- } -- octeon_cf_data.base_region = i; -- octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width; -- octeon_cf_data.base_region_bias = base_ptr - region_base; -- memset(cf_resources, 0, sizeof(cf_resources)); -- num_resources = 0; -- cf_resources[num_resources].flags = IORESOURCE_MEM; -- cf_resources[num_resources].start = region_base; -- cf_resources[num_resources].end = region_base + region_size - 1; -- num_resources++; -- -- -- if (!(base_ptr & 0xfffful)) { -- /* -- * Boot loader signals availability of DMA (true_ide -- * mode) by setting low order bits of base_ptr to -- * zero. -- */ -- -- /* Asume that CS1 immediately follows. */ -- mio_boot_reg_cfg.u64 = -- cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1)); -- region_base = mio_boot_reg_cfg.s.base << 16; -- region_size = (mio_boot_reg_cfg.s.size + 1) << 16; -- if (!mio_boot_reg_cfg.s.en) -- goto out; -- -- cf_resources[num_resources].flags = IORESOURCE_MEM; -- cf_resources[num_resources].start = region_base; -- cf_resources[num_resources].end = region_base + region_size - 1; -- num_resources++; -- -- octeon_cf_data.dma_engine = 0; -- cf_resources[num_resources].flags = IORESOURCE_IRQ; -- cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA; -- cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA; -- num_resources++; -- } else { -- octeon_cf_data.dma_engine = -1; -- } -- -- pd = platform_device_alloc("pata_octeon_cf", -1); -- if (!pd) { -- ret = -ENOMEM; -- goto out; -- } -- pd->dev.platform_data = &octeon_cf_data; -- -- ret = platform_device_add_resources(pd, cf_resources, num_resources); -- if (ret) -- goto fail; -- -- ret = platform_device_add(pd); -- if (ret) -- goto fail; -- -- return ret; --fail: -- platform_device_put(pd); --out: -- return ret; --} --device_initcall(octeon_cf_device_init); -- --/* Octeon Random Number Generator. */ --static int __init octeon_rng_device_init(void) --{ -- struct platform_device *pd; -- int ret = 0; -- -- struct resource rng_resources[] = { -- { -- .flags = IORESOURCE_MEM, -- .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), -- .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf -- }, { -- .flags = IORESOURCE_MEM, -- .start = cvmx_build_io_address(8, 0), -- .end = cvmx_build_io_address(8, 0) + 0x7 -- } -- }; -- -- pd = platform_device_alloc("octeon_rng", -1); -- if (!pd) { -- ret = -ENOMEM; -- goto out; -- } -- -- ret = platform_device_add_resources(pd, rng_resources, -- ARRAY_SIZE(rng_resources)); -- if (ret) -- goto fail; -- -- ret = platform_device_add(pd); -- if (ret) -- goto fail; -- -- return ret; --fail: -- platform_device_put(pd); -- --out: -- return ret; --} --device_initcall(octeon_rng_device_init); diff --git a/target/linux/octeon/patches/018-dwc_otg.patch b/target/linux/octeon/patches/018-dwc_otg.patch deleted file mode 100644 index 6f4a4d68ba..0000000000 --- a/target/linux/octeon/patches/018-dwc_otg.patch +++ /dev/null @@ -1,17496 +0,0 @@ -Signed-off-by: David Daney ---- - arch/mips/cavium-octeon/octeon-platform.c | 105 ++ - arch/mips/include/asm/octeon/cvmx-usbcx-defs.h | 1199 ++++++++++++++++++++++++ - arch/mips/include/asm/octeon/cvmx-usbnx-defs.h | 760 +++++++++++++++ - 3 files changed, 2064 insertions(+), 0 deletions(-) - create mode 100644 arch/mips/include/asm/octeon/cvmx-usbcx-defs.h - create mode 100644 arch/mips/include/asm/octeon/cvmx-usbnx-defs.h - -diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c -index cfdb4c2..20698a6 100644 ---- a/arch/mips/cavium-octeon/octeon-platform.c -+++ b/arch/mips/cavium-octeon/octeon-platform.c -@@ -7,13 +7,19 @@ - * Copyright (C) 2008 Wind River Systems - */ - -+#include - #include - #include -+#include - #include - #include - -+#include -+ - #include - #include -+#include -+#include - - static struct octeon_cf_data octeon_cf_data; - -@@ -247,6 +253,105 @@ out: - } - device_initcall(octeon_mgmt_device_init); - -+/* Octeon USB. */ -+static int __init octeon_usb_device_init(void) -+{ -+ int p_rtype_ref_clk = 2; -+ int number_usb_ports; -+ int usb_port; -+ int ret = 0; -+ -+ if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { -+ number_usb_ports = 0; -+ } else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { -+ number_usb_ports = 2; -+ /* CN52XX encodes this field differently */ -+ p_rtype_ref_clk = 1; -+ } else { -+ number_usb_ports = 1; -+ } -+ -+ for (usb_port = 0; usb_port < number_usb_ports; usb_port++) { -+ int divisor; -+ union cvmx_usbnx_clk_ctl usbn_clk_ctl; -+ struct platform_device *pdev; -+ struct resource usb_resource[2]; -+ -+ /* -+ * Divide the core clock down such that USB is as -+ * close as possible to 125Mhz. -+ */ -+ divisor = DIV_ROUND_UP(mips_hpt_frequency, 125000000); -+ /* Lower than 4 doesn't seem to work properly */ -+ if (divisor < 4) -+ divisor = 4; -+ -+ /* Fetch the value of the Register, and de-assert POR */ -+ usbn_clk_ctl.u64 = cvmx_read_csr(CVMX_USBNX_CLK_CTL(usb_port)); -+ usbn_clk_ctl.s.por = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ usbn_clk_ctl.cn31xx.p_rclk = 1; -+ usbn_clk_ctl.cn31xx.p_xenbn = 0; -+ } else { -+ if (cvmx_sysinfo_get()->board_type != -+ CVMX_BOARD_TYPE_BBGW_REF) -+ usbn_clk_ctl.cn56xx.p_rtype = p_rtype_ref_clk; -+ else -+ usbn_clk_ctl.cn56xx.p_rtype = 0; -+ } -+ usbn_clk_ctl.s.divide = divisor; -+ usbn_clk_ctl.s.divide2 = 0; -+ cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb_port), usbn_clk_ctl.u64); -+ -+ /* Wait for POR */ -+ udelay(850); -+ -+ usbn_clk_ctl.u64 = cvmx_read_csr(CVMX_USBNX_CLK_CTL(usb_port)); -+ usbn_clk_ctl.s.por = 0; -+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { -+ usbn_clk_ctl.cn31xx.p_rclk = 1; -+ usbn_clk_ctl.cn31xx.p_xenbn = 0; -+ } else { -+ if (cvmx_sysinfo_get()->board_type != -+ CVMX_BOARD_TYPE_BBGW_REF) -+ usbn_clk_ctl.cn56xx.p_rtype = p_rtype_ref_clk; -+ else -+ usbn_clk_ctl.cn56xx.p_rtype = 0; -+ } -+ usbn_clk_ctl.s.prst = 1; -+ cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb_port), usbn_clk_ctl.u64); -+ -+ udelay(1); -+ -+ usbn_clk_ctl.s.hrst = 1; -+ cvmx_write_csr(CVMX_USBNX_CLK_CTL(usb_port), usbn_clk_ctl.u64); -+ udelay(1); -+ -+ memset(usb_resource, 0, sizeof(usb_resource)); -+ usb_resource[0].start = -+ XKPHYS_TO_PHYS(CVMX_USBCX_GOTGCTL(usb_port)); -+ usb_resource[0].end = usb_resource[0].start + 0x10000; -+ usb_resource[0].flags = IORESOURCE_MEM; -+ -+ usb_resource[1].start = (usb_port == 0) ? -+ OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1; -+ usb_resource[1].end = usb_resource[1].start; -+ usb_resource[1].flags = IORESOURCE_IRQ; -+ -+ pdev = platform_device_register_simple("dwc_otg", -+ usb_port, -+ usb_resource, 2); -+ if (!pdev) { -+ pr_err("dwc_otg: Failed to allocate platform device " -+ "for USB%d\n", usb_port); -+ ret = -ENOMEM; -+ } -+ } -+ -+ return ret; -+} -+device_initcall(octeon_usb_device_init); -+ - MODULE_AUTHOR("David Daney "); - MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("Platform driver for Octeon SOC"); -diff --git a/arch/mips/include/asm/octeon/cvmx-usbcx-defs.h b/arch/mips/include/asm/octeon/cvmx-usbcx-defs.h -new file mode 100644 -index 0000000..c1e078e ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-usbcx-defs.h -@@ -0,0 +1,1199 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_USBCX_DEFS_H__ -+#define __CVMX_USBCX_DEFS_H__ -+ -+#define CVMX_USBCX_DAINT(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000818ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DAINTMSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001000081Cull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DCFG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000800ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DCTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000804ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DIEPCTLX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000900ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DIEPINTX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000908ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DIEPMSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000810ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DIEPTSIZX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000910ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DOEPCTLX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000B00ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DOEPINTX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000B08ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DOEPMSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000814ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DOEPTSIZX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000B10ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DPTXFSIZX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000100ull + (((offset) & 7) * 4) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DSTS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000808ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DTKNQR1(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000820ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DTKNQR2(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000824ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DTKNQR3(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000830ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_DTKNQR4(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000834ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GAHBCFG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000008ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GHWCFG1(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000044ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GHWCFG2(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000048ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GHWCFG3(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001000004Cull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GHWCFG4(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000050ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GINTMSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000018ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GINTSTS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000014ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GNPTXFSIZ(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000028ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GNPTXSTS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001000002Cull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GOTGCTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000000ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GOTGINT(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000004ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GRSTCTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000010ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GRXFSIZ(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000024ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GRXSTSPD(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010040020ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GRXSTSPH(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000020ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GRXSTSRD(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001004001Cull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GRXSTSRH(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001000001Cull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GSNPSID(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000040ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_GUSBCFG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001000000Cull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HAINT(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000414ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HAINTMSK(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000418ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HCCHARX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000500ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HCFG(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000400ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HCINTMSKX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F001000050Cull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HCINTX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000508ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HCSPLTX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000504ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HCTSIZX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000510ull + (((offset) & 7) * 32) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HFIR(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000404ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HFNUM(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000408ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HPRT(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000440ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HPTXFSIZ(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000100ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_HPTXSTS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000410ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_NPTXDFIFOX(offset, block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010001000ull + (((offset) & 7) * 4096) + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBCX_PCGCCTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0010000E00ull + (((block_id) & 1) * 0x100000000000ull)) -+ -+union cvmx_usbcx_daint { -+ uint32_t u32; -+ struct cvmx_usbcx_daint_s { -+ uint32_t outepint:16; -+ uint32_t inepint:16; -+ } s; -+ struct cvmx_usbcx_daint_s cn30xx; -+ struct cvmx_usbcx_daint_s cn31xx; -+ struct cvmx_usbcx_daint_s cn50xx; -+ struct cvmx_usbcx_daint_s cn52xx; -+ struct cvmx_usbcx_daint_s cn52xxp1; -+ struct cvmx_usbcx_daint_s cn56xx; -+ struct cvmx_usbcx_daint_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_daintmsk { -+ uint32_t u32; -+ struct cvmx_usbcx_daintmsk_s { -+ uint32_t outepmsk:16; -+ uint32_t inepmsk:16; -+ } s; -+ struct cvmx_usbcx_daintmsk_s cn30xx; -+ struct cvmx_usbcx_daintmsk_s cn31xx; -+ struct cvmx_usbcx_daintmsk_s cn50xx; -+ struct cvmx_usbcx_daintmsk_s cn52xx; -+ struct cvmx_usbcx_daintmsk_s cn52xxp1; -+ struct cvmx_usbcx_daintmsk_s cn56xx; -+ struct cvmx_usbcx_daintmsk_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dcfg { -+ uint32_t u32; -+ struct cvmx_usbcx_dcfg_s { -+ uint32_t reserved_23_31:9; -+ uint32_t epmiscnt:5; -+ uint32_t reserved_13_17:5; -+ uint32_t perfrint:2; -+ uint32_t devaddr:7; -+ uint32_t reserved_3_3:1; -+ uint32_t nzstsouthshk:1; -+ uint32_t devspd:2; -+ } s; -+ struct cvmx_usbcx_dcfg_s cn30xx; -+ struct cvmx_usbcx_dcfg_s cn31xx; -+ struct cvmx_usbcx_dcfg_s cn50xx; -+ struct cvmx_usbcx_dcfg_s cn52xx; -+ struct cvmx_usbcx_dcfg_s cn52xxp1; -+ struct cvmx_usbcx_dcfg_s cn56xx; -+ struct cvmx_usbcx_dcfg_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dctl { -+ uint32_t u32; -+ struct cvmx_usbcx_dctl_s { -+ uint32_t reserved_12_31:20; -+ uint32_t pwronprgdone:1; -+ uint32_t cgoutnak:1; -+ uint32_t sgoutnak:1; -+ uint32_t cgnpinnak:1; -+ uint32_t sgnpinnak:1; -+ uint32_t tstctl:3; -+ uint32_t goutnaksts:1; -+ uint32_t gnpinnaksts:1; -+ uint32_t sftdiscon:1; -+ uint32_t rmtwkupsig:1; -+ } s; -+ struct cvmx_usbcx_dctl_s cn30xx; -+ struct cvmx_usbcx_dctl_s cn31xx; -+ struct cvmx_usbcx_dctl_s cn50xx; -+ struct cvmx_usbcx_dctl_s cn52xx; -+ struct cvmx_usbcx_dctl_s cn52xxp1; -+ struct cvmx_usbcx_dctl_s cn56xx; -+ struct cvmx_usbcx_dctl_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_diepctlx { -+ uint32_t u32; -+ struct cvmx_usbcx_diepctlx_s { -+ uint32_t epena:1; -+ uint32_t epdis:1; -+ uint32_t setd1pid:1; -+ uint32_t setd0pid:1; -+ uint32_t snak:1; -+ uint32_t cnak:1; -+ uint32_t txfnum:4; -+ uint32_t stall:1; -+ uint32_t reserved_20_20:1; -+ uint32_t eptype:2; -+ uint32_t naksts:1; -+ uint32_t dpid:1; -+ uint32_t usbactep:1; -+ uint32_t nextep:4; -+ uint32_t mps:11; -+ } s; -+ struct cvmx_usbcx_diepctlx_s cn30xx; -+ struct cvmx_usbcx_diepctlx_s cn31xx; -+ struct cvmx_usbcx_diepctlx_s cn50xx; -+ struct cvmx_usbcx_diepctlx_s cn52xx; -+ struct cvmx_usbcx_diepctlx_s cn52xxp1; -+ struct cvmx_usbcx_diepctlx_s cn56xx; -+ struct cvmx_usbcx_diepctlx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_diepintx { -+ uint32_t u32; -+ struct cvmx_usbcx_diepintx_s { -+ uint32_t reserved_7_31:25; -+ uint32_t inepnakeff:1; -+ uint32_t intknepmis:1; -+ uint32_t intkntxfemp:1; -+ uint32_t timeout:1; -+ uint32_t ahberr:1; -+ uint32_t epdisbld:1; -+ uint32_t xfercompl:1; -+ } s; -+ struct cvmx_usbcx_diepintx_s cn30xx; -+ struct cvmx_usbcx_diepintx_s cn31xx; -+ struct cvmx_usbcx_diepintx_s cn50xx; -+ struct cvmx_usbcx_diepintx_s cn52xx; -+ struct cvmx_usbcx_diepintx_s cn52xxp1; -+ struct cvmx_usbcx_diepintx_s cn56xx; -+ struct cvmx_usbcx_diepintx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_diepmsk { -+ uint32_t u32; -+ struct cvmx_usbcx_diepmsk_s { -+ uint32_t reserved_7_31:25; -+ uint32_t inepnakeffmsk:1; -+ uint32_t intknepmismsk:1; -+ uint32_t intkntxfempmsk:1; -+ uint32_t timeoutmsk:1; -+ uint32_t ahberrmsk:1; -+ uint32_t epdisbldmsk:1; -+ uint32_t xfercomplmsk:1; -+ } s; -+ struct cvmx_usbcx_diepmsk_s cn30xx; -+ struct cvmx_usbcx_diepmsk_s cn31xx; -+ struct cvmx_usbcx_diepmsk_s cn50xx; -+ struct cvmx_usbcx_diepmsk_s cn52xx; -+ struct cvmx_usbcx_diepmsk_s cn52xxp1; -+ struct cvmx_usbcx_diepmsk_s cn56xx; -+ struct cvmx_usbcx_diepmsk_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dieptsizx { -+ uint32_t u32; -+ struct cvmx_usbcx_dieptsizx_s { -+ uint32_t reserved_31_31:1; -+ uint32_t mc:2; -+ uint32_t pktcnt:10; -+ uint32_t xfersize:19; -+ } s; -+ struct cvmx_usbcx_dieptsizx_s cn30xx; -+ struct cvmx_usbcx_dieptsizx_s cn31xx; -+ struct cvmx_usbcx_dieptsizx_s cn50xx; -+ struct cvmx_usbcx_dieptsizx_s cn52xx; -+ struct cvmx_usbcx_dieptsizx_s cn52xxp1; -+ struct cvmx_usbcx_dieptsizx_s cn56xx; -+ struct cvmx_usbcx_dieptsizx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_doepctlx { -+ uint32_t u32; -+ struct cvmx_usbcx_doepctlx_s { -+ uint32_t epena:1; -+ uint32_t epdis:1; -+ uint32_t setd1pid:1; -+ uint32_t setd0pid:1; -+ uint32_t snak:1; -+ uint32_t cnak:1; -+ uint32_t reserved_22_25:4; -+ uint32_t stall:1; -+ uint32_t snp:1; -+ uint32_t eptype:2; -+ uint32_t naksts:1; -+ uint32_t dpid:1; -+ uint32_t usbactep:1; -+ uint32_t reserved_11_14:4; -+ uint32_t mps:11; -+ } s; -+ struct cvmx_usbcx_doepctlx_s cn30xx; -+ struct cvmx_usbcx_doepctlx_s cn31xx; -+ struct cvmx_usbcx_doepctlx_s cn50xx; -+ struct cvmx_usbcx_doepctlx_s cn52xx; -+ struct cvmx_usbcx_doepctlx_s cn52xxp1; -+ struct cvmx_usbcx_doepctlx_s cn56xx; -+ struct cvmx_usbcx_doepctlx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_doepintx { -+ uint32_t u32; -+ struct cvmx_usbcx_doepintx_s { -+ uint32_t reserved_5_31:27; -+ uint32_t outtknepdis:1; -+ uint32_t setup:1; -+ uint32_t ahberr:1; -+ uint32_t epdisbld:1; -+ uint32_t xfercompl:1; -+ } s; -+ struct cvmx_usbcx_doepintx_s cn30xx; -+ struct cvmx_usbcx_doepintx_s cn31xx; -+ struct cvmx_usbcx_doepintx_s cn50xx; -+ struct cvmx_usbcx_doepintx_s cn52xx; -+ struct cvmx_usbcx_doepintx_s cn52xxp1; -+ struct cvmx_usbcx_doepintx_s cn56xx; -+ struct cvmx_usbcx_doepintx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_doepmsk { -+ uint32_t u32; -+ struct cvmx_usbcx_doepmsk_s { -+ uint32_t reserved_5_31:27; -+ uint32_t outtknepdismsk:1; -+ uint32_t setupmsk:1; -+ uint32_t ahberrmsk:1; -+ uint32_t epdisbldmsk:1; -+ uint32_t xfercomplmsk:1; -+ } s; -+ struct cvmx_usbcx_doepmsk_s cn30xx; -+ struct cvmx_usbcx_doepmsk_s cn31xx; -+ struct cvmx_usbcx_doepmsk_s cn50xx; -+ struct cvmx_usbcx_doepmsk_s cn52xx; -+ struct cvmx_usbcx_doepmsk_s cn52xxp1; -+ struct cvmx_usbcx_doepmsk_s cn56xx; -+ struct cvmx_usbcx_doepmsk_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_doeptsizx { -+ uint32_t u32; -+ struct cvmx_usbcx_doeptsizx_s { -+ uint32_t reserved_31_31:1; -+ uint32_t mc:2; -+ uint32_t pktcnt:10; -+ uint32_t xfersize:19; -+ } s; -+ struct cvmx_usbcx_doeptsizx_s cn30xx; -+ struct cvmx_usbcx_doeptsizx_s cn31xx; -+ struct cvmx_usbcx_doeptsizx_s cn50xx; -+ struct cvmx_usbcx_doeptsizx_s cn52xx; -+ struct cvmx_usbcx_doeptsizx_s cn52xxp1; -+ struct cvmx_usbcx_doeptsizx_s cn56xx; -+ struct cvmx_usbcx_doeptsizx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dptxfsizx { -+ uint32_t u32; -+ struct cvmx_usbcx_dptxfsizx_s { -+ uint32_t dptxfsize:16; -+ uint32_t dptxfstaddr:16; -+ } s; -+ struct cvmx_usbcx_dptxfsizx_s cn30xx; -+ struct cvmx_usbcx_dptxfsizx_s cn31xx; -+ struct cvmx_usbcx_dptxfsizx_s cn50xx; -+ struct cvmx_usbcx_dptxfsizx_s cn52xx; -+ struct cvmx_usbcx_dptxfsizx_s cn52xxp1; -+ struct cvmx_usbcx_dptxfsizx_s cn56xx; -+ struct cvmx_usbcx_dptxfsizx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dsts { -+ uint32_t u32; -+ struct cvmx_usbcx_dsts_s { -+ uint32_t reserved_22_31:10; -+ uint32_t soffn:14; -+ uint32_t reserved_4_7:4; -+ uint32_t errticerr:1; -+ uint32_t enumspd:2; -+ uint32_t suspsts:1; -+ } s; -+ struct cvmx_usbcx_dsts_s cn30xx; -+ struct cvmx_usbcx_dsts_s cn31xx; -+ struct cvmx_usbcx_dsts_s cn50xx; -+ struct cvmx_usbcx_dsts_s cn52xx; -+ struct cvmx_usbcx_dsts_s cn52xxp1; -+ struct cvmx_usbcx_dsts_s cn56xx; -+ struct cvmx_usbcx_dsts_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dtknqr1 { -+ uint32_t u32; -+ struct cvmx_usbcx_dtknqr1_s { -+ uint32_t eptkn:24; -+ uint32_t wrapbit:1; -+ uint32_t reserved_5_6:2; -+ uint32_t intknwptr:5; -+ } s; -+ struct cvmx_usbcx_dtknqr1_s cn30xx; -+ struct cvmx_usbcx_dtknqr1_s cn31xx; -+ struct cvmx_usbcx_dtknqr1_s cn50xx; -+ struct cvmx_usbcx_dtknqr1_s cn52xx; -+ struct cvmx_usbcx_dtknqr1_s cn52xxp1; -+ struct cvmx_usbcx_dtknqr1_s cn56xx; -+ struct cvmx_usbcx_dtknqr1_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dtknqr2 { -+ uint32_t u32; -+ struct cvmx_usbcx_dtknqr2_s { -+ uint32_t eptkn:32; -+ } s; -+ struct cvmx_usbcx_dtknqr2_s cn30xx; -+ struct cvmx_usbcx_dtknqr2_s cn31xx; -+ struct cvmx_usbcx_dtknqr2_s cn50xx; -+ struct cvmx_usbcx_dtknqr2_s cn52xx; -+ struct cvmx_usbcx_dtknqr2_s cn52xxp1; -+ struct cvmx_usbcx_dtknqr2_s cn56xx; -+ struct cvmx_usbcx_dtknqr2_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dtknqr3 { -+ uint32_t u32; -+ struct cvmx_usbcx_dtknqr3_s { -+ uint32_t eptkn:32; -+ } s; -+ struct cvmx_usbcx_dtknqr3_s cn30xx; -+ struct cvmx_usbcx_dtknqr3_s cn31xx; -+ struct cvmx_usbcx_dtknqr3_s cn50xx; -+ struct cvmx_usbcx_dtknqr3_s cn52xx; -+ struct cvmx_usbcx_dtknqr3_s cn52xxp1; -+ struct cvmx_usbcx_dtknqr3_s cn56xx; -+ struct cvmx_usbcx_dtknqr3_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_dtknqr4 { -+ uint32_t u32; -+ struct cvmx_usbcx_dtknqr4_s { -+ uint32_t eptkn:32; -+ } s; -+ struct cvmx_usbcx_dtknqr4_s cn30xx; -+ struct cvmx_usbcx_dtknqr4_s cn31xx; -+ struct cvmx_usbcx_dtknqr4_s cn50xx; -+ struct cvmx_usbcx_dtknqr4_s cn52xx; -+ struct cvmx_usbcx_dtknqr4_s cn52xxp1; -+ struct cvmx_usbcx_dtknqr4_s cn56xx; -+ struct cvmx_usbcx_dtknqr4_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gahbcfg { -+ uint32_t u32; -+ struct cvmx_usbcx_gahbcfg_s { -+ uint32_t reserved_9_31:23; -+ uint32_t ptxfemplvl:1; -+ uint32_t nptxfemplvl:1; -+ uint32_t reserved_6_6:1; -+ uint32_t dmaen:1; -+ uint32_t hbstlen:4; -+ uint32_t glblintrmsk:1; -+ } s; -+ struct cvmx_usbcx_gahbcfg_s cn30xx; -+ struct cvmx_usbcx_gahbcfg_s cn31xx; -+ struct cvmx_usbcx_gahbcfg_s cn50xx; -+ struct cvmx_usbcx_gahbcfg_s cn52xx; -+ struct cvmx_usbcx_gahbcfg_s cn52xxp1; -+ struct cvmx_usbcx_gahbcfg_s cn56xx; -+ struct cvmx_usbcx_gahbcfg_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_ghwcfg1 { -+ uint32_t u32; -+ struct cvmx_usbcx_ghwcfg1_s { -+ uint32_t epdir:32; -+ } s; -+ struct cvmx_usbcx_ghwcfg1_s cn30xx; -+ struct cvmx_usbcx_ghwcfg1_s cn31xx; -+ struct cvmx_usbcx_ghwcfg1_s cn50xx; -+ struct cvmx_usbcx_ghwcfg1_s cn52xx; -+ struct cvmx_usbcx_ghwcfg1_s cn52xxp1; -+ struct cvmx_usbcx_ghwcfg1_s cn56xx; -+ struct cvmx_usbcx_ghwcfg1_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_ghwcfg2 { -+ uint32_t u32; -+ struct cvmx_usbcx_ghwcfg2_s { -+ uint32_t reserved_31_31:1; -+ uint32_t tknqdepth:5; -+ uint32_t ptxqdepth:2; -+ uint32_t nptxqdepth:2; -+ uint32_t reserved_20_21:2; -+ uint32_t dynfifosizing:1; -+ uint32_t periosupport:1; -+ uint32_t numhstchnl:4; -+ uint32_t numdeveps:4; -+ uint32_t fsphytype:2; -+ uint32_t hsphytype:2; -+ uint32_t singpnt:1; -+ uint32_t otgarch:2; -+ uint32_t otgmode:3; -+ } s; -+ struct cvmx_usbcx_ghwcfg2_s cn30xx; -+ struct cvmx_usbcx_ghwcfg2_s cn31xx; -+ struct cvmx_usbcx_ghwcfg2_s cn50xx; -+ struct cvmx_usbcx_ghwcfg2_s cn52xx; -+ struct cvmx_usbcx_ghwcfg2_s cn52xxp1; -+ struct cvmx_usbcx_ghwcfg2_s cn56xx; -+ struct cvmx_usbcx_ghwcfg2_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_ghwcfg3 { -+ uint32_t u32; -+ struct cvmx_usbcx_ghwcfg3_s { -+ uint32_t dfifodepth:16; -+ uint32_t reserved_13_15:3; -+ uint32_t ahbphysync:1; -+ uint32_t rsttype:1; -+ uint32_t optfeature:1; -+ uint32_t vendor_control_interface_support:1; -+ uint32_t i2c_selection:1; -+ uint32_t otgen:1; -+ uint32_t pktsizewidth:3; -+ uint32_t xfersizewidth:4; -+ } s; -+ struct cvmx_usbcx_ghwcfg3_s cn30xx; -+ struct cvmx_usbcx_ghwcfg3_s cn31xx; -+ struct cvmx_usbcx_ghwcfg3_s cn50xx; -+ struct cvmx_usbcx_ghwcfg3_s cn52xx; -+ struct cvmx_usbcx_ghwcfg3_s cn52xxp1; -+ struct cvmx_usbcx_ghwcfg3_s cn56xx; -+ struct cvmx_usbcx_ghwcfg3_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_ghwcfg4 { -+ uint32_t u32; -+ struct cvmx_usbcx_ghwcfg4_s { -+ uint32_t reserved_30_31:2; -+ uint32_t numdevmodinend:4; -+ uint32_t endedtrfifo:1; -+ uint32_t sessendfltr:1; -+ uint32_t bvalidfltr:1; -+ uint32_t avalidfltr:1; -+ uint32_t vbusvalidfltr:1; -+ uint32_t iddgfltr:1; -+ uint32_t numctleps:4; -+ uint32_t phydatawidth:2; -+ uint32_t reserved_6_13:8; -+ uint32_t ahbfreq:1; -+ uint32_t enablepwropt:1; -+ uint32_t numdevperioeps:4; -+ } s; -+ struct cvmx_usbcx_ghwcfg4_cn30xx { -+ uint32_t reserved_25_31:7; -+ uint32_t sessendfltr:1; -+ uint32_t bvalidfltr:1; -+ uint32_t avalidfltr:1; -+ uint32_t vbusvalidfltr:1; -+ uint32_t iddgfltr:1; -+ uint32_t numctleps:4; -+ uint32_t phydatawidth:2; -+ uint32_t reserved_6_13:8; -+ uint32_t ahbfreq:1; -+ uint32_t enablepwropt:1; -+ uint32_t numdevperioeps:4; -+ } cn30xx; -+ struct cvmx_usbcx_ghwcfg4_cn30xx cn31xx; -+ struct cvmx_usbcx_ghwcfg4_s cn50xx; -+ struct cvmx_usbcx_ghwcfg4_s cn52xx; -+ struct cvmx_usbcx_ghwcfg4_s cn52xxp1; -+ struct cvmx_usbcx_ghwcfg4_s cn56xx; -+ struct cvmx_usbcx_ghwcfg4_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gintmsk { -+ uint32_t u32; -+ struct cvmx_usbcx_gintmsk_s { -+ uint32_t wkupintmsk:1; -+ uint32_t sessreqintmsk:1; -+ uint32_t disconnintmsk:1; -+ uint32_t conidstschngmsk:1; -+ uint32_t reserved_27_27:1; -+ uint32_t ptxfempmsk:1; -+ uint32_t hchintmsk:1; -+ uint32_t prtintmsk:1; -+ uint32_t reserved_23_23:1; -+ uint32_t fetsuspmsk:1; -+ uint32_t incomplpmsk:1; -+ uint32_t incompisoinmsk:1; -+ uint32_t oepintmsk:1; -+ uint32_t inepintmsk:1; -+ uint32_t epmismsk:1; -+ uint32_t reserved_16_16:1; -+ uint32_t eopfmsk:1; -+ uint32_t isooutdropmsk:1; -+ uint32_t enumdonemsk:1; -+ uint32_t usbrstmsk:1; -+ uint32_t usbsuspmsk:1; -+ uint32_t erlysuspmsk:1; -+ uint32_t i2cint:1; -+ uint32_t ulpickintmsk:1; -+ uint32_t goutnakeffmsk:1; -+ uint32_t ginnakeffmsk:1; -+ uint32_t nptxfempmsk:1; -+ uint32_t rxflvlmsk:1; -+ uint32_t sofmsk:1; -+ uint32_t otgintmsk:1; -+ uint32_t modemismsk:1; -+ uint32_t reserved_0_0:1; -+ } s; -+ struct cvmx_usbcx_gintmsk_s cn30xx; -+ struct cvmx_usbcx_gintmsk_s cn31xx; -+ struct cvmx_usbcx_gintmsk_s cn50xx; -+ struct cvmx_usbcx_gintmsk_s cn52xx; -+ struct cvmx_usbcx_gintmsk_s cn52xxp1; -+ struct cvmx_usbcx_gintmsk_s cn56xx; -+ struct cvmx_usbcx_gintmsk_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gintsts { -+ uint32_t u32; -+ struct cvmx_usbcx_gintsts_s { -+ uint32_t wkupint:1; -+ uint32_t sessreqint:1; -+ uint32_t disconnint:1; -+ uint32_t conidstschng:1; -+ uint32_t reserved_27_27:1; -+ uint32_t ptxfemp:1; -+ uint32_t hchint:1; -+ uint32_t prtint:1; -+ uint32_t reserved_23_23:1; -+ uint32_t fetsusp:1; -+ uint32_t incomplp:1; -+ uint32_t incompisoin:1; -+ uint32_t oepint:1; -+ uint32_t iepint:1; -+ uint32_t epmis:1; -+ uint32_t reserved_16_16:1; -+ uint32_t eopf:1; -+ uint32_t isooutdrop:1; -+ uint32_t enumdone:1; -+ uint32_t usbrst:1; -+ uint32_t usbsusp:1; -+ uint32_t erlysusp:1; -+ uint32_t i2cint:1; -+ uint32_t ulpickint:1; -+ uint32_t goutnakeff:1; -+ uint32_t ginnakeff:1; -+ uint32_t nptxfemp:1; -+ uint32_t rxflvl:1; -+ uint32_t sof:1; -+ uint32_t otgint:1; -+ uint32_t modemis:1; -+ uint32_t curmod:1; -+ } s; -+ struct cvmx_usbcx_gintsts_s cn30xx; -+ struct cvmx_usbcx_gintsts_s cn31xx; -+ struct cvmx_usbcx_gintsts_s cn50xx; -+ struct cvmx_usbcx_gintsts_s cn52xx; -+ struct cvmx_usbcx_gintsts_s cn52xxp1; -+ struct cvmx_usbcx_gintsts_s cn56xx; -+ struct cvmx_usbcx_gintsts_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gnptxfsiz { -+ uint32_t u32; -+ struct cvmx_usbcx_gnptxfsiz_s { -+ uint32_t nptxfdep:16; -+ uint32_t nptxfstaddr:16; -+ } s; -+ struct cvmx_usbcx_gnptxfsiz_s cn30xx; -+ struct cvmx_usbcx_gnptxfsiz_s cn31xx; -+ struct cvmx_usbcx_gnptxfsiz_s cn50xx; -+ struct cvmx_usbcx_gnptxfsiz_s cn52xx; -+ struct cvmx_usbcx_gnptxfsiz_s cn52xxp1; -+ struct cvmx_usbcx_gnptxfsiz_s cn56xx; -+ struct cvmx_usbcx_gnptxfsiz_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gnptxsts { -+ uint32_t u32; -+ struct cvmx_usbcx_gnptxsts_s { -+ uint32_t reserved_31_31:1; -+ uint32_t nptxqtop:7; -+ uint32_t nptxqspcavail:8; -+ uint32_t nptxfspcavail:16; -+ } s; -+ struct cvmx_usbcx_gnptxsts_s cn30xx; -+ struct cvmx_usbcx_gnptxsts_s cn31xx; -+ struct cvmx_usbcx_gnptxsts_s cn50xx; -+ struct cvmx_usbcx_gnptxsts_s cn52xx; -+ struct cvmx_usbcx_gnptxsts_s cn52xxp1; -+ struct cvmx_usbcx_gnptxsts_s cn56xx; -+ struct cvmx_usbcx_gnptxsts_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gotgctl { -+ uint32_t u32; -+ struct cvmx_usbcx_gotgctl_s { -+ uint32_t reserved_20_31:12; -+ uint32_t bsesvld:1; -+ uint32_t asesvld:1; -+ uint32_t dbnctime:1; -+ uint32_t conidsts:1; -+ uint32_t reserved_12_15:4; -+ uint32_t devhnpen:1; -+ uint32_t hstsethnpen:1; -+ uint32_t hnpreq:1; -+ uint32_t hstnegscs:1; -+ uint32_t reserved_2_7:6; -+ uint32_t sesreq:1; -+ uint32_t sesreqscs:1; -+ } s; -+ struct cvmx_usbcx_gotgctl_s cn30xx; -+ struct cvmx_usbcx_gotgctl_s cn31xx; -+ struct cvmx_usbcx_gotgctl_s cn50xx; -+ struct cvmx_usbcx_gotgctl_s cn52xx; -+ struct cvmx_usbcx_gotgctl_s cn52xxp1; -+ struct cvmx_usbcx_gotgctl_s cn56xx; -+ struct cvmx_usbcx_gotgctl_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gotgint { -+ uint32_t u32; -+ struct cvmx_usbcx_gotgint_s { -+ uint32_t reserved_20_31:12; -+ uint32_t dbncedone:1; -+ uint32_t adevtoutchg:1; -+ uint32_t hstnegdet:1; -+ uint32_t reserved_10_16:7; -+ uint32_t hstnegsucstschng:1; -+ uint32_t sesreqsucstschng:1; -+ uint32_t reserved_3_7:5; -+ uint32_t sesenddet:1; -+ uint32_t reserved_0_1:2; -+ } s; -+ struct cvmx_usbcx_gotgint_s cn30xx; -+ struct cvmx_usbcx_gotgint_s cn31xx; -+ struct cvmx_usbcx_gotgint_s cn50xx; -+ struct cvmx_usbcx_gotgint_s cn52xx; -+ struct cvmx_usbcx_gotgint_s cn52xxp1; -+ struct cvmx_usbcx_gotgint_s cn56xx; -+ struct cvmx_usbcx_gotgint_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_grstctl { -+ uint32_t u32; -+ struct cvmx_usbcx_grstctl_s { -+ uint32_t ahbidle:1; -+ uint32_t dmareq:1; -+ uint32_t reserved_11_29:19; -+ uint32_t txfnum:5; -+ uint32_t txfflsh:1; -+ uint32_t rxfflsh:1; -+ uint32_t intknqflsh:1; -+ uint32_t frmcntrrst:1; -+ uint32_t hsftrst:1; -+ uint32_t csftrst:1; -+ } s; -+ struct cvmx_usbcx_grstctl_s cn30xx; -+ struct cvmx_usbcx_grstctl_s cn31xx; -+ struct cvmx_usbcx_grstctl_s cn50xx; -+ struct cvmx_usbcx_grstctl_s cn52xx; -+ struct cvmx_usbcx_grstctl_s cn52xxp1; -+ struct cvmx_usbcx_grstctl_s cn56xx; -+ struct cvmx_usbcx_grstctl_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_grxfsiz { -+ uint32_t u32; -+ struct cvmx_usbcx_grxfsiz_s { -+ uint32_t reserved_16_31:16; -+ uint32_t rxfdep:16; -+ } s; -+ struct cvmx_usbcx_grxfsiz_s cn30xx; -+ struct cvmx_usbcx_grxfsiz_s cn31xx; -+ struct cvmx_usbcx_grxfsiz_s cn50xx; -+ struct cvmx_usbcx_grxfsiz_s cn52xx; -+ struct cvmx_usbcx_grxfsiz_s cn52xxp1; -+ struct cvmx_usbcx_grxfsiz_s cn56xx; -+ struct cvmx_usbcx_grxfsiz_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_grxstspd { -+ uint32_t u32; -+ struct cvmx_usbcx_grxstspd_s { -+ uint32_t reserved_25_31:7; -+ uint32_t fn:4; -+ uint32_t pktsts:4; -+ uint32_t dpid:2; -+ uint32_t bcnt:11; -+ uint32_t epnum:4; -+ } s; -+ struct cvmx_usbcx_grxstspd_s cn30xx; -+ struct cvmx_usbcx_grxstspd_s cn31xx; -+ struct cvmx_usbcx_grxstspd_s cn50xx; -+ struct cvmx_usbcx_grxstspd_s cn52xx; -+ struct cvmx_usbcx_grxstspd_s cn52xxp1; -+ struct cvmx_usbcx_grxstspd_s cn56xx; -+ struct cvmx_usbcx_grxstspd_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_grxstsph { -+ uint32_t u32; -+ struct cvmx_usbcx_grxstsph_s { -+ uint32_t reserved_21_31:11; -+ uint32_t pktsts:4; -+ uint32_t dpid:2; -+ uint32_t bcnt:11; -+ uint32_t chnum:4; -+ } s; -+ struct cvmx_usbcx_grxstsph_s cn30xx; -+ struct cvmx_usbcx_grxstsph_s cn31xx; -+ struct cvmx_usbcx_grxstsph_s cn50xx; -+ struct cvmx_usbcx_grxstsph_s cn52xx; -+ struct cvmx_usbcx_grxstsph_s cn52xxp1; -+ struct cvmx_usbcx_grxstsph_s cn56xx; -+ struct cvmx_usbcx_grxstsph_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_grxstsrd { -+ uint32_t u32; -+ struct cvmx_usbcx_grxstsrd_s { -+ uint32_t reserved_25_31:7; -+ uint32_t fn:4; -+ uint32_t pktsts:4; -+ uint32_t dpid:2; -+ uint32_t bcnt:11; -+ uint32_t epnum:4; -+ } s; -+ struct cvmx_usbcx_grxstsrd_s cn30xx; -+ struct cvmx_usbcx_grxstsrd_s cn31xx; -+ struct cvmx_usbcx_grxstsrd_s cn50xx; -+ struct cvmx_usbcx_grxstsrd_s cn52xx; -+ struct cvmx_usbcx_grxstsrd_s cn52xxp1; -+ struct cvmx_usbcx_grxstsrd_s cn56xx; -+ struct cvmx_usbcx_grxstsrd_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_grxstsrh { -+ uint32_t u32; -+ struct cvmx_usbcx_grxstsrh_s { -+ uint32_t reserved_21_31:11; -+ uint32_t pktsts:4; -+ uint32_t dpid:2; -+ uint32_t bcnt:11; -+ uint32_t chnum:4; -+ } s; -+ struct cvmx_usbcx_grxstsrh_s cn30xx; -+ struct cvmx_usbcx_grxstsrh_s cn31xx; -+ struct cvmx_usbcx_grxstsrh_s cn50xx; -+ struct cvmx_usbcx_grxstsrh_s cn52xx; -+ struct cvmx_usbcx_grxstsrh_s cn52xxp1; -+ struct cvmx_usbcx_grxstsrh_s cn56xx; -+ struct cvmx_usbcx_grxstsrh_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gsnpsid { -+ uint32_t u32; -+ struct cvmx_usbcx_gsnpsid_s { -+ uint32_t synopsysid:32; -+ } s; -+ struct cvmx_usbcx_gsnpsid_s cn30xx; -+ struct cvmx_usbcx_gsnpsid_s cn31xx; -+ struct cvmx_usbcx_gsnpsid_s cn50xx; -+ struct cvmx_usbcx_gsnpsid_s cn52xx; -+ struct cvmx_usbcx_gsnpsid_s cn52xxp1; -+ struct cvmx_usbcx_gsnpsid_s cn56xx; -+ struct cvmx_usbcx_gsnpsid_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_gusbcfg { -+ uint32_t u32; -+ struct cvmx_usbcx_gusbcfg_s { -+ uint32_t reserved_17_31:15; -+ uint32_t otgi2csel:1; -+ uint32_t phylpwrclksel:1; -+ uint32_t reserved_14_14:1; -+ uint32_t usbtrdtim:4; -+ uint32_t hnpcap:1; -+ uint32_t srpcap:1; -+ uint32_t ddrsel:1; -+ uint32_t physel:1; -+ uint32_t fsintf:1; -+ uint32_t ulpi_utmi_sel:1; -+ uint32_t phyif:1; -+ uint32_t toutcal:3; -+ } s; -+ struct cvmx_usbcx_gusbcfg_s cn30xx; -+ struct cvmx_usbcx_gusbcfg_s cn31xx; -+ struct cvmx_usbcx_gusbcfg_s cn50xx; -+ struct cvmx_usbcx_gusbcfg_s cn52xx; -+ struct cvmx_usbcx_gusbcfg_s cn52xxp1; -+ struct cvmx_usbcx_gusbcfg_s cn56xx; -+ struct cvmx_usbcx_gusbcfg_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_haint { -+ uint32_t u32; -+ struct cvmx_usbcx_haint_s { -+ uint32_t reserved_16_31:16; -+ uint32_t haint:16; -+ } s; -+ struct cvmx_usbcx_haint_s cn30xx; -+ struct cvmx_usbcx_haint_s cn31xx; -+ struct cvmx_usbcx_haint_s cn50xx; -+ struct cvmx_usbcx_haint_s cn52xx; -+ struct cvmx_usbcx_haint_s cn52xxp1; -+ struct cvmx_usbcx_haint_s cn56xx; -+ struct cvmx_usbcx_haint_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_haintmsk { -+ uint32_t u32; -+ struct cvmx_usbcx_haintmsk_s { -+ uint32_t reserved_16_31:16; -+ uint32_t haintmsk:16; -+ } s; -+ struct cvmx_usbcx_haintmsk_s cn30xx; -+ struct cvmx_usbcx_haintmsk_s cn31xx; -+ struct cvmx_usbcx_haintmsk_s cn50xx; -+ struct cvmx_usbcx_haintmsk_s cn52xx; -+ struct cvmx_usbcx_haintmsk_s cn52xxp1; -+ struct cvmx_usbcx_haintmsk_s cn56xx; -+ struct cvmx_usbcx_haintmsk_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hccharx { -+ uint32_t u32; -+ struct cvmx_usbcx_hccharx_s { -+ uint32_t chena:1; -+ uint32_t chdis:1; -+ uint32_t oddfrm:1; -+ uint32_t devaddr:7; -+ uint32_t ec:2; -+ uint32_t eptype:2; -+ uint32_t lspddev:1; -+ uint32_t reserved_16_16:1; -+ uint32_t epdir:1; -+ uint32_t epnum:4; -+ uint32_t mps:11; -+ } s; -+ struct cvmx_usbcx_hccharx_s cn30xx; -+ struct cvmx_usbcx_hccharx_s cn31xx; -+ struct cvmx_usbcx_hccharx_s cn50xx; -+ struct cvmx_usbcx_hccharx_s cn52xx; -+ struct cvmx_usbcx_hccharx_s cn52xxp1; -+ struct cvmx_usbcx_hccharx_s cn56xx; -+ struct cvmx_usbcx_hccharx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hcfg { -+ uint32_t u32; -+ struct cvmx_usbcx_hcfg_s { -+ uint32_t reserved_3_31:29; -+ uint32_t fslssupp:1; -+ uint32_t fslspclksel:2; -+ } s; -+ struct cvmx_usbcx_hcfg_s cn30xx; -+ struct cvmx_usbcx_hcfg_s cn31xx; -+ struct cvmx_usbcx_hcfg_s cn50xx; -+ struct cvmx_usbcx_hcfg_s cn52xx; -+ struct cvmx_usbcx_hcfg_s cn52xxp1; -+ struct cvmx_usbcx_hcfg_s cn56xx; -+ struct cvmx_usbcx_hcfg_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hcintx { -+ uint32_t u32; -+ struct cvmx_usbcx_hcintx_s { -+ uint32_t reserved_11_31:21; -+ uint32_t datatglerr:1; -+ uint32_t frmovrun:1; -+ uint32_t bblerr:1; -+ uint32_t xacterr:1; -+ uint32_t nyet:1; -+ uint32_t ack:1; -+ uint32_t nak:1; -+ uint32_t stall:1; -+ uint32_t ahberr:1; -+ uint32_t chhltd:1; -+ uint32_t xfercompl:1; -+ } s; -+ struct cvmx_usbcx_hcintx_s cn30xx; -+ struct cvmx_usbcx_hcintx_s cn31xx; -+ struct cvmx_usbcx_hcintx_s cn50xx; -+ struct cvmx_usbcx_hcintx_s cn52xx; -+ struct cvmx_usbcx_hcintx_s cn52xxp1; -+ struct cvmx_usbcx_hcintx_s cn56xx; -+ struct cvmx_usbcx_hcintx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hcintmskx { -+ uint32_t u32; -+ struct cvmx_usbcx_hcintmskx_s { -+ uint32_t reserved_11_31:21; -+ uint32_t datatglerrmsk:1; -+ uint32_t frmovrunmsk:1; -+ uint32_t bblerrmsk:1; -+ uint32_t xacterrmsk:1; -+ uint32_t nyetmsk:1; -+ uint32_t ackmsk:1; -+ uint32_t nakmsk:1; -+ uint32_t stallmsk:1; -+ uint32_t ahberrmsk:1; -+ uint32_t chhltdmsk:1; -+ uint32_t xfercomplmsk:1; -+ } s; -+ struct cvmx_usbcx_hcintmskx_s cn30xx; -+ struct cvmx_usbcx_hcintmskx_s cn31xx; -+ struct cvmx_usbcx_hcintmskx_s cn50xx; -+ struct cvmx_usbcx_hcintmskx_s cn52xx; -+ struct cvmx_usbcx_hcintmskx_s cn52xxp1; -+ struct cvmx_usbcx_hcintmskx_s cn56xx; -+ struct cvmx_usbcx_hcintmskx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hcspltx { -+ uint32_t u32; -+ struct cvmx_usbcx_hcspltx_s { -+ uint32_t spltena:1; -+ uint32_t reserved_17_30:14; -+ uint32_t compsplt:1; -+ uint32_t xactpos:2; -+ uint32_t hubaddr:7; -+ uint32_t prtaddr:7; -+ } s; -+ struct cvmx_usbcx_hcspltx_s cn30xx; -+ struct cvmx_usbcx_hcspltx_s cn31xx; -+ struct cvmx_usbcx_hcspltx_s cn50xx; -+ struct cvmx_usbcx_hcspltx_s cn52xx; -+ struct cvmx_usbcx_hcspltx_s cn52xxp1; -+ struct cvmx_usbcx_hcspltx_s cn56xx; -+ struct cvmx_usbcx_hcspltx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hctsizx { -+ uint32_t u32; -+ struct cvmx_usbcx_hctsizx_s { -+ uint32_t dopng:1; -+ uint32_t pid:2; -+ uint32_t pktcnt:10; -+ uint32_t xfersize:19; -+ } s; -+ struct cvmx_usbcx_hctsizx_s cn30xx; -+ struct cvmx_usbcx_hctsizx_s cn31xx; -+ struct cvmx_usbcx_hctsizx_s cn50xx; -+ struct cvmx_usbcx_hctsizx_s cn52xx; -+ struct cvmx_usbcx_hctsizx_s cn52xxp1; -+ struct cvmx_usbcx_hctsizx_s cn56xx; -+ struct cvmx_usbcx_hctsizx_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hfir { -+ uint32_t u32; -+ struct cvmx_usbcx_hfir_s { -+ uint32_t reserved_16_31:16; -+ uint32_t frint:16; -+ } s; -+ struct cvmx_usbcx_hfir_s cn30xx; -+ struct cvmx_usbcx_hfir_s cn31xx; -+ struct cvmx_usbcx_hfir_s cn50xx; -+ struct cvmx_usbcx_hfir_s cn52xx; -+ struct cvmx_usbcx_hfir_s cn52xxp1; -+ struct cvmx_usbcx_hfir_s cn56xx; -+ struct cvmx_usbcx_hfir_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hfnum { -+ uint32_t u32; -+ struct cvmx_usbcx_hfnum_s { -+ uint32_t frrem:16; -+ uint32_t frnum:16; -+ } s; -+ struct cvmx_usbcx_hfnum_s cn30xx; -+ struct cvmx_usbcx_hfnum_s cn31xx; -+ struct cvmx_usbcx_hfnum_s cn50xx; -+ struct cvmx_usbcx_hfnum_s cn52xx; -+ struct cvmx_usbcx_hfnum_s cn52xxp1; -+ struct cvmx_usbcx_hfnum_s cn56xx; -+ struct cvmx_usbcx_hfnum_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hprt { -+ uint32_t u32; -+ struct cvmx_usbcx_hprt_s { -+ uint32_t reserved_19_31:13; -+ uint32_t prtspd:2; -+ uint32_t prttstctl:4; -+ uint32_t prtpwr:1; -+ uint32_t prtlnsts:2; -+ uint32_t reserved_9_9:1; -+ uint32_t prtrst:1; -+ uint32_t prtsusp:1; -+ uint32_t prtres:1; -+ uint32_t prtovrcurrchng:1; -+ uint32_t prtovrcurract:1; -+ uint32_t prtenchng:1; -+ uint32_t prtena:1; -+ uint32_t prtconndet:1; -+ uint32_t prtconnsts:1; -+ } s; -+ struct cvmx_usbcx_hprt_s cn30xx; -+ struct cvmx_usbcx_hprt_s cn31xx; -+ struct cvmx_usbcx_hprt_s cn50xx; -+ struct cvmx_usbcx_hprt_s cn52xx; -+ struct cvmx_usbcx_hprt_s cn52xxp1; -+ struct cvmx_usbcx_hprt_s cn56xx; -+ struct cvmx_usbcx_hprt_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hptxfsiz { -+ uint32_t u32; -+ struct cvmx_usbcx_hptxfsiz_s { -+ uint32_t ptxfsize:16; -+ uint32_t ptxfstaddr:16; -+ } s; -+ struct cvmx_usbcx_hptxfsiz_s cn30xx; -+ struct cvmx_usbcx_hptxfsiz_s cn31xx; -+ struct cvmx_usbcx_hptxfsiz_s cn50xx; -+ struct cvmx_usbcx_hptxfsiz_s cn52xx; -+ struct cvmx_usbcx_hptxfsiz_s cn52xxp1; -+ struct cvmx_usbcx_hptxfsiz_s cn56xx; -+ struct cvmx_usbcx_hptxfsiz_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_hptxsts { -+ uint32_t u32; -+ struct cvmx_usbcx_hptxsts_s { -+ uint32_t ptxqtop:8; -+ uint32_t ptxqspcavail:8; -+ uint32_t ptxfspcavail:16; -+ } s; -+ struct cvmx_usbcx_hptxsts_s cn30xx; -+ struct cvmx_usbcx_hptxsts_s cn31xx; -+ struct cvmx_usbcx_hptxsts_s cn50xx; -+ struct cvmx_usbcx_hptxsts_s cn52xx; -+ struct cvmx_usbcx_hptxsts_s cn52xxp1; -+ struct cvmx_usbcx_hptxsts_s cn56xx; -+ struct cvmx_usbcx_hptxsts_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_nptxdfifox { -+ uint32_t u32; -+ struct cvmx_usbcx_nptxdfifox_s { -+ uint32_t data:32; -+ } s; -+ struct cvmx_usbcx_nptxdfifox_s cn30xx; -+ struct cvmx_usbcx_nptxdfifox_s cn31xx; -+ struct cvmx_usbcx_nptxdfifox_s cn50xx; -+ struct cvmx_usbcx_nptxdfifox_s cn52xx; -+ struct cvmx_usbcx_nptxdfifox_s cn52xxp1; -+ struct cvmx_usbcx_nptxdfifox_s cn56xx; -+ struct cvmx_usbcx_nptxdfifox_s cn56xxp1; -+}; -+ -+union cvmx_usbcx_pcgcctl { -+ uint32_t u32; -+ struct cvmx_usbcx_pcgcctl_s { -+ uint32_t reserved_5_31:27; -+ uint32_t physuspended:1; -+ uint32_t rstpdwnmodule:1; -+ uint32_t pwrclmp:1; -+ uint32_t gatehclk:1; -+ uint32_t stoppclk:1; -+ } s; -+ struct cvmx_usbcx_pcgcctl_s cn30xx; -+ struct cvmx_usbcx_pcgcctl_s cn31xx; -+ struct cvmx_usbcx_pcgcctl_s cn50xx; -+ struct cvmx_usbcx_pcgcctl_s cn52xx; -+ struct cvmx_usbcx_pcgcctl_s cn52xxp1; -+ struct cvmx_usbcx_pcgcctl_s cn56xx; -+ struct cvmx_usbcx_pcgcctl_s cn56xxp1; -+}; -+ -+#endif -diff --git a/arch/mips/include/asm/octeon/cvmx-usbnx-defs.h b/arch/mips/include/asm/octeon/cvmx-usbnx-defs.h -new file mode 100644 -index 0000000..90be974 ---- /dev/null -+++ b/arch/mips/include/asm/octeon/cvmx-usbnx-defs.h -@@ -0,0 +1,760 @@ -+/***********************license start*************** -+ * Author: Cavium Networks -+ * -+ * Contact: support@caviumnetworks.com -+ * This file is part of the OCTEON SDK -+ * -+ * Copyright (c) 2003-2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, but -+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * or visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ ***********************license end**************************************/ -+ -+#ifndef __CVMX_USBNX_DEFS_H__ -+#define __CVMX_USBNX_DEFS_H__ -+ -+#define CVMX_USBNX_BIST_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00011800680007F8ull + (((block_id) & 1) * 0x10000000ull)) -+#define CVMX_USBNX_CLK_CTL(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180068000010ull + (((block_id) & 1) * 0x10000000ull)) -+#define CVMX_USBNX_CTL_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000800ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN0(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000818ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN1(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000820ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN2(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000828ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN3(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000830ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN4(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000838ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN5(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000840ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN6(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000848ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_INB_CHN7(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000850ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN0(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000858ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN1(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000860ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN2(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000868ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN3(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000870ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN4(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000878ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN5(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000880ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN6(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000888ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA0_OUTB_CHN7(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000890ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_DMA_TEST(block_id) \ -+ CVMX_ADD_IO_SEG(0x00016F0000000808ull + (((block_id) & 1) * 0x100000000000ull)) -+#define CVMX_USBNX_INT_ENB(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180068000008ull + (((block_id) & 1) * 0x10000000ull)) -+#define CVMX_USBNX_INT_SUM(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180068000000ull + (((block_id) & 1) * 0x10000000ull)) -+#define CVMX_USBNX_USBP_CTL_STATUS(block_id) \ -+ CVMX_ADD_IO_SEG(0x0001180068000018ull + (((block_id) & 1) * 0x10000000ull)) -+ -+union cvmx_usbnx_bist_status { -+ uint64_t u64; -+ struct cvmx_usbnx_bist_status_s { -+ uint64_t reserved_7_63:57; -+ uint64_t u2nc_bis:1; -+ uint64_t u2nf_bis:1; -+ uint64_t e2hc_bis:1; -+ uint64_t n2uf_bis:1; -+ uint64_t usbc_bis:1; -+ uint64_t nif_bis:1; -+ uint64_t nof_bis:1; -+ } s; -+ struct cvmx_usbnx_bist_status_cn30xx { -+ uint64_t reserved_3_63:61; -+ uint64_t usbc_bis:1; -+ uint64_t nif_bis:1; -+ uint64_t nof_bis:1; -+ } cn30xx; -+ struct cvmx_usbnx_bist_status_cn30xx cn31xx; -+ struct cvmx_usbnx_bist_status_s cn50xx; -+ struct cvmx_usbnx_bist_status_s cn52xx; -+ struct cvmx_usbnx_bist_status_s cn52xxp1; -+ struct cvmx_usbnx_bist_status_s cn56xx; -+ struct cvmx_usbnx_bist_status_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_clk_ctl { -+ uint64_t u64; -+ struct cvmx_usbnx_clk_ctl_s { -+ uint64_t reserved_20_63:44; -+ uint64_t divide2:2; -+ uint64_t hclk_rst:1; -+ uint64_t p_x_on:1; -+ uint64_t reserved_14_15:2; -+ uint64_t p_com_on:1; -+ uint64_t p_c_sel:2; -+ uint64_t cdiv_byp:1; -+ uint64_t sd_mode:2; -+ uint64_t s_bist:1; -+ uint64_t por:1; -+ uint64_t enable:1; -+ uint64_t prst:1; -+ uint64_t hrst:1; -+ uint64_t divide:3; -+ } s; -+ struct cvmx_usbnx_clk_ctl_cn30xx { -+ uint64_t reserved_18_63:46; -+ uint64_t hclk_rst:1; -+ uint64_t p_x_on:1; -+ uint64_t p_rclk:1; -+ uint64_t p_xenbn:1; -+ uint64_t p_com_on:1; -+ uint64_t p_c_sel:2; -+ uint64_t cdiv_byp:1; -+ uint64_t sd_mode:2; -+ uint64_t s_bist:1; -+ uint64_t por:1; -+ uint64_t enable:1; -+ uint64_t prst:1; -+ uint64_t hrst:1; -+ uint64_t divide:3; -+ } cn30xx; -+ struct cvmx_usbnx_clk_ctl_cn30xx cn31xx; -+ struct cvmx_usbnx_clk_ctl_cn50xx { -+ uint64_t reserved_20_63:44; -+ uint64_t divide2:2; -+ uint64_t hclk_rst:1; -+ uint64_t reserved_16_16:1; -+ uint64_t p_rtype:2; -+ uint64_t p_com_on:1; -+ uint64_t p_c_sel:2; -+ uint64_t cdiv_byp:1; -+ uint64_t sd_mode:2; -+ uint64_t s_bist:1; -+ uint64_t por:1; -+ uint64_t enable:1; -+ uint64_t prst:1; -+ uint64_t hrst:1; -+ uint64_t divide:3; -+ } cn50xx; -+ struct cvmx_usbnx_clk_ctl_cn50xx cn52xx; -+ struct cvmx_usbnx_clk_ctl_cn50xx cn52xxp1; -+ struct cvmx_usbnx_clk_ctl_cn50xx cn56xx; -+ struct cvmx_usbnx_clk_ctl_cn50xx cn56xxp1; -+}; -+ -+union cvmx_usbnx_ctl_status { -+ uint64_t u64; -+ struct cvmx_usbnx_ctl_status_s { -+ uint64_t reserved_6_63:58; -+ uint64_t dma_0pag:1; -+ uint64_t dma_stt:1; -+ uint64_t dma_test:1; -+ uint64_t inv_a2:1; -+ uint64_t l2c_emod:2; -+ } s; -+ struct cvmx_usbnx_ctl_status_s cn30xx; -+ struct cvmx_usbnx_ctl_status_s cn31xx; -+ struct cvmx_usbnx_ctl_status_s cn50xx; -+ struct cvmx_usbnx_ctl_status_s cn52xx; -+ struct cvmx_usbnx_ctl_status_s cn52xxp1; -+ struct cvmx_usbnx_ctl_status_s cn56xx; -+ struct cvmx_usbnx_ctl_status_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn0 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn0_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn0_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn1 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn1_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn1_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn2 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn2_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn2_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn3 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn3_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn3_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn4 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn4_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn4_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn5 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn5_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn5_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn6 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn6_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn6_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_inb_chn7 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_inb_chn7_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn30xx; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn31xx; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn50xx; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn52xx; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn52xxp1; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn56xx; -+ struct cvmx_usbnx_dma0_inb_chn7_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn0 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn0_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn0_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn1 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn1_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn1_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn2 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn2_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn2_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn3 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn3_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn3_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn4 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn4_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn4_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn5 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn5_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn5_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn6 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn6_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn6_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma0_outb_chn7 { -+ uint64_t u64; -+ struct cvmx_usbnx_dma0_outb_chn7_s { -+ uint64_t reserved_36_63:28; -+ uint64_t addr:36; -+ } s; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn30xx; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn31xx; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn50xx; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn52xx; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn52xxp1; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn56xx; -+ struct cvmx_usbnx_dma0_outb_chn7_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_dma_test { -+ uint64_t u64; -+ struct cvmx_usbnx_dma_test_s { -+ uint64_t reserved_40_63:24; -+ uint64_t done:1; -+ uint64_t req:1; -+ uint64_t f_addr:18; -+ uint64_t count:11; -+ uint64_t channel:5; -+ uint64_t burst:4; -+ } s; -+ struct cvmx_usbnx_dma_test_s cn30xx; -+ struct cvmx_usbnx_dma_test_s cn31xx; -+ struct cvmx_usbnx_dma_test_s cn50xx; -+ struct cvmx_usbnx_dma_test_s cn52xx; -+ struct cvmx_usbnx_dma_test_s cn52xxp1; -+ struct cvmx_usbnx_dma_test_s cn56xx; -+ struct cvmx_usbnx_dma_test_s cn56xxp1; -+}; -+ -+union cvmx_usbnx_int_enb { -+ uint64_t u64; -+ struct cvmx_usbnx_int_enb_s { -+ uint64_t reserved_38_63:26; -+ uint64_t nd4o_dpf:1; -+ uint64_t nd4o_dpe:1; -+ uint64_t nd4o_rpf:1; -+ uint64_t nd4o_rpe:1; -+ uint64_t ltl_f_pf:1; -+ uint64_t ltl_f_pe:1; -+ uint64_t u2n_c_pe:1; -+ uint64_t u2n_c_pf:1; -+ uint64_t u2n_d_pf:1; -+ uint64_t u2n_d_pe:1; -+ uint64_t n2u_pe:1; -+ uint64_t n2u_pf:1; -+ uint64_t uod_pf:1; -+ uint64_t uod_pe:1; -+ uint64_t rq_q3_e:1; -+ uint64_t rq_q3_f:1; -+ uint64_t rq_q2_e:1; -+ uint64_t rq_q2_f:1; -+ uint64_t rg_fi_f:1; -+ uint64_t rg_fi_e:1; -+ uint64_t l2_fi_f:1; -+ uint64_t l2_fi_e:1; -+ uint64_t l2c_a_f:1; -+ uint64_t l2c_s_e:1; -+ uint64_t dcred_f:1; -+ uint64_t dcred_e:1; -+ uint64_t lt_pu_f:1; -+ uint64_t lt_po_e:1; -+ uint64_t nt_pu_f:1; -+ uint64_t nt_po_e:1; -+ uint64_t pt_pu_f:1; -+ uint64_t pt_po_e:1; -+ uint64_t lr_pu_f:1; -+ uint64_t lr_po_e:1; -+ uint64_t nr_pu_f:1; -+ uint64_t nr_po_e:1; -+ uint64_t pr_pu_f:1; -+ uint64_t pr_po_e:1; -+ } s; -+ struct cvmx_usbnx_int_enb_s cn30xx; -+ struct cvmx_usbnx_int_enb_s cn31xx; -+ struct cvmx_usbnx_int_enb_cn50xx { -+ uint64_t reserved_38_63:26; -+ uint64_t nd4o_dpf:1; -+ uint64_t nd4o_dpe:1; -+ uint64_t nd4o_rpf:1; -+ uint64_t nd4o_rpe:1; -+ uint64_t ltl_f_pf:1; -+ uint64_t ltl_f_pe:1; -+ uint64_t reserved_26_31:6; -+ uint64_t uod_pf:1; -+ uint64_t uod_pe:1; -+ uint64_t rq_q3_e:1; -+ uint64_t rq_q3_f:1; -+ uint64_t rq_q2_e:1; -+ uint64_t rq_q2_f:1; -+ uint64_t rg_fi_f:1; -+ uint64_t rg_fi_e:1; -+ uint64_t l2_fi_f:1; -+ uint64_t l2_fi_e:1; -+ uint64_t l2c_a_f:1; -+ uint64_t l2c_s_e:1; -+ uint64_t dcred_f:1; -+ uint64_t dcred_e:1; -+ uint64_t lt_pu_f:1; -+ uint64_t lt_po_e:1; -+ uint64_t nt_pu_f:1; -+ uint64_t nt_po_e:1; -+ uint64_t pt_pu_f:1; -+ uint64_t pt_po_e:1; -+ uint64_t lr_pu_f:1; -+ uint64_t lr_po_e:1; -+ uint64_t nr_pu_f:1; -+ uint64_t nr_po_e:1; -+ uint64_t pr_pu_f:1; -+ uint64_t pr_po_e:1; -+ } cn50xx; -+ struct cvmx_usbnx_int_enb_cn50xx cn52xx; -+ struct cvmx_usbnx_int_enb_cn50xx cn52xxp1; -+ struct cvmx_usbnx_int_enb_cn50xx cn56xx; -+ struct cvmx_usbnx_int_enb_cn50xx cn56xxp1; -+}; -+ -+union cvmx_usbnx_int_sum { -+ uint64_t u64; -+ struct cvmx_usbnx_int_sum_s { -+ uint64_t reserved_38_63:26; -+ uint64_t nd4o_dpf:1; -+ uint64_t nd4o_dpe:1; -+ uint64_t nd4o_rpf:1; -+ uint64_t nd4o_rpe:1; -+ uint64_t ltl_f_pf:1; -+ uint64_t ltl_f_pe:1; -+ uint64_t u2n_c_pe:1; -+ uint64_t u2n_c_pf:1; -+ uint64_t u2n_d_pf:1; -+ uint64_t u2n_d_pe:1; -+ uint64_t n2u_pe:1; -+ uint64_t n2u_pf:1; -+ uint64_t uod_pf:1; -+ uint64_t uod_pe:1; -+ uint64_t rq_q3_e:1; -+ uint64_t rq_q3_f:1; -+ uint64_t rq_q2_e:1; -+ uint64_t rq_q2_f:1; -+ uint64_t rg_fi_f:1; -+ uint64_t rg_fi_e:1; -+ uint64_t lt_fi_f:1; -+ uint64_t lt_fi_e:1; -+ uint64_t l2c_a_f:1; -+ uint64_t l2c_s_e:1; -+ uint64_t dcred_f:1; -+ uint64_t dcred_e:1; -+ uint64_t lt_pu_f:1; -+ uint64_t lt_po_e:1; -+ uint64_t nt_pu_f:1; -+ uint64_t nt_po_e:1; -+ uint64_t pt_pu_f:1; -+ uint64_t pt_po_e:1; -+ uint64_t lr_pu_f:1; -+ uint64_t lr_po_e:1; -+ uint64_t nr_pu_f:1; -+ uint64_t nr_po_e:1; -+ uint64_t pr_pu_f:1; -+ uint64_t pr_po_e:1; -+ } s; -+ struct cvmx_usbnx_int_sum_s cn30xx; -+ struct cvmx_usbnx_int_sum_s cn31xx; -+ struct cvmx_usbnx_int_sum_cn50xx { -+ uint64_t reserved_38_63:26; -+ uint64_t nd4o_dpf:1; -+ uint64_t nd4o_dpe:1; -+ uint64_t nd4o_rpf:1; -+ uint64_t nd4o_rpe:1; -+ uint64_t ltl_f_pf:1; -+ uint64_t ltl_f_pe:1; -+ uint64_t reserved_26_31:6; -+ uint64_t uod_pf:1; -+ uint64_t uod_pe:1; -+ uint64_t rq_q3_e:1; -+ uint64_t rq_q3_f:1; -+ uint64_t rq_q2_e:1; -+ uint64_t rq_q2_f:1; -+ uint64_t rg_fi_f:1; -+ uint64_t rg_fi_e:1; -+ uint64_t lt_fi_f:1; -+ uint64_t lt_fi_e:1; -+ uint64_t l2c_a_f:1; -+ uint64_t l2c_s_e:1; -+ uint64_t dcred_f:1; -+ uint64_t dcred_e:1; -+ uint64_t lt_pu_f:1; -+ uint64_t lt_po_e:1; -+ uint64_t nt_pu_f:1; -+ uint64_t nt_po_e:1; -+ uint64_t pt_pu_f:1; -+ uint64_t pt_po_e:1; -+ uint64_t lr_pu_f:1; -+ uint64_t lr_po_e:1; -+ uint64_t nr_pu_f:1; -+ uint64_t nr_po_e:1; -+ uint64_t pr_pu_f:1; -+ uint64_t pr_po_e:1; -+ } cn50xx; -+ struct cvmx_usbnx_int_sum_cn50xx cn52xx; -+ struct cvmx_usbnx_int_sum_cn50xx cn52xxp1; -+ struct cvmx_usbnx_int_sum_cn50xx cn56xx; -+ struct cvmx_usbnx_int_sum_cn50xx cn56xxp1; -+}; -+ -+union cvmx_usbnx_usbp_ctl_status { -+ uint64_t u64; -+ struct cvmx_usbnx_usbp_ctl_status_s { -+ uint64_t txrisetune:1; -+ uint64_t txvreftune:4; -+ uint64_t txfslstune:4; -+ uint64_t txhsxvtune:2; -+ uint64_t sqrxtune:3; -+ uint64_t compdistune:3; -+ uint64_t otgtune:3; -+ uint64_t otgdisable:1; -+ uint64_t portreset:1; -+ uint64_t drvvbus:1; -+ uint64_t lsbist:1; -+ uint64_t fsbist:1; -+ uint64_t hsbist:1; -+ uint64_t bist_done:1; -+ uint64_t bist_err:1; -+ uint64_t tdata_out:4; -+ uint64_t siddq:1; -+ uint64_t txpreemphasistune:1; -+ uint64_t dma_bmode:1; -+ uint64_t usbc_end:1; -+ uint64_t usbp_bist:1; -+ uint64_t tclk:1; -+ uint64_t dp_pulld:1; -+ uint64_t dm_pulld:1; -+ uint64_t hst_mode:1; -+ uint64_t tuning:4; -+ uint64_t tx_bs_enh:1; -+ uint64_t tx_bs_en:1; -+ uint64_t loop_enb:1; -+ uint64_t vtest_enb:1; -+ uint64_t bist_enb:1; -+ uint64_t tdata_sel:1; -+ uint64_t taddr_in:4; -+ uint64_t tdata_in:8; -+ uint64_t ate_reset:1; -+ } s; -+ struct cvmx_usbnx_usbp_ctl_status_cn30xx { -+ uint64_t reserved_38_63:26; -+ uint64_t bist_done:1; -+ uint64_t bist_err:1; -+ uint64_t tdata_out:4; -+ uint64_t reserved_30_31:2; -+ uint64_t dma_bmode:1; -+ uint64_t usbc_end:1; -+ uint64_t usbp_bist:1; -+ uint64_t tclk:1; -+ uint64_t dp_pulld:1; -+ uint64_t dm_pulld:1; -+ uint64_t hst_mode:1; -+ uint64_t tuning:4; -+ uint64_t tx_bs_enh:1; -+ uint64_t tx_bs_en:1; -+ uint64_t loop_enb:1; -+ uint64_t vtest_enb:1; -+ uint64_t bist_enb:1; -+ uint64_t tdata_sel:1; -+ uint64_t taddr_in:4; -+ uint64_t tdata_in:8; -+ uint64_t ate_reset:1; -+ } cn30xx; -+ struct cvmx_usbnx_usbp_ctl_status_cn30xx cn31xx; -+ struct cvmx_usbnx_usbp_ctl_status_cn50xx { -+ uint64_t txrisetune:1; -+ uint64_t txvreftune:4; -+ uint64_t txfslstune:4; -+ uint64_t txhsxvtune:2; -+ uint64_t sqrxtune:3; -+ uint64_t compdistune:3; -+ uint64_t otgtune:3; -+ uint64_t otgdisable:1; -+ uint64_t portreset:1; -+ uint64_t drvvbus:1; -+ uint64_t lsbist:1; -+ uint64_t fsbist:1; -+ uint64_t hsbist:1; -+ uint64_t bist_done:1; -+ uint64_t bist_err:1; -+ uint64_t tdata_out:4; -+ uint64_t reserved_31_31:1; -+ uint64_t txpreemphasistune:1; -+ uint64_t dma_bmode:1; -+ uint64_t usbc_end:1; -+ uint64_t usbp_bist:1; -+ uint64_t tclk:1; -+ uint64_t dp_pulld:1; -+ uint64_t dm_pulld:1; -+ uint64_t hst_mode:1; -+ uint64_t reserved_19_22:4; -+ uint64_t tx_bs_enh:1; -+ uint64_t tx_bs_en:1; -+ uint64_t loop_enb:1; -+ uint64_t vtest_enb:1; -+ uint64_t bist_enb:1; -+ uint64_t tdata_sel:1; -+ uint64_t taddr_in:4; -+ uint64_t tdata_in:8; -+ uint64_t ate_reset:1; -+ } cn50xx; -+ struct cvmx_usbnx_usbp_ctl_status_cn50xx cn52xx; -+ struct cvmx_usbnx_usbp_ctl_status_cn50xx cn52xxp1; -+ struct cvmx_usbnx_usbp_ctl_status_cn56xx { -+ uint64_t txrisetune:1; -+ uint64_t txvreftune:4; -+ uint64_t txfslstune:4; -+ uint64_t txhsxvtune:2; -+ uint64_t sqrxtune:3; -+ uint64_t compdistune:3; -+ uint64_t otgtune:3; -+ uint64_t otgdisable:1; -+ uint64_t portreset:1; -+ uint64_t drvvbus:1; -+ uint64_t lsbist:1; -+ uint64_t fsbist:1; -+ uint64_t hsbist:1; -+ uint64_t bist_done:1; -+ uint64_t bist_err:1; -+ uint64_t tdata_out:4; -+ uint64_t siddq:1; -+ uint64_t txpreemphasistune:1; -+ uint64_t dma_bmode:1; -+ uint64_t usbc_end:1; -+ uint64_t usbp_bist:1; -+ uint64_t tclk:1; -+ uint64_t dp_pulld:1; -+ uint64_t dm_pulld:1; -+ uint64_t hst_mode:1; -+ uint64_t reserved_19_22:4; -+ uint64_t tx_bs_enh:1; -+ uint64_t tx_bs_en:1; -+ uint64_t loop_enb:1; -+ uint64_t vtest_enb:1; -+ uint64_t bist_enb:1; -+ uint64_t tdata_sel:1; -+ uint64_t taddr_in:4; -+ uint64_t tdata_in:8; -+ uint64_t ate_reset:1; -+ } cn56xx; -+ struct cvmx_usbnx_usbp_ctl_status_cn50xx cn56xxp1; -+}; -+ -+#endif --- -1.6.0.6 - --- -To unsubscribe from this list: send the line "unsubscribe linux-usb" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.htmlSigned-off-by: David Daney ---- - drivers/usb/host/Kconfig | 8 + - drivers/usb/host/Makefile | 1 + - drivers/usb/host/dwc_otg/Kbuild | 16 + - drivers/usb/host/dwc_otg/dwc_otg_attr.c | 854 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_attr.h | 63 + - drivers/usb/host/dwc_otg/dwc_otg_cil.c | 2887 ++++++++++++++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_cil.h | 866 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 689 ++++++ - drivers/usb/host/dwc_otg/dwc_otg_driver.h | 63 + - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 2878 +++++++++++++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 661 ++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 1890 +++++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 695 +++++++ - drivers/usb/host/dwc_otg/dwc_otg_octeon.c | 1078 ++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_plat.h | 236 +++ - drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2355 +++++++++++++++++++++ - 16 files changed, 15240 insertions(+), 0 deletions(-) - create mode 100644 drivers/usb/host/dwc_otg/Kbuild - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_octeon.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_plat.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h - -diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 9b43b22..342dc54 100644 ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -381,3 +381,11 @@ config USB_HWA_HCD - - To compile this driver a module, choose M here: the module - will be called "hwa-hc". -+ -+config USB_DWC_OTG -+ tristate "Cavium Octeon USB" -+ depends on USB && CPU_CAVIUM_OCTEON -+ ---help--- -+ The Cavium Octeon on-chip USB controller. To compile this -+ driver as a module, choose M here: the module will be called -+ "dwc_otg". -diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index f58b249..76faf12 100644 ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -15,6 +15,7 @@ endif - xhci-objs := xhci-hcd.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o - - obj-$(CONFIG_USB_WHCI_HCD) += whci/ -+obj-$(CONFIG_USB_DWC_OTG) += dwc_otg/ - - obj-$(CONFIG_PCI) += pci-quirks.o - -diff --git a/drivers/usb/host/dwc_otg/Kbuild b/drivers/usb/host/dwc_otg/Kbuild -new file mode 100644 -index 0000000..cb32638 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/Kbuild -@@ -0,0 +1,16 @@ -+# -+# Makefile for DWC_otg Highspeed USB controller driver -+# -+ -+# Use one of the following flags to compile the software in host-only or -+# device-only mode. -+#EXTRA_CFLAGS += -DDWC_HOST_ONLY -+#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY -+ -+EXTRA_CFLAGS += -DDWC_HOST_ONLY -+obj-$(CONFIG_USB_DWC_OTG) += dwc_otg.o -+ -+dwc_otg-y := dwc_otg_octeon.o dwc_otg_attr.o -+dwc_otg-y += dwc_otg_cil.o dwc_otg_cil_intr.o -+dwc_otg-y += dwc_otg_hcd.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o -+ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -new file mode 100644 -index 0000000..d854a79 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -@@ -0,0 +1,854 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+/* -+ * -+ * The diagnostic interface will provide access to the controller for -+ * bringing up the hardware and testing. The Linux driver attributes -+ * feature will be used to provide the Linux Diagnostic -+ * Interface. These attributes are accessed through sysfs. -+ */ -+ -+/** @page "Linux Module Attributes" -+ * -+ * The Linux module attributes feature is used to provide the Linux -+ * Diagnostic Interface. These attributes are accessed through sysfs. -+ * The diagnostic interface will provide access to the controller for -+ * bringing up the hardware and testing. -+ -+ The following table shows the attributes. -+

Parameter NameMeaning
otg_capSpecifies the OTG capabilities. The driver will automatically detect the ++ value for this parameter if none is specified. ++ - 0: HNP and SRP capable (default, if available) ++ - 1: SRP Only capable ++ - 2: No HNP/SRP capable ++
dma_enableSpecifies whether to use slave or DMA mode for accessing the data FIFOs. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Slave ++ - 1: DMA (default, if available) ++
dma_burst_sizeThe DMA Burst size (applicable only for External DMA Mode). ++ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++
speedSpecifies the maximum speed of operation in host and device mode. The ++ actual speed depends on the speed of the attached device and the value of ++ phy_type. ++ - 0: High Speed (default) ++ - 1: Full Speed ++
host_support_fs_ls_low_powerSpecifies whether low power mode is supported when attached to a Full ++ Speed or Low Speed device in host mode. ++ - 0: Don't support low power mode (default) ++ - 1: Support low power mode ++
host_ls_low_power_phy_clkSpecifies the PHY clock rate in low power mode when connected to a Low ++ Speed device in host mode. This parameter is applicable only if ++ HOST_SUPPORT_FS_LS_LOW_POWER is enabled. ++ - 0: 48 MHz (default) ++ - 1: 6 MHz ++
enable_dynamic_fifo Specifies whether FIFOs may be resized by the driver software. ++ - 0: Use cC FIFO size parameters ++ - 1: Allow dynamic FIFO sizing (default) ++
data_fifo_sizeTotal number of 4-byte words in the data FIFO memory. This memory ++ includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs. ++ - Values: 32 to 32768 (default 8192) ++ ++ Note: The total FIFO memory depth in the FPGA configuration is 8192. ++
dev_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in device mode when dynamic ++ FIFO sizing is enabled. ++ - Values: 16 to 32768 (default 1064) ++
dev_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in device mode when ++ dynamic FIFO sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++
dev_perio_tx_fifo_size_n (n = 1 to 15)Number of 4-byte words in each of the periodic Tx FIFOs in device mode ++ when dynamic FIFO sizing is enabled. ++ - Values: 4 to 768 (default 256) ++
host_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in host mode when dynamic FIFO ++ sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++
host_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in host mode when ++ dynamic FIFO sizing is enabled in the core. ++ - Values: 16 to 32768 (default 1024) ++
host_perio_tx_fifo_sizeNumber of 4-byte words in the host periodic Tx FIFO when dynamic FIFO ++ sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++
max_transfer_sizeThe maximum transfer size supported in bytes. ++ - Values: 2047 to 65,535 (default 65,535) ++
max_packet_countThe maximum number of packets in a transfer. ++ - Values: 15 to 511 (default 511) ++
host_channelsThe number of host channel registers to use. ++ - Values: 1 to 16 (default 12) ++ ++ Note: The FPGA configuration supports a maximum of 12 host channels. ++
dev_endpointsThe number of endpoints in addition to EP0 available for device mode ++ operations. ++ - Values: 1 to 15 (default 6 IN and OUT) ++ ++ Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in ++ addition to EP0. ++
phy_typeSpecifies the type of PHY interface to use. By default, the driver will ++ automatically detect the phy_type. ++ - 0: Full Speed ++ - 1: UTMI+ (default, if available) ++ - 2: ULPI ++
phy_utmi_widthSpecifies the UTMI+ Data Width. This parameter is applicable for a ++ phy_type of UTMI+. Also, this parameter is applicable only if the ++ OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the ++ core has been configured to work at either data path width. ++ - Values: 8 or 16 bits (default 16) ++
phy_ulpi_ddrSpecifies whether the ULPI operates at double or single data rate. This ++ parameter is only applicable if phy_type is ULPI. ++ - 0: single data rate ULPI interface with 8 bit wide data bus (default) ++ - 1: double data rate ULPI interface with 4 bit wide data bus ++
i2c_enableSpecifies whether to use the I2C interface for full speed PHY. This ++ parameter is only applicable if PHY_TYPE is FS. ++ - 0: Disabled (default) ++ - 1: Enabled ++
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Name Description Access
mode Returns the current mode: 0 for device mode, 1 for host mode Read
hnpcapable Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. -+ Read returns the current value. Read/Write
srpcapable Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. -+ Read returns the current value. Read/Write
hnp Initiates the Host Negotiation Protocol. Read returns the status. Read/Write
srp Initiates the Session Request Protocol. Read returns the status. Read/Write
buspower Gets or sets the Power State of the bus (0 - Off or 1 - On) Read/Write
bussuspend Suspends the USB bus. Read/Write
busconnected Gets the connection status of the bus Read
gotgctl Gets or sets the Core Control Status Register. Read/Write
gusbcfg Gets or sets the Core USB Configuration Register Read/Write
grxfsiz Gets or sets the Receive FIFO Size Register Read/Write
gnptxfsiz Gets or sets the non-periodic Transmit Size Register Read/Write
gpvndctl Gets or sets the PHY Vendor Control Register Read/Write
ggpio Gets the value in the lower 16-bits of the General Purpose IO Register -+ or sets the upper 16 bits. Read/Write
guid Gets or sets the value of the User ID Register Read/Write
gsnpsid Gets the value of the Synopsys ID Regester Read
devspeed Gets or sets the device speed setting in the DCFG register Read/Write
enumspeed Gets the device enumeration Speed. Read
hptxfsiz Gets the value of the Host Periodic Transmit FIFO Read
hprt0 Gets or sets the value in the Host Port Control and Status Register Read/Write
regoffset Sets the register offset for the next Register Access Read/Write
regvalue Gets or sets the value of the register at the offset in the regoffset attribute. Read/Write
remote_wakeup On read, shows the status of Remote Wakeup. On write, initiates a remote -+ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote -+ Wakeup signalling bit in the Device Control Register is set for 1 -+ milli-second. Read/Write
regdump Dumps the contents of core registers. Read
hcddump Dumps the current HCD state. Read
hcd_frrem Shows the average value of the Frame Remaining -+ field in the Host Frame Number/Frame Remaining register when an SOF interrupt -+ occurs. This can be used to determine the average interrupt latency. Also -+ shows the average Frame Remaining value for start_transfer and the "a" and -+ "b" sample points. The "a" and "b" sample points may be used during debugging -+ bto determine how long it takes to execute a section of the HCD code. Read
rd_reg_test Displays the time required to read the GNPTXFSIZ register many times -+ (the output shows the number of times the register is read). -+ Read
wr_reg_test Displays the time required to write the GNPTXFSIZ register many times -+ (the output shows the number of times the register is written). -+ Read
-+ -+ Example usage: -+ To get the current mode: -+ cat /sys/devices/lm0/mode -+ -+ To power down the USB: -+ echo 0 > /sys/devices/lm0/buspower -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* permission constants */ -+ -+#include -+ -+#include "dwc_otg_plat.h" -+#include "dwc_otg_attr.h" -+#include "dwc_otg_driver.h" -+#ifndef DWC_HOST_ONLY -+#include "dwc_otg_pcd.h" -+#endif -+#include "dwc_otg_hcd.h" -+ -+/* -+ * MACROs for defining sysfs attribute -+ */ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, _addr_, \ -+ _mask_, _shift_, _string_) \ -+ static ssize_t _otg_attr_name_##_show (struct device *_dev, \ -+ struct device_attribute *attr, \ -+ char *buf) \ -+ { \ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; \ -+ uint32_t val; \ -+ val = dwc_read_reg32(_addr_); \ -+ val = (val & (_mask_)) >> _shift_; \ -+ return sprintf(buf, "%s = 0x%x\n", _string_, val); \ -+ } -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_, _addr_, \ -+ _mask_, _shift_, _string_) \ -+ static ssize_t _otg_attr_name_##_store (struct device *_dev, \ -+ struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+ { \ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; \ -+ uint32_t set = simple_strtoul(buf, NULL, 16); \ -+ uint32_t clear = set; \ -+ clear = ((~clear) << _shift_) & _mask_; \ -+ set = (set << _shift_) & _mask_; \ -+ dev_dbg(_dev, \ -+ "Storing Address=%p Set=0x%08x Clear=0x%08x\n", \ -+ _addr_, set, clear); \ -+ dwc_modify_reg32(_addr_, clear, set); \ -+ return count; \ -+ } -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_, _addr_, \ -+ _mask_, _shift_, _string_) \ -+ DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, _addr_, \ -+ _mask_, _shift_, _string_) \ -+ DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_, _addr_, \ -+ _mask_, _shift_, _string_) \ -+ DEVICE_ATTR(_otg_attr_name_, 0644, _otg_attr_name_##_show, \ -+ _otg_attr_name_##_store); -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_, _addr_, \ -+ _mask_, _shift_, _string_) \ -+ DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, \ -+ _addr_, _mask_, _shift_, _string_) \ -+ DEVICE_ATTR(_otg_attr_name_, 0444, _otg_attr_name_##_show, NULL); -+ -+/* -+ * MACROs for defining sysfs attribute for 32-bit registers -+ */ -+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \ -+ static ssize_t _otg_attr_name_##_show(struct device *_dev, \ -+ struct device_attribute *attr, \ -+ char *buf) \ -+ { \ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; \ -+ uint32_t val; \ -+ val = dwc_read_reg32(_addr_); \ -+ return sprintf(buf, "%s = 0x%08x\n", _string_, val); \ -+ } -+ -+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_, _addr_, _string_) \ -+ static ssize_t _otg_attr_name_##_store(struct device *_dev, \ -+ struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+ { \ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; \ -+ uint32_t val = simple_strtoul(buf, NULL, 16); \ -+ dev_dbg(_dev, "Storing Address=%p Val=0x%08x\n", _addr_, val); \ -+ dwc_write_reg32(_addr_, val); \ -+ return count; \ -+ } -+ -+#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_, _addr_, _string_) \ -+ DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \ -+ DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_, _addr_, _string_) \ -+ DEVICE_ATTR(_otg_attr_name_, 0644, _otg_attr_name_##_show, \ -+ _otg_attr_name_##_store); -+ -+#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_, _addr_, _string_) \ -+ DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \ -+ DEVICE_ATTR(_otg_attr_name_, 0444, _otg_attr_name_##_show, NULL); -+ -+/** -+ * Show the register offset of the Register Access. -+ */ -+static ssize_t regoffset_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", -+ otg_dev->reg_offset); -+} -+ -+/** -+ * Set the register offset for the next Register Access Read/Write -+ */ -+static ssize_t regoffset_store(struct device *_dev, -+ struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t offset = simple_strtoul(buf, NULL, 16); -+ -+ if (offset < SZ_256K) -+ otg_dev->reg_offset = offset; -+ else -+ dev_err(_dev, "invalid offset\n"); -+ -+ return count; -+} -+ -+DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); -+ -+/** -+ * Show the value of the register at the offset in the reg_offset -+ * attribute. -+ */ -+static ssize_t regvalue_show(struct device *_dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t val; -+ uint32_t *addr; -+ -+ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { -+ /* Calculate the address */ -+ addr = (uint32_t *) (otg_dev->reg_offset + -+ (uint8_t *) otg_dev->base); -+ -+ val = dwc_read_reg32(addr); -+ return snprintf(buf, -+ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, -+ "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset, -+ val); -+ } else { -+ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset); -+ return sprintf(buf, "invalid offset\n"); -+ } -+} -+ -+/** -+ * Store the value in the register at the offset in the reg_offset -+ * attribute. -+ * -+ */ -+static ssize_t regvalue_store(struct device *_dev, -+ struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t *addr; -+ uint32_t val = simple_strtoul(buf, NULL, 16); -+ -+ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { -+ /* Calculate the address */ -+ addr = (uint32_t *) (otg_dev->reg_offset + -+ (uint8_t *) otg_dev->base); -+ -+ dwc_write_reg32(addr, val); -+ } else { -+ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", -+ otg_dev->reg_offset); -+ } -+ return count; -+} -+ -+DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); -+ -+/* -+ * Attributes -+ */ -+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, -+ &(otg_dev->core_if->core_global_regs->gotgctl), -+ (1 << 20), 20, "Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, -+ &(otg_dev->core_if->core_global_regs->gusbcfg), -+ (1 << 9), 9, "Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, -+ &(otg_dev->core_if->core_global_regs->gusbcfg), -+ (1 << 8), 8, "Mode"); -+#if 0 -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower, &(otg_dev->core_if->core_global_regs->gotgctl), (1<<8), 8, "Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend, &(otg_dev->core_if->core_global_regs->gotgctl), (1<<8), 8, "Mode"); -+#endif -+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, otg_dev->core_if->host_if->hprt0, -+ 0x01, 0, "Bus Connected"); -+ -+DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, -+ &(otg_dev->core_if->core_global_regs->gotgctl), -+ "GOTGCTL"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, -+ &(otg_dev->core_if->core_global_regs->gusbcfg), -+ "GUSBCFG"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, -+ &(otg_dev->core_if->core_global_regs->grxfsiz), -+ "GRXFSIZ"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, -+ &(otg_dev->core_if->core_global_regs->gnptxfsiz), -+ "GNPTXFSIZ"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, -+ &(otg_dev->core_if->core_global_regs->gpvndctl), -+ "GPVNDCTL"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio, -+ &(otg_dev->core_if->core_global_regs->ggpio), -+ "GGPIO"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), -+ "GUID"); -+DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, -+ &(otg_dev->core_if->core_global_regs->gsnpsid), -+ "GSNPSID"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, -+ &(otg_dev->core_if->dev_if->dev_global_regs-> -+ dcfg), 0x3, 0, "Device Speed"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, -+ &(otg_dev->core_if->dev_if->dev_global_regs-> -+ dsts), 0x6, 1, "Device Enumeration Speed"); -+ -+DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, -+ &(otg_dev->core_if->core_global_regs->hptxfsiz), -+ "HPTXFSIZ"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); -+ -+/** -+ * @todo Add code to initiate the HNP. -+ */ -+/** -+ * Show the HNP status bit -+ */ -+static ssize_t hnp_show(struct device *_dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ union gotgctl_data val; -+ val.d32 = -+ dwc_read_reg32(&(otg_dev->core_if->core_global_regs->gotgctl)); -+ return sprintf(buf, "HstNegScs = 0x%x\n", val.b.hstnegscs); -+} -+ -+/** -+ * Set the HNP Request bit -+ */ -+static ssize_t hnp_store(struct device *_dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t in = simple_strtoul(buf, NULL, 16); -+ uint32_t *addr = -+ (uint32_t *) &(otg_dev->core_if->core_global_regs->gotgctl); -+ union gotgctl_data mem; -+ mem.d32 = dwc_read_reg32(addr); -+ mem.b.hnpreq = in; -+ dev_dbg(_dev, "Storing Address=%p Data=0x%08x\n", addr, mem.d32); -+ dwc_write_reg32(addr, mem.d32); -+ return count; -+} -+ -+DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); -+ -+/** -+ * @todo Add code to initiate the SRP. -+ */ -+/** -+ * Show the SRP status bit -+ */ -+static ssize_t srp_show(struct device *_dev, struct device_attribute *attr, -+ char *buf) -+{ -+#ifndef DWC_HOST_ONLY -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ union gotgctl_data val; -+ val.d32 = -+ dwc_read_reg32(&(otg_dev->core_if->core_global_regs->gotgctl)); -+ return sprintf(buf, "SesReqScs = 0x%x\n", val.b.sesreqscs); -+#else -+ return sprintf(buf, "Host Only Mode!\n"); -+#endif -+} -+ -+/** -+ * Set the SRP Request bit -+ */ -+static ssize_t srp_store(struct device *_dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifndef DWC_HOST_ONLY -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ dwc_otg_pcd_initiate_srp(otg_dev->pcd); -+#endif -+ return count; -+} -+ -+DEVICE_ATTR(srp, 0644, srp_show, srp_store); -+ -+/** -+ * @todo Need to do more for power on/off? -+ */ -+/** -+ * Show the Bus Power status -+ */ -+static ssize_t buspower_show(struct device *_dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ union hprt0_data val; -+ val.d32 = dwc_read_reg32(otg_dev->core_if->host_if->hprt0); -+ return sprintf(buf, "Bus Power = 0x%x\n", val.b.prtpwr); -+} -+ -+/** -+ * Set the Bus Power status -+ */ -+static ssize_t buspower_store(struct device *_dev, -+ struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t on = simple_strtoul(buf, NULL, 16); -+ uint32_t *addr = (uint32_t *) otg_dev->core_if->host_if->hprt0; -+ union hprt0_data mem; -+ -+ mem.d32 = dwc_read_reg32(addr); -+ mem.b.prtpwr = on; -+ -+ dwc_write_reg32(addr, mem.d32); -+ -+ return count; -+} -+ -+DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); -+ -+/** -+ * @todo Need to do more for suspend? -+ */ -+/** -+ * Show the Bus Suspend status -+ */ -+static ssize_t bussuspend_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ union hprt0_data val; -+ val.d32 = dwc_read_reg32(otg_dev->core_if->host_if->hprt0); -+ return sprintf(buf, "Bus Suspend = 0x%x\n", val.b.prtsusp); -+} -+ -+/** -+ * Set the Bus Suspend status -+ */ -+static ssize_t bussuspend_store(struct device *_dev, -+ struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t in = simple_strtoul(buf, NULL, 16); -+ uint32_t *addr = (uint32_t *) otg_dev->core_if->host_if->hprt0; -+ union hprt0_data mem; -+ mem.d32 = dwc_read_reg32(addr); -+ mem.b.prtsusp = in; -+ dev_dbg(_dev, "Storing Address=%p Data=0x%08x\n", addr, mem.d32); -+ dwc_write_reg32(addr, mem.d32); -+ return count; -+} -+ -+DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); -+ -+/** -+ * Show the status of Remote Wakeup. -+ */ -+static ssize_t remote_wakeup_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_HOST_ONLY -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ union dctl_data val; -+ val.d32 = -+ dwc_read_reg32(&otg_dev->core_if->dev_if->dev_global_regs->dctl); -+ return sprintf(buf, "Remote Wakeup = %d Enabled = %d\n", -+ val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable); -+#else -+ return sprintf(buf, "Host Only Mode!\n"); -+#endif -+} -+ -+/** -+ * Initiate a remote wakeup of the host. The Device control register -+ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable -+ * flag is set. -+ * -+ */ -+static ssize_t remote_wakeup_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifndef DWC_HOST_ONLY -+ uint32_t val = simple_strtoul(buf, NULL, 16); -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ if (val & 1) -+ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1); -+ else -+ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0); -+#endif -+ return count; -+} -+ -+DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, -+ remote_wakeup_store); -+ -+/** -+ * Dump global registers and either host or device registers (depending on the -+ * current mode of the core). -+ */ -+static ssize_t regdump_show(struct device *_dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ -+ dwc_otg_dump_global_registers(otg_dev->core_if); -+ if (dwc_otg_is_host_mode(otg_dev->core_if)) -+ dwc_otg_dump_host_registers(otg_dev->core_if); -+ else -+ dwc_otg_dump_dev_registers(otg_dev->core_if); -+ -+ return sprintf(buf, "Register Dump\n"); -+} -+ -+DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); -+ -+/** -+ * Dump the current hcd state. -+ */ -+static ssize_t hcddump_show(struct device *_dev, struct device_attribute *attr, -+ char *buf) -+{ -+#ifndef DWC_DEVICE_ONLY -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ dwc_otg_hcd_dump_state(otg_dev->hcd); -+#endif -+ return sprintf(buf, "HCD Dump\n"); -+} -+ -+DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); -+ -+/** -+ * Dump the average frame remaining at SOF. This can be used to -+ * determine average interrupt latency. Frame remaining is also shown for -+ * start transfer and two additional sample points. -+ */ -+static ssize_t hcd_frrem_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_DEVICE_ONLY -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ dwc_otg_hcd_dump_frrem(otg_dev->hcd); -+#endif -+ return sprintf(buf, "HCD Dump Frame Remaining\n"); -+} -+ -+DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); -+ -+/** -+ * Displays the time required to read the GNPTXFSIZ register many times (the -+ * output shows the number of times the register is read). -+ */ -+#define RW_REG_COUNT 10000000 -+#define MSEC_PER_JIFFIE (1000/HZ) -+static ssize_t rd_reg_test_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int i; -+ int time; -+ int start_jiffies; -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ -+ pr_info("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", -+ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); -+ start_jiffies = jiffies; -+ for (i = 0; i < RW_REG_COUNT; i++) -+ dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz); -+ -+ time = jiffies - start_jiffies; -+ return sprintf(buf, -+ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", -+ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); -+} -+ -+DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); -+ -+/** -+ * Displays the time required to write the GNPTXFSIZ register many times (the -+ * output shows the number of times the register is written). -+ */ -+static ssize_t wr_reg_test_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int i; -+ int time; -+ int start_jiffies; -+ struct dwc_otg_device *otg_dev = _dev->platform_data; -+ uint32_t reg_val; -+ -+ pr_info("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", -+ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); -+ reg_val = -+ dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz); -+ start_jiffies = jiffies; -+ for (i = 0; i < RW_REG_COUNT; i++) -+ dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz, -+ reg_val); -+ -+ time = jiffies - start_jiffies; -+ return sprintf(buf, -+ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", -+ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); -+} -+ -+DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); -+ -+/* -+ * Create the device files -+ */ -+void dwc_otg_attr_create(struct device *dev) -+{ -+ int error; -+ error = device_create_file(dev, &dev_attr_regoffset); -+ error |= device_create_file(dev, &dev_attr_regvalue); -+ error |= device_create_file(dev, &dev_attr_mode); -+ error |= device_create_file(dev, &dev_attr_hnpcapable); -+ error |= device_create_file(dev, &dev_attr_srpcapable); -+ error |= device_create_file(dev, &dev_attr_hnp); -+ error |= device_create_file(dev, &dev_attr_srp); -+ error |= device_create_file(dev, &dev_attr_buspower); -+ error |= device_create_file(dev, &dev_attr_bussuspend); -+ error |= device_create_file(dev, &dev_attr_busconnected); -+ error |= device_create_file(dev, &dev_attr_gotgctl); -+ error |= device_create_file(dev, &dev_attr_gusbcfg); -+ error |= device_create_file(dev, &dev_attr_grxfsiz); -+ error |= device_create_file(dev, &dev_attr_gnptxfsiz); -+ error |= device_create_file(dev, &dev_attr_gpvndctl); -+ error |= device_create_file(dev, &dev_attr_ggpio); -+ error |= device_create_file(dev, &dev_attr_guid); -+ error |= device_create_file(dev, &dev_attr_gsnpsid); -+ error |= device_create_file(dev, &dev_attr_devspeed); -+ error |= device_create_file(dev, &dev_attr_enumspeed); -+ error |= device_create_file(dev, &dev_attr_hptxfsiz); -+ error |= device_create_file(dev, &dev_attr_hprt0); -+ error |= device_create_file(dev, &dev_attr_remote_wakeup); -+ error |= device_create_file(dev, &dev_attr_regdump); -+ error |= device_create_file(dev, &dev_attr_hcddump); -+ error |= device_create_file(dev, &dev_attr_hcd_frrem); -+ error |= device_create_file(dev, &dev_attr_rd_reg_test); -+ error |= device_create_file(dev, &dev_attr_wr_reg_test); -+ if (error) -+ pr_err("DWC_OTG: Creating some device files failed\n"); -+} -+ -+/* -+ * Remove the device files -+ */ -+void dwc_otg_attr_remove(struct device *dev) -+{ -+ device_remove_file(dev, &dev_attr_regoffset); -+ device_remove_file(dev, &dev_attr_regvalue); -+ device_remove_file(dev, &dev_attr_mode); -+ device_remove_file(dev, &dev_attr_hnpcapable); -+ device_remove_file(dev, &dev_attr_srpcapable); -+ device_remove_file(dev, &dev_attr_hnp); -+ device_remove_file(dev, &dev_attr_srp); -+ device_remove_file(dev, &dev_attr_buspower); -+ device_remove_file(dev, &dev_attr_bussuspend); -+ device_remove_file(dev, &dev_attr_busconnected); -+ device_remove_file(dev, &dev_attr_gotgctl); -+ device_remove_file(dev, &dev_attr_gusbcfg); -+ device_remove_file(dev, &dev_attr_grxfsiz); -+ device_remove_file(dev, &dev_attr_gnptxfsiz); -+ device_remove_file(dev, &dev_attr_gpvndctl); -+ device_remove_file(dev, &dev_attr_ggpio); -+ device_remove_file(dev, &dev_attr_guid); -+ device_remove_file(dev, &dev_attr_gsnpsid); -+ device_remove_file(dev, &dev_attr_devspeed); -+ device_remove_file(dev, &dev_attr_enumspeed); -+ device_remove_file(dev, &dev_attr_hptxfsiz); -+ device_remove_file(dev, &dev_attr_hprt0); -+ device_remove_file(dev, &dev_attr_remote_wakeup); -+ device_remove_file(dev, &dev_attr_regdump); -+ device_remove_file(dev, &dev_attr_hcddump); -+ device_remove_file(dev, &dev_attr_hcd_frrem); -+ device_remove_file(dev, &dev_attr_rd_reg_test); -+ device_remove_file(dev, &dev_attr_wr_reg_test); -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -new file mode 100644 -index 0000000..925524f ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -@@ -0,0 +1,63 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_OTG_ATTR_H__) -+#define __DWC_OTG_ATTR_H__ -+ -+/* -+ * This file contains the interface to the Linux device attributes. -+ */ -+extern struct device_attribute dev_attr_regoffset; -+extern struct device_attribute dev_attr_regvalue; -+ -+extern struct device_attribute dev_attr_mode; -+extern struct device_attribute dev_attr_hnpcapable; -+extern struct device_attribute dev_attr_srpcapable; -+extern struct device_attribute dev_attr_hnp; -+extern struct device_attribute dev_attr_srp; -+extern struct device_attribute dev_attr_buspower; -+extern struct device_attribute dev_attr_bussuspend; -+extern struct device_attribute dev_attr_busconnected; -+extern struct device_attribute dev_attr_gotgctl; -+extern struct device_attribute dev_attr_gusbcfg; -+extern struct device_attribute dev_attr_grxfsiz; -+extern struct device_attribute dev_attr_gnptxfsiz; -+extern struct device_attribute dev_attr_gpvndctl; -+extern struct device_attribute dev_attr_ggpio; -+extern struct device_attribute dev_attr_guid; -+extern struct device_attribute dev_attr_gsnpsid; -+extern struct device_attribute dev_attr_devspeed; -+extern struct device_attribute dev_attr_enumspeed; -+extern struct device_attribute dev_attr_hptxfsiz; -+extern struct device_attribute dev_attr_hprt0; -+ -+void dwc_otg_attr_create(struct device *dev); -+void dwc_otg_attr_remove(struct device *dev); -+ -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -new file mode 100644 -index 0000000..86153ba ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -@@ -0,0 +1,2887 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+/* -+ * -+ * The Core Interface Layer provides basic services for accessing and -+ * managing the DWC_otg hardware. These services are used by both the -+ * Host Controller Driver and the Peripheral Controller Driver. -+ * -+ * The CIL manages the memory map for the core so that the HCD and PCD -+ * don't have to do this separately. It also handles basic tasks like -+ * reading/writing the registers and data FIFOs in the controller. -+ * Some of the data access functions provide encapsulation of several -+ * operations required to perform a task, such as writing multiple -+ * registers to start a transfer. Finally, the CIL performs basic -+ * services that are not specific to either the host or device modes -+ * of operation. These services include management of the OTG Host -+ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A -+ * Diagnostic API is also provided to allow testing of the controller -+ * hardware. -+ * -+ * The Core Interface Layer has the following requirements: -+ * - Provides basic controller operations. -+ * - Minimal use of OS services. -+ * - The OS services used will be abstracted by using inline functions -+ * or macros. -+ * -+ */ -+#include -+#ifdef DEBUG -+#include -+#endif -+ -+#include "dwc_otg_plat.h" -+#include "dwc_otg_regs.h" -+#include "dwc_otg_cil.h" -+ -+/** -+ * This function is called to initialize the DWC_otg CSR data -+ * structures. The register addresses in the device and host -+ * structures are initialized from the base address supplied by the -+ * caller. The calling function must make the OS calls to get the -+ * base address of the DWC_otg controller registers. The core_params -+ * argument holds the parameters that specify how the core should be -+ * configured. -+ * -+ * @reg_base_addr: Base address of DWC_otg core registers -+ * @core_params: Pointer to the core configuration parameters -+ * -+ */ -+struct dwc_otg_core_if *dwc_otg_cil_init(const uint32_t *reg_base_addr, -+ struct dwc_otg_core_params *core_params) -+{ -+ struct dwc_otg_core_if *core_if = 0; -+ struct dwc_otg_dev_if *dev_if = 0; -+ struct dwc_otg_host_if *host_if = 0; -+ uint8_t *reg_base = (uint8_t *) reg_base_addr; -+ int i = 0; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s(%p,%p)\n", __func__, reg_base_addr, -+ core_params); -+ -+ core_if = kmalloc(sizeof(struct dwc_otg_core_if), GFP_KERNEL); -+ if (core_if == 0) { -+ DWC_DEBUGPL(DBG_CIL, -+ "Allocation of struct dwc_otg_core_if failed\n"); -+ return 0; -+ } -+ memset(core_if, 0, sizeof(struct dwc_otg_core_if)); -+ -+ core_if->core_params = core_params; -+ core_if->core_global_regs = -+ (struct dwc_otg_core_global_regs *)reg_base; -+ /* -+ * Allocate the Device Mode structures. -+ */ -+ dev_if = kmalloc(sizeof(struct dwc_otg_dev_if), GFP_KERNEL); -+ if (dev_if == 0) { -+ DWC_DEBUGPL(DBG_CIL, "Allocation of struct dwc_otg_dev_if " -+ "failed\n"); -+ kfree(core_if); -+ return 0; -+ } -+ -+ dev_if->dev_global_regs = -+ (struct dwc_otg_dev_global_regs *) (reg_base + -+ DWC_DEV_GLOBAL_REG_OFFSET); -+ -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ dev_if->in_ep_regs[i] = (struct dwc_otg_dev_in_ep_regs *) -+ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + -+ (i * DWC_EP_REG_OFFSET)); -+ -+ dev_if->out_ep_regs[i] = (struct dwc_otg_dev_out_ep_regs *) -+ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + -+ (i * DWC_EP_REG_OFFSET)); -+ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", -+ i, &dev_if->in_ep_regs[i]->diepctl); -+ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", -+ i, &dev_if->out_ep_regs[i]->doepctl); -+ } -+ dev_if->speed = 0; /* unknown */ -+ dev_if->num_eps = MAX_EPS_CHANNELS; -+ dev_if->num_perio_eps = 0; -+ -+ core_if->dev_if = dev_if; -+ /* -+ * Allocate the Host Mode structures. -+ */ -+ host_if = kmalloc(sizeof(struct dwc_otg_host_if), GFP_KERNEL); -+ if (host_if == 0) { -+ DWC_DEBUGPL(DBG_CIL, -+ "Allocation of struct dwc_otg_host_if failed\n"); -+ kfree(dev_if); -+ kfree(core_if); -+ return 0; -+ } -+ -+ host_if->host_global_regs = (struct dwc_otg_host_global_regs *) -+ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET); -+ host_if->hprt0 = -+ (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET); -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ host_if->hc_regs[i] = (struct dwc_otg_hc_regs *) -+ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET + -+ (i * DWC_OTG_CHAN_REGS_OFFSET)); -+ DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", -+ i, &host_if->hc_regs[i]->hcchar); -+ } -+ host_if->num_host_channels = MAX_EPS_CHANNELS; -+ core_if->host_if = host_if; -+ -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ core_if->data_fifo[i] = -+ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET + -+ (i * DWC_OTG_DATA_FIFO_SIZE)); -+ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=%p\n", -+ i, core_if->data_fifo[i]); -+ } -+ -+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); -+ -+ /* -+ * Store the contents of the hardware configuration registers here for -+ * easy access later. -+ */ -+ core_if->hwcfg1.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg1); -+ core_if->hwcfg2.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg2); -+ core_if->hwcfg3.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg3); -+ core_if->hwcfg4.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg4); -+ -+ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); -+ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); -+ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); -+ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); -+ -+ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); -+ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); -+ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); -+ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", -+ core_if->hwcfg2.b.num_host_chan); -+ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", -+ core_if->hwcfg2.b.nonperio_tx_q_depth); -+ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", -+ core_if->hwcfg2.b.host_perio_tx_q_depth); -+ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", -+ core_if->hwcfg2.b.dev_token_q_depth); -+ -+ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", -+ core_if->hwcfg3.b.dfifo_depth); -+ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", -+ core_if->hwcfg3.b.xfer_size_cntr_width); -+ -+ /* -+ * Set the SRP sucess bit for FS-I2c -+ */ -+ core_if->srp_success = 0; -+ core_if->srp_timer_started = 0; -+ -+ return core_if; -+} -+ -+/** -+ * This function frees the structures allocated by dwc_otg_cil_init(). -+ * -+ * @core_if: The core interface pointer returned from -+ * dwc_otg_cil_init(). -+ * -+ */ -+void dwc_otg_cil_remove(struct dwc_otg_core_if *core_if) -+{ -+ /* Disable all interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 1, 0); -+ dwc_write_reg32(&core_if->core_global_regs->gintmsk, 0); -+ -+ kfree(core_if->dev_if); -+ kfree(core_if->host_if); -+ -+ kfree(core_if); -+} -+ -+/** -+ * This function enables the controller's Global Interrupt in the AHB Config -+ * register. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+extern void dwc_otg_enable_global_interrupts(struct dwc_otg_core_if *core_if) -+{ -+ union gahbcfg_data ahbcfg = {.d32 = 0 }; -+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); -+} -+ -+/** -+ * This function disables the controller's Global Interrupt in the AHB Config -+ * register. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+extern void dwc_otg_disable_global_interrupts(struct dwc_otg_core_if *core_if) -+{ -+ union gahbcfg_data ahbcfg = {.d32 = 0 }; -+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); -+} -+ -+/** -+ * This function initializes the commmon interrupts, used in both -+ * device and host modes. -+ * -+ * @core_if: Programming view of the DWC_otg controller -+ * -+ */ -+static void dwc_otg_enable_common_interrupts(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = -+ core_if->core_global_regs; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ /* Clear any pending OTG Interrupts */ -+ dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF); -+ /* Clear any pending interrupts */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ /* -+ * Enable the interrupts in the GINTMSK. -+ */ -+ intr_mask.b.modemismatch = 1; -+ intr_mask.b.otgintr = 1; -+ if (!core_if->dma_enable) -+ intr_mask.b.rxstsqlvl = 1; -+ -+ intr_mask.b.conidstschng = 1; -+ intr_mask.b.wkupintr = 1; -+ intr_mask.b.disconnect = 1; -+ intr_mask.b.usbsuspend = 1; -+ intr_mask.b.sessreqintr = 1; -+ dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32); -+} -+ -+/** -+ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY -+ * type. -+ */ -+static void init_fslspclksel(struct dwc_otg_core_if *core_if) -+{ -+ uint32_t val; -+ union hcfg_data hcfg; -+ -+ if (((core_if->hwcfg2.b.hs_phy_type == 2) && -+ (core_if->hwcfg2.b.fs_phy_type == 1) && -+ (core_if->core_params->ulpi_fs_ls)) || -+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { -+ /* Full speed PHY */ -+ val = DWC_HCFG_48_MHZ; -+ } else { -+ /* High speed PHY running at full speed or high speed */ -+ val = DWC_HCFG_30_60_MHZ; -+ } -+ -+ DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); -+ hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); -+ hcfg.b.fslspclksel = val; -+ dwc_write_reg32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+} -+ -+/** -+ * Initializes the DevSpd field of the DCFG register depending on the PHY type -+ * and the enumeration speed of the device. -+ */ -+static void init_devspd(struct dwc_otg_core_if *core_if) -+{ -+ uint32_t val; -+ union dcfg_data dcfg; -+ -+ if (((core_if->hwcfg2.b.hs_phy_type == 2) && -+ (core_if->hwcfg2.b.fs_phy_type == 1) && -+ (core_if->core_params->ulpi_fs_ls)) || -+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { -+ /* Full speed PHY */ -+ val = 0x3; -+ } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { -+ /* High speed PHY running at full speed */ -+ val = 0x1; -+ } else { -+ /* High speed PHY running at high speed */ -+ val = 0x0; -+ } -+ -+ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.b.devspd = val; -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+} -+ -+/** -+ * This function initializes the DWC_otg controller registers and -+ * prepares the core for device mode or host mode operation. -+ * -+ * @core_if: Programming view of the DWC_otg controller -+ * -+ */ -+void dwc_otg_core_init(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ struct dwc_otg_dev_if *dev_if = core_if->dev_if; -+ int i = 0; -+ union gahbcfg_data ahbcfg = {.d32 = 0 }; -+ union gusbcfg_data usbcfg = {.d32 = 0 }; -+ union gi2cctl_data i2cctl = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p)\n", core_if); -+ -+ /* Common Initialization */ -+ -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ -+ /* Program the ULPI External VBUS bit if needed */ -+ usbcfg.b.ulpi_ext_vbus_drv = -+ (core_if->core_params->phy_ulpi_ext_vbus == -+ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0; -+ -+ /* Set external TS Dline pulsing */ -+ usbcfg.b.term_sel_dl_pulse = -+ (core_if->core_params->ts_dline == 1) ? 1 : 0; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ -+ /* Reset the Controller */ -+ dwc_otg_core_reset(core_if); -+ -+ /* Initialize parameters from Hardware configuration registers. */ -+ dev_if->num_eps = core_if->hwcfg2.b.num_dev_ep; -+ dev_if->num_perio_eps = core_if->hwcfg4.b.num_dev_perio_in_ep; -+ -+ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", -+ core_if->hwcfg4.b.num_dev_perio_in_ep); -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { -+ dev_if->perio_tx_fifo_size[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz[i]) >> 16; -+ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", -+ i, dev_if->perio_tx_fifo_size[i]); -+ } -+ -+ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; -+ core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz); -+ core_if->nperio_tx_fifo_size = -+ dwc_read_reg32(&global_regs->gnptxfsiz) >> 16; -+ -+ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n", -+ core_if->nperio_tx_fifo_size); -+ -+ /* This programming sequence needs to happen in FS mode before any other -+ * programming occurs */ -+ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) && -+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { -+ /* If FS mode with FS PHY */ -+ -+ /* core_init() is now called on every switch so only call the -+ * following for the first time through. */ -+ if (!core_if->phy_init_done) { -+ core_if->phy_init_done = 1; -+ DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.b.physel = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ -+ /* Reset after a PHY select */ -+ dwc_otg_core_reset(core_if); -+ } -+ -+ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also -+ * do this on HNP Dev/Host mode switches (done in dev_init and -+ * host_init). */ -+ if (dwc_otg_is_host_mode(core_if)) -+ init_fslspclksel(core_if); -+ else -+ init_devspd(core_if); -+ -+ if (core_if->core_params->i2c_enable) { -+ DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); -+ /* Program GUSBCFG.OtgUtmifsSel to I2C */ -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.b.otgutmifssel = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ -+ /* Program GI2CCTL.I2CEn */ -+ i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl); -+ i2cctl.b.i2cdevaddr = 1; -+ i2cctl.b.i2cen = 0; -+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); -+ i2cctl.b.i2cen = 1; -+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); -+ } -+ -+ } -+ /* endif speed == DWC_SPEED_PARAM_FULL */ -+ else { -+ /* High speed PHY. */ -+ if (!core_if->phy_init_done) { -+ core_if->phy_init_done = 1; -+ /* HS PHY parameters. These parameters are preserved -+ * during soft reset so only program the first time. Do -+ * a soft reset immediately after setting phyif. */ -+ usbcfg.b.ulpi_utmi_sel = -+ (core_if->core_params->phy_type == -+ DWC_PHY_TYPE_PARAM_ULPI); -+ if (usbcfg.b.ulpi_utmi_sel == 1) { -+ /* ULPI interface */ -+ usbcfg.b.phyif = 0; -+ usbcfg.b.ddrsel = -+ core_if->core_params->phy_ulpi_ddr; -+ } else { -+ /* UTMI+ interface */ -+ if (core_if->core_params->phy_utmi_width == 16) -+ usbcfg.b.phyif = 1; -+ else -+ usbcfg.b.phyif = 0; -+ } -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ -+ /* Reset after setting the PHY parameters */ -+ dwc_otg_core_reset(core_if); -+ } -+ } -+ -+ if ((core_if->hwcfg2.b.hs_phy_type == 2) && -+ (core_if->hwcfg2.b.fs_phy_type == 1) && -+ (core_if->core_params->ulpi_fs_ls)) { -+ DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.b.ulpi_fsls = 1; -+ usbcfg.b.ulpi_clk_sus_m = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ } else { -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.b.ulpi_fsls = 0; -+ usbcfg.b.ulpi_clk_sus_m = 0; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ } -+ -+ /* Program the GAHBCFG Register. */ -+ switch (core_if->hwcfg2.b.architecture) { -+ -+ case DWC_SLAVE_ONLY_ARCH: -+ DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n"); -+ ahbcfg.b.nptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; -+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; -+ core_if->dma_enable = 0; -+ break; -+ -+ case DWC_EXT_DMA_ARCH: -+ DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n"); -+ ahbcfg.b.hburstlen = core_if->core_params->dma_burst_size; -+ core_if->dma_enable = (core_if->core_params->dma_enable != 0); -+ break; -+ -+ case DWC_INT_DMA_ARCH: -+ DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); -+ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR; -+ core_if->dma_enable = (core_if->core_params->dma_enable != 0); -+ break; -+ -+ } -+ ahbcfg.b.dmaenable = core_if->dma_enable; -+ dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32); -+ -+ /* -+ * Program the GUSBCFG register. -+ */ -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ -+ switch (core_if->hwcfg2.b.op_mode) { -+ case DWC_MODE_HNP_SRP_CAPABLE: -+ usbcfg.b.hnpcap = (core_if->core_params->otg_cap == -+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); -+ usbcfg.b.srpcap = (core_if->core_params->otg_cap != -+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); -+ break; -+ -+ case DWC_MODE_SRP_ONLY_CAPABLE: -+ usbcfg.b.hnpcap = 0; -+ usbcfg.b.srpcap = (core_if->core_params->otg_cap != -+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); -+ break; -+ -+ case DWC_MODE_NO_HNP_SRP_CAPABLE: -+ usbcfg.b.hnpcap = 0; -+ usbcfg.b.srpcap = 0; -+ break; -+ -+ case DWC_MODE_SRP_CAPABLE_DEVICE: -+ usbcfg.b.hnpcap = 0; -+ usbcfg.b.srpcap = (core_if->core_params->otg_cap != -+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); -+ break; -+ -+ case DWC_MODE_NO_SRP_CAPABLE_DEVICE: -+ usbcfg.b.hnpcap = 0; -+ usbcfg.b.srpcap = 0; -+ break; -+ -+ case DWC_MODE_SRP_CAPABLE_HOST: -+ usbcfg.b.hnpcap = 0; -+ usbcfg.b.srpcap = (core_if->core_params->otg_cap != -+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); -+ break; -+ -+ case DWC_MODE_NO_SRP_CAPABLE_HOST: -+ usbcfg.b.hnpcap = 0; -+ usbcfg.b.srpcap = 0; -+ break; -+ } -+ -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ -+ /* Enable common interrupts */ -+ dwc_otg_enable_common_interrupts(core_if); -+ -+ /* Do device or host intialization based on mode during PCD -+ * and HCD initialization */ -+ if (dwc_otg_is_host_mode(core_if)) { -+ DWC_DEBUGPL(DBG_ANY, "Host Mode\n"); -+ core_if->op_state = A_HOST; -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "Device Mode\n"); -+ core_if->op_state = B_PERIPHERAL; -+#ifdef DWC_DEVICE_ONLY -+ dwc_otg_core_dev_init(core_if); -+#endif -+ } -+} -+ -+/** -+ * This function enables the Device mode interrupts. -+ * -+ * @core_if: Programming view of DWC_otg controller -+ */ -+void dwc_otg_enable_device_interrupts(struct dwc_otg_core_if *core_if) -+{ -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ -+ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); -+ -+ /* Disable all interrupts. */ -+ dwc_write_reg32(&global_regs->gintmsk, 0); -+ -+ /* Clear any pending interrupts */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Enable the common interrupts */ -+ dwc_otg_enable_common_interrupts(core_if); -+ -+ /* Enable interrupts */ -+ intr_mask.b.usbreset = 1; -+ intr_mask.b.enumdone = 1; -+ intr_mask.b.epmismatch = 1; -+ intr_mask.b.inepintr = 1; -+ intr_mask.b.outepintr = 1; -+ intr_mask.b.erlysuspend = 1; -+ -+#ifdef USE_PERIODIC_EP -+ /** @todo NGS: Should this be a module parameter? */ -+ intr_mask.b.isooutdrop = 1; -+ intr_mask.b.eopframe = 1; -+ intr_mask.b.incomplisoin = 1; -+ intr_mask.b.incomplisoout = 1; -+#endif -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); -+ -+ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, -+ dwc_read_reg32(&global_regs->gintmsk)); -+} -+ -+/** -+ * This function initializes the DWC_otg controller registers for -+ * device mode. -+ * -+ * @core_if: Programming view of DWC_otg controller -+ * -+ */ -+void dwc_otg_core_dev_init(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ struct dwc_otg_dev_if *dev_if = core_if->dev_if; -+ struct dwc_otg_core_params *params = core_if->core_params; -+ union dcfg_data dcfg = {.d32 = 0 }; -+ union grstctl_data resetctl = {.d32 = 0 }; -+ int i; -+ uint32_t rx_fifo_size; -+ union fifosize_data nptxfifosize; -+#ifdef USE_PERIODIC_EP -+ union fifosize_data ptxfifosize; -+#endif -+ -+ /* Restart the Phy Clock */ -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ -+ /* Device configuration register */ -+ init_devspd(core_if); -+ dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; -+ dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ /* Configure data FIFO sizes */ -+ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -+ -+ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", -+ core_if->total_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", -+ params->dev_rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", -+ params->dev_nperio_tx_fifo_size); -+ -+ /* Rx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ rx_fifo_size = params->dev_rx_fifo_size; -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ -+ /* Non-periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; -+ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); -+ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+#ifdef USE_PERIODIC_EP -+ /**@todo NGS: Fix Periodic FIFO Sizing! */ -+ /* -+ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. -+ * Indexes of the FIFO size module parameters in the -+ * dev_perio_tx_fifo_size array and the FIFO size registers in -+ * the dptxfsiz array run from 0 to 14. -+ */ -+ /** @todo Finish debug of this */ -+ ptxfifosize.b.startaddr = -+ nptxfifosize.b.startaddr + nptxfifosize.b.depth; -+ for (i = 0; i < dev_if->num_perio_eps; i++) { -+ ptxfifosize.b.depth = params->dev_perio_tx_fifo_size[i]; -+ DWC_DEBUGPL(DBG_CIL, "initial dptxfsiz[%d]=%08x\n", i, -+ dwc_read_reg32(&global_regs->dptxfsiz[i])); -+ dwc_write_reg32(&global_regs->dptxfsiz[i], -+ ptxfifosize.d32); -+ DWC_DEBUGPL(DBG_CIL, "new dptxfsiz[%d]=%08x\n", i, -+ dwc_read_reg32(&global_regs->dptxfsiz[i])); -+ ptxfifosize.b.startaddr += ptxfifosize.b.depth; -+ } -+#endif -+ } -+ /* Flush the FIFOs */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -+ dwc_otg_flush_rx_fifo(core_if); -+ -+ /* Flush the Learning Queue. */ -+ resetctl.b.intknqflsh = 1; -+ dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ -+ /* Clear all pending Device Interrupts */ -+ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0); -+ dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0); -+ dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); -+ dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0); -+ -+ for (i = 0; i < dev_if->num_eps; i++) { -+ union depctl_data depctl; -+ depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -+ if (depctl.b.epena) { -+ depctl.d32 = 0; -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ } else { -+ depctl.d32 = 0; -+ } -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); -+ -+ depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); -+ if (depctl.b.epena) { -+ depctl.d32 = 0; -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ } else { -+ depctl.d32 = 0; -+ } -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); -+ -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0); -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0); -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF); -+ } -+ -+ dwc_otg_enable_device_interrupts(core_if); -+} -+ -+/** -+ * This function enables the Host mode interrupts. -+ * -+ * @core_if: Programming view of DWC_otg controller -+ */ -+void dwc_otg_enable_host_interrupts(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); -+ -+ /* Disable all interrupts. */ -+ dwc_write_reg32(&global_regs->gintmsk, 0); -+ -+ /* Clear any pending interrupts. */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Enable the common interrupts */ -+ dwc_otg_enable_common_interrupts(core_if); -+ -+ /* -+ * Enable host mode interrupts without disturbing common -+ * interrupts. -+ */ -+ intr_mask.b.sofintr = 1; -+ intr_mask.b.portintr = 1; -+ intr_mask.b.hcintr = 1; -+ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); -+} -+ -+/** -+ * This function disables the Host Mode interrupts. -+ * -+ * @core_if: Programming view of DWC_otg controller -+ */ -+void dwc_otg_disable_host_interrupts(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); -+ -+ /* -+ * Disable host mode interrupts without disturbing common -+ * interrupts. -+ */ -+ intr_mask.b.sofintr = 1; -+ intr_mask.b.portintr = 1; -+ intr_mask.b.hcintr = 1; -+ intr_mask.b.ptxfempty = 1; -+ intr_mask.b.nptxfempty = 1; -+ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0); -+} -+ -+/** -+ * The FIFOs are established based on a default percentage of the -+ * total FIFO depth. This function converts the percentage into the -+ * proper setting. -+ * -+ */ -+static inline uint32_t fifo_percentage(uint16_t total_fifo_size, -+ int32_t percentage) -+{ -+ /* 16-byte aligned */ -+ return ((total_fifo_size * percentage) / 100) & (-1 << 3); -+} -+ -+/** -+ * This function initializes the DWC_otg controller registers for -+ * host mode. -+ * -+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the -+ * request queues. Host channels are reset to ensure that they are ready for -+ * performing transfers. -+ * -+ * @core_if: Programming view of DWC_otg controller -+ * -+ */ -+void dwc_otg_core_host_init(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ struct dwc_otg_host_if *host_if = core_if->host_if; -+ struct dwc_otg_core_params *params = core_if->core_params; -+ union hprt0_data hprt0 = {.d32 = 0 }; -+ union fifosize_data nptxfifosize; -+ union fifosize_data ptxfifosize; -+ int i; -+ union hcchar_data hcchar; -+ union hcfg_data hcfg; -+ struct dwc_otg_hc_regs *hc_regs; -+ int num_channels; -+ union gotgctl_data gotgctl = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); -+ -+ /* Restart the Phy Clock */ -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ -+ /* Initialize Host Configuration Register */ -+ init_fslspclksel(core_if); -+ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { -+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg); -+ hcfg.b.fslssupp = 1; -+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32); -+ } -+ -+ /* Configure data FIFO sizes */ -+ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -+ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", -+ core_if->total_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", -+ params->host_rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", -+ params->host_nperio_tx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", -+ params->host_perio_tx_fifo_size); -+ -+ /* Rx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ dwc_write_reg32(&global_regs->grxfsiz, -+ fifo_percentage(core_if->total_fifo_size, -+ dwc_param_host_rx_fifo_size_percentage)); -+ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ -+ /* Non-periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ nptxfifosize.b.depth = -+ fifo_percentage(core_if->total_fifo_size, -+ dwc_param_host_nperio_tx_fifo_size_percentage); -+ nptxfifosize.b.startaddr = -+ dwc_read_reg32(&global_regs->grxfsiz); -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); -+ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+ /* Periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->hptxfsiz)); -+ ptxfifosize.b.depth = -+ core_if->total_fifo_size - -+ dwc_read_reg32(&global_regs->grxfsiz) - -+ nptxfifosize.b.depth; -+ ptxfifosize.b.startaddr = -+ nptxfifosize.b.startaddr + nptxfifosize.b.depth; -+ dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32); -+ DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->hptxfsiz)); -+ } -+ -+ /* Clear Host Set HNP Enable in the OTG Control Register */ -+ gotgctl.b.hstsethnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ -+ /* Make sure the FIFOs are flushed. */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -+ dwc_otg_flush_rx_fifo(core_if); -+ -+ /* Flush out any leftover queued requests. */ -+ num_channels = core_if->core_params->host_channels; -+ for (i = 0; i < num_channels; i++) { -+ hc_regs = core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.chen = 0; -+ hcchar.b.chdis = 1; -+ hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ } -+ -+ /* Halt all channels to put them into a known state. */ -+ for (i = 0; i < num_channels; i++) { -+ int count = 0; -+ hc_regs = core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 1; -+ hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i); -+ do { -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (++count > 1000) { -+ DWC_ERROR -+ ("%s: Unable to clear halt on channel %d\n", -+ __func__, i); -+ break; -+ } -+ } while (hcchar.b.chen); -+ } -+ -+ /* Turn on the vbus power. */ -+ DWC_PRINT("Init: Port Power? op_state=%d\n", core_if->op_state); -+ if (core_if->op_state == A_HOST) { -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ DWC_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr); -+ if (hprt0.b.prtpwr == 0) { -+ hprt0.b.prtpwr = 1; -+ dwc_write_reg32(host_if->hprt0, hprt0.d32); -+ } -+ } -+ -+ dwc_otg_enable_host_interrupts(core_if); -+} -+ -+/** -+ * Prepares a host channel for transferring packets to/from a specific -+ * endpoint. The HCCHARn register is set up with the characteristics specified -+ * in hc. Host channel interrupts that may need to be serviced while this -+ * transfer is in progress are enabled. -+ * -+ * @core_if: Programming view of DWC_otg controller -+ * @hc: Information needed to initialize the host channel -+ */ -+void dwc_otg_hc_init(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) -+{ -+ uint32_t intr_enable; -+ union hcintmsk_data hc_intr_mask; -+ union gintmsk_data gintmsk = {.d32 = 0 }; -+ union hcchar_data hcchar; -+ union hcsplt_data hcsplt; -+ -+ uint8_t hc_num = hc->hc_num; -+ struct dwc_otg_host_if *host_if = core_if->host_if; -+ struct dwc_otg_hc_regs *hc_regs = host_if->hc_regs[hc_num]; -+ -+ /* Clear old interrupt conditions for this host channel. */ -+ hc_intr_mask.d32 = 0xFFFFFFFF; -+ hc_intr_mask.b.reserved = 0; -+ dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32); -+ -+ /* Enable channel interrupts required for this transfer. */ -+ hc_intr_mask.d32 = 0; -+ hc_intr_mask.b.chhltd = 1; -+ if (core_if->dma_enable) { -+ hc_intr_mask.b.ahberr = 1; -+ if (hc->error_state && !hc->do_split && -+ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { -+ hc_intr_mask.b.ack = 1; -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.datatglerr = 1; -+ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) -+ hc_intr_mask.b.nak = 1; -+ } -+ } -+ } else { -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ hc_intr_mask.b.xfercompl = 1; -+ hc_intr_mask.b.stall = 1; -+ hc_intr_mask.b.xacterr = 1; -+ hc_intr_mask.b.datatglerr = 1; -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.bblerr = 1; -+ } else { -+ hc_intr_mask.b.nak = 1; -+ hc_intr_mask.b.nyet = 1; -+ if (hc->do_ping) -+ hc_intr_mask.b.ack = 1; -+ } -+ -+ if (hc->do_split) { -+ hc_intr_mask.b.nak = 1; -+ if (hc->complete_split) -+ hc_intr_mask.b.nyet = 1; -+ else -+ hc_intr_mask.b.ack = 1; -+ } -+ -+ if (hc->error_state) -+ hc_intr_mask.b.ack = 1; -+ break; -+ case DWC_OTG_EP_TYPE_INTR: -+ hc_intr_mask.b.xfercompl = 1; -+ hc_intr_mask.b.nak = 1; -+ hc_intr_mask.b.stall = 1; -+ hc_intr_mask.b.xacterr = 1; -+ hc_intr_mask.b.datatglerr = 1; -+ hc_intr_mask.b.frmovrun = 1; -+ -+ if (hc->ep_is_in) -+ hc_intr_mask.b.bblerr = 1; -+ if (hc->error_state) -+ hc_intr_mask.b.ack = 1; -+ if (hc->do_split) { -+ if (hc->complete_split) -+ hc_intr_mask.b.nyet = 1; -+ else -+ hc_intr_mask.b.ack = 1; -+ } -+ break; -+ case DWC_OTG_EP_TYPE_ISOC: -+ hc_intr_mask.b.xfercompl = 1; -+ hc_intr_mask.b.frmovrun = 1; -+ hc_intr_mask.b.ack = 1; -+ -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.xacterr = 1; -+ hc_intr_mask.b.bblerr = 1; -+ } -+ break; -+ } -+ } -+ dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32); -+ -+ /* Enable the top level host channel interrupt. */ -+ intr_enable = (1 << hc_num); -+ dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable); -+ -+ /* Make sure host channel interrupts are enabled. */ -+ gintmsk.b.hcintr = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); -+ -+ /* -+ * Program the HCCHARn register with the endpoint characteristics for -+ * the current transfer. -+ */ -+ hcchar.d32 = 0; -+ hcchar.b.devaddr = hc->dev_addr; -+ hcchar.b.epnum = hc->ep_num; -+ hcchar.b.epdir = hc->ep_is_in; -+ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); -+ hcchar.b.eptype = hc->ep_type; -+ hcchar.b.mps = hc->max_packet; -+ -+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); -+ DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); -+ DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); -+ DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); -+ DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); -+ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); -+ -+ /* -+ * Program the HCSPLIT register for SPLITs -+ */ -+ hcsplt.d32 = 0; -+ if (hc->do_split) { -+ DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", -+ hc->hc_num, -+ hc->complete_split ? "CSPLIT" : "SSPLIT"); -+ hcsplt.b.compsplt = hc->complete_split; -+ hcsplt.b.xactpos = hc->xact_pos; -+ hcsplt.b.hubaddr = hc->hub_addr; -+ hcsplt.b.prtaddr = hc->port_addr; -+ DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", -+ hc->complete_split); -+ DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); -+ DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); -+ DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); -+ DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); -+ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); -+ } -+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); -+ -+} -+ -+/** -+ * Attempts to halt a host channel. This function should only be called in -+ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under -+ * normal circumstances in DMA mode, the controller halts the channel when the -+ * transfer is complete or a condition occurs that requires application -+ * intervention. -+ * -+ * In slave mode, checks for a free request queue entry, then sets the Channel -+ * Enable and Channel Disable bits of the Host Channel Characteristics -+ * register of the specified channel to intiate the halt. If there is no free -+ * request queue entry, sets only the Channel Disable bit of the HCCHARn -+ * register to flush requests for this channel. In the latter case, sets a -+ * flag to indicate that the host channel needs to be halted when a request -+ * queue slot is open. -+ * -+ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the -+ * HCCHARn register. The controller ensures there is space in the request -+ * queue before submitting the halt request. -+ * -+ * Some time may elapse before the core flushes any posted requests for this -+ * host channel and halts. The Channel Halted interrupt handler completes the -+ * deactivation of the host channel. -+ * -+ * @core_if: Controller register interface. -+ * @hc: Host channel to halt. -+ * @halt_status: Reason for halting the channel. -+ */ -+void dwc_otg_hc_halt(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc, enum dwc_otg_halt_status halt_status) -+{ -+ union gnptxsts_data nptxsts; -+ union hptxsts_data hptxsts; -+ union hcchar_data hcchar; -+ struct dwc_otg_hc_regs *hc_regs; -+ struct dwc_otg_core_global_regs *global_regs; -+ struct dwc_otg_host_global_regs *host_global_regs; -+ -+ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ global_regs = core_if->core_global_regs; -+ host_global_regs = core_if->host_if->host_global_regs; -+ -+ WARN_ON(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS); -+ -+ if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || -+ halt_status == DWC_OTG_HC_XFER_AHB_ERR) { -+ /* -+ * Disable all channel interrupts except Ch Halted. The QTD -+ * and QH state associated with this transfer has been cleared -+ * (in the case of URB_DEQUEUE), so the channel needs to be -+ * shut down carefully to prevent crashes. -+ */ -+ union hcintmsk_data hcintmsk; -+ hcintmsk.d32 = 0; -+ hcintmsk.b.chhltd = 1; -+ dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32); -+ -+ /* -+ * Make sure no other interrupts besides halt are currently -+ * pending. Handling another interrupt could cause a crash due -+ * to the QTD and QH state. -+ */ -+ dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32); -+ -+ /* -+ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR -+ * even if the channel was already halted for some other -+ * reason. -+ */ -+ hc->halt_status = halt_status; -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen == 0) { -+ /* -+ * The channel is either already halted or it hasn't -+ * started yet. In DMA mode, the transfer may halt if -+ * it finishes normally or a condition occurs that -+ * requires driver intervention. Don't want to halt -+ * the channel again. In either Slave or DMA mode, -+ * it's possible that the transfer has been assigned -+ * to a channel, but not started yet when an URB is -+ * dequeued. Don't want to halt a channel that hasn't -+ * started yet. -+ */ -+ return; -+ } -+ } -+ -+ if (hc->halt_pending) { -+ /* -+ * A halt has already been issued for this channel. This might -+ * happen when a transfer is aborted by a higher level in -+ * the stack. -+ */ -+#ifdef DEBUG -+ DWC_PRINT -+ ("*** %s: Channel %d, hc->halt_pending already set ***\n", -+ __func__, hc->hc_num); -+ -+/* dwc_otg_dump_global_registers(core_if); */ -+/* dwc_otg_dump_host_registers(core_if); */ -+#endif -+ return; -+ } -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 1; -+ -+ if (!core_if->dma_enable) { -+ /* Check for space in the request queue to issue the halt. */ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || -+ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { -+ nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ if (nptxsts.b.nptxqspcavail == 0) -+ hcchar.b.chen = 0; -+ } else { -+ hptxsts.d32 = -+ dwc_read_reg32(&host_global_regs->hptxsts); -+ if ((hptxsts.b.ptxqspcavail == 0) -+ || (core_if->queuing_high_bandwidth)) { -+ hcchar.b.chen = 0; -+ } -+ } -+ } -+ -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ hc->halt_status = halt_status; -+ -+ if (hcchar.b.chen) { -+ hc->halt_pending = 1; -+ hc->halt_on_queue = 0; -+ } else { -+ hc->halt_on_queue = 1; -+ } -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); -+ DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); -+ DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); -+ DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); -+ -+ return; -+} -+ -+/** -+ * Clears the transfer state for a host channel. This function is normally -+ * called after a transfer is done and the host channel is being released. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @hc: Identifies the host channel to clean up. -+ */ -+void dwc_otg_hc_cleanup(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) -+{ -+ struct dwc_otg_hc_regs *hc_regs; -+ -+ hc->xfer_started = 0; -+ -+ /* -+ * Clear channel interrupt enables and any unhandled channel interrupt -+ * conditions. -+ */ -+ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ dwc_write_reg32(&hc_regs->hcintmsk, 0); -+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF); -+ -+#ifdef DEBUG -+ del_timer(&core_if->hc_xfer_timer[hc->hc_num]); -+ { -+ union hcchar_data hcchar; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chdis) { -+ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", -+ __func__, hc->hc_num, hcchar.d32); -+ } -+ } -+#endif -+} -+ -+/** -+ * Sets the channel property that indicates in which frame a periodic transfer -+ * should occur. This is always set to the _next_ frame. This function has no -+ * effect on non-periodic transfers. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @hc: Identifies the host channel to set up and its properties. -+ * @hcchar: Current value of the HCCHAR register for the specified host -+ * channel. -+ */ -+static inline void hc_set_even_odd_frame(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc, -+ union hcchar_data *hcchar) -+{ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ union hfnum_data hfnum; -+ hfnum.d32 = -+ dwc_read_reg32(&core_if->host_if->host_global_regs->hfnum); -+ /* 1 if _next_ frame is odd, 0 if it's even */ -+ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; -+#ifdef DEBUG -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split -+ && !hc->complete_split) { -+ switch (hfnum.b.frnum & 0x7) { -+ case 7: -+ core_if->hfnum_7_samples++; -+ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; -+ break; -+ case 0: -+ core_if->hfnum_0_samples++; -+ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; -+ break; -+ default: -+ core_if->hfnum_other_samples++; -+ core_if->hfnum_other_frrem_accum += -+ hfnum.b.frrem; -+ break; -+ } -+ } -+#endif -+ } -+} -+ -+#ifdef DEBUG -+static void hc_xfer_timeout(unsigned long _ptr) -+{ -+ struct hc_xfer_info *xfer_info = (struct hc_xfer_info *) _ptr; -+ int hc_num = xfer_info->hc->hc_num; -+ DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); -+ DWC_WARN(" start_hcchar_val 0x%08x\n", -+ xfer_info->core_if->start_hcchar_val[hc_num]); -+} -+#endif -+ -+/** -+ * This function does the setup for a data transfer for a host channel and -+ * starts the transfer. May be called in either Slave mode or DMA mode. In -+ * Slave mode, the caller must ensure that there is sufficient space in the -+ * request queue and Tx Data FIFO. -+ * -+ * For an OUT transfer in Slave mode, it loads a data packet into the -+ * appropriate FIFO. If necessary, additional data packets will be loaded in -+ * the Host ISR. -+ * -+ * For an IN transfer in Slave mode, a data packet is requested. The data -+ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, -+ * additional data packets are requested in the Host ISR. -+ * -+ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ -+ * register along with a packet count of 1 and the channel is enabled. This -+ * causes a single PING transaction to occur. Other fields in HCTSIZ are -+ * simply set to 0 since no data transfer occurs in this case. -+ * -+ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with -+ * all the information required to perform the subsequent data transfer. In -+ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the -+ * controller performs the entire PING protocol, then starts the data -+ * transfer. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @hc: Information needed to initialize the host channel. The xfer_len -+ * value may be reduced to accommodate the max widths of the XferSize and -+ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed -+ * to reflect the final xfer_len value. -+ */ -+void dwc_otg_hc_start_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc) -+{ -+ union hcchar_data hcchar; -+ union hctsiz_data hctsiz; -+ uint16_t num_packets; -+ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; -+ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; -+ struct dwc_otg_hc_regs *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ -+ hctsiz.d32 = 0; -+ -+ if (hc->do_ping) { -+ if (!core_if->dma_enable) { -+ dwc_otg_hc_do_ping(core_if, hc); -+ hc->xfer_started = 1; -+ return; -+ } else { -+ hctsiz.b.dopng = 1; -+ } -+ } -+ -+ if (hc->do_split) { -+ num_packets = 1; -+ -+ if (hc->complete_split && !hc->ep_is_in) { -+ /* For CSPLIT OUT Transfer, set the size to 0 so the -+ * core doesn't expect any data written to the FIFO */ -+ hc->xfer_len = 0; -+ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { -+ hc->xfer_len = hc->max_packet; -+ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { -+ hc->xfer_len = 188; -+ } -+ -+ hctsiz.b.xfersize = hc->xfer_len; -+ } else { -+ /* -+ * Ensure that the transfer length and packet count will fit -+ * in the widths allocated for them in the HCTSIZn register. -+ */ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * Make sure the transfer size is no larger than one -+ * (micro)frame's worth of data. (A check was done -+ * when the periodic transfer was accepted to ensure -+ * that a (micro)frame's worth of data can be -+ * programmed into a channel.) -+ */ -+ uint32_t max_periodic_len = -+ hc->multi_count * hc->max_packet; -+ if (hc->xfer_len > max_periodic_len) -+ hc->xfer_len = max_periodic_len; -+ } else if (hc->xfer_len > max_hc_xfer_size) { -+ /* -+ * Make sure that xfer_len is a multiple of -+ * max packet size. -+ */ -+ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; -+ } -+ -+ if (hc->xfer_len > 0) { -+ num_packets = -+ (hc->xfer_len + hc->max_packet - -+ 1) / hc->max_packet; -+ if (num_packets > max_hc_pkt_count) { -+ num_packets = max_hc_pkt_count; -+ hc->xfer_len = num_packets * hc->max_packet; -+ } -+ } else { -+ /* Need 1 packet for transfer length of 0. */ -+ num_packets = 1; -+ } -+ -+ if (hc->ep_is_in) { -+ /* -+ * Always program an integral # of max packets -+ * for IN transfers. -+ */ -+ hc->xfer_len = num_packets * hc->max_packet; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * Make sure that the multi_count field matches the -+ * actual transfer length. -+ */ -+ hc->multi_count = num_packets; -+ -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* Set up the initial PID for the transfer. */ -+ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { -+ if (hc->ep_is_in) { -+ if (hc->multi_count == 1) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA0; -+ } else if (hc->multi_count == 2) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA1; -+ } else { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA2; -+ } -+ } else { -+ if (hc->multi_count == 1) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA0; -+ } else { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_MDATA; -+ } -+ } -+ } else { -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; -+ } -+ } -+ -+ hctsiz.b.xfersize = hc->xfer_len; -+ } -+ -+ hc->start_pkt_count = num_packets; -+ hctsiz.b.pktcnt = num_packets; -+ hctsiz.b.pid = hc->data_pid_start; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); -+ DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); -+ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); -+ -+ if (core_if->dma_enable) { -+#ifdef CONFIG_CPU_CAVIUM_OCTEON -+ /* Octeon uses external DMA */ -+ const uint64_t USBN_DMA0_OUTB_CHN0 = -+ CVMX_USBNX_DMA0_OUTB_CHN0(core_if->usb_num); -+ wmb(); -+ cvmx_write_csr(USBN_DMA0_OUTB_CHN0 + hc->hc_num * 8, -+ (unsigned long)hc->xfer_buff); -+ cvmx_read_csr(USBN_DMA0_OUTB_CHN0 + hc->hc_num * 8); -+ DWC_DEBUGPL(DBG_HCDV, -+ "OUT: hc->hc_num = %d, hc->xfer_buff = %p\n", -+ hc->hc_num, hc->xfer_buff); -+#else -+ dwc_write_reg32(&hc_regs->hcdma, -+ (uint32_t) (long)hc->xfer_buff); -+#endif /* CONFIG_CPU_CAVIUM_OCTEON */ -+ } -+ -+ /* Start the split */ -+ if (hc->do_split) { -+ union hcsplt_data hcsplt; -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hcsplt.b.spltena = 1; -+ dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32); -+ } -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.multicnt = hc->multi_count; -+ hc_set_even_odd_frame(core_if, hc, &hcchar); -+#ifdef DEBUG -+ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; -+ if (hcchar.b.chdis) { -+ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", -+ __func__, hc->hc_num, hcchar.d32); -+ } -+#endif -+ -+ /* Set host channel enable after all other setup is complete. */ -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ hc->xfer_started = 1; -+ hc->requests++; -+ -+ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { -+ /* Load OUT packet into the appropriate Tx FIFO. */ -+ dwc_otg_hc_write_packet(core_if, hc); -+ } -+#ifdef DEBUG -+ /* Start a timer for this transfer. */ -+ core_if->hc_xfer_timer[hc->hc_num].function = hc_xfer_timeout; -+ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; -+ core_if->hc_xfer_info[hc->hc_num].hc = hc; -+ core_if->hc_xfer_timer[hc->hc_num].data = -+ (unsigned long)(&core_if->hc_xfer_info[hc->hc_num]); -+ core_if->hc_xfer_timer[hc->hc_num].expires = jiffies + (HZ * 10); -+ add_timer(&core_if->hc_xfer_timer[hc->hc_num]); -+#endif -+} -+ -+/** -+ * This function continues a data transfer that was started by previous call -+ * to dwc_otg_hc_start_transfer. The caller must ensure there is -+ * sufficient space in the request queue and Tx Data FIFO. This function -+ * should only be called in Slave mode. In DMA mode, the controller acts -+ * autonomously to complete transfers programmed to a host channel. -+ * -+ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO -+ * if there is any data remaining to be queued. For an IN transfer, another -+ * data packet is always requested. For the SETUP phase of a control transfer, -+ * this function does nothing. -+ * -+ * Returns 1 if a new request is queued, 0 if no more requests are required -+ * for this transfer. -+ */ -+int dwc_otg_hc_continue_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc) -+{ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ -+ if (hc->do_split) { -+ /* SPLITs always queue just once per channel */ -+ return 0; -+ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { -+ /* SETUPs are queued only once since they can't be NAKed. */ -+ return 0; -+ } else if (hc->ep_is_in) { -+ /* -+ * Always queue another request for other IN transfers. If -+ * back-to-back INs are issued and NAKs are received for both, -+ * the driver may still be processing the first NAK when the -+ * second NAK is received. When the interrupt handler clears -+ * the NAK interrupt for the first NAK, the second NAK will -+ * not be seen. So we can't depend on the NAK interrupt -+ * handler to requeue a NAKed request. Instead, IN requests -+ * are issued each time this function is called. When the -+ * transfer completes, the extra requests for the channel will -+ * be flushed. -+ */ -+ union hcchar_data hcchar; -+ struct dwc_otg_hc_regs *hc_regs = -+ core_if->host_if->hc_regs[hc->hc_num]; -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hc_set_even_odd_frame(core_if, hc, &hcchar); -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 0; -+ DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", -+ hcchar.d32); -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ hc->requests++; -+ return 1; -+ } else { -+ /* OUT transfers. */ -+ if (hc->xfer_count < hc->xfer_len) { -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ union hcchar_data hcchar; -+ struct dwc_otg_hc_regs *hc_regs; -+ hc_regs = -+ core_if->host_if->hc_regs[hc->hc_num]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hc_set_even_odd_frame(core_if, hc, &hcchar); -+ } -+ -+ /* Load OUT packet into the appropriate Tx FIFO. */ -+ dwc_otg_hc_write_packet(core_if, hc); -+ hc->requests++; -+ return 1; -+ } else { -+ return 0; -+ } -+ } -+} -+ -+/** -+ * Starts a PING transfer. This function should only be called in Slave mode. -+ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. -+ */ -+void dwc_otg_hc_do_ping(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) -+{ -+ union hcchar_data hcchar; -+ union hctsiz_data hctsiz; -+ struct dwc_otg_hc_regs *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ -+ hctsiz.d32 = 0; -+ hctsiz.b.dopng = 1; -+ hctsiz.b.pktcnt = 1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+} -+ -+/* -+ * This function writes a packet into the Tx FIFO associated with the Host -+ * Channel. For a channel associated with a non-periodic EP, the non-periodic -+ * Tx FIFO is written. For a channel associated with a periodic EP, the -+ * periodic Tx FIFO is written. This function should only be called in Slave -+ * mode. -+ * -+ * Upon return the xfer_buff and xfer_count fields in hc are incremented by -+ * then number of bytes written to the Tx FIFO. -+ */ -+void dwc_otg_hc_write_packet(struct dwc_otg_core_if *core_if, struct dwc_hc *hc) -+{ -+ uint32_t i; -+ uint32_t remaining_count; -+ uint32_t byte_count; -+ uint32_t dword_count; -+ -+ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); -+ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; -+ -+ remaining_count = hc->xfer_len - hc->xfer_count; -+ if (remaining_count > hc->max_packet) -+ byte_count = hc->max_packet; -+ else -+ byte_count = remaining_count; -+ -+ dword_count = (byte_count + 3) / 4; -+ -+ if ((((unsigned long)data_buff) & 0x3) == 0) { -+ /* xfer_buff is DWORD aligned. */ -+ for (i = 0; i < dword_count; i++, data_buff++) -+ dwc_write_reg32(data_fifo, *data_buff); -+ } else { -+ /* xfer_buff is not DWORD aligned. */ -+ for (i = 0; i < dword_count; i++, data_buff++) -+ dwc_write_reg32(data_fifo, get_unaligned(data_buff)); -+ } -+ -+ hc->xfer_count += byte_count; -+ hc->xfer_buff += byte_count; -+} -+ -+/** -+ * Gets the current USB frame number. This is the frame number from the last -+ * SOF packet. -+ */ -+uint32_t dwc_otg_get_frame_number(struct dwc_otg_core_if *core_if) -+{ -+ union dsts_data dsts; -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ -+ /* read current frame/microfreme number from DSTS register */ -+ return dsts.b.soffn; -+} -+ -+/** -+ * This function reads a setup packet from the Rx FIFO into the destination -+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) -+ * Interrupt routine when a SETUP packet has been received in Slave mode. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @dest: Destination buffer for packet data. -+ */ -+void dwc_otg_read_setup_packet(struct dwc_otg_core_if *core_if, uint32_t *dest) -+{ -+ /* Get the 8 bytes of a setup transaction data */ -+ -+ /* Pop 2 DWORDS off the receive data FIFO into memory */ -+ dest[0] = dwc_read_reg32(core_if->data_fifo[0]); -+ dest[1] = dwc_read_reg32(core_if->data_fifo[0]); -+} -+ -+/** -+ * This function enables EP0 OUT to receive SETUP packets and configures EP0 -+ * IN for transmitting packets. It is normally called when the -+ * "Enumeration Done" interrupt occurs. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP0 data. -+ */ -+void dwc_otg_ep0_activate(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) -+{ -+ struct dwc_otg_dev_if *dev_if = core_if->dev_if; -+ union dsts_data dsts; -+ union depctl_data diepctl; -+ union depctl_data doepctl; -+ union dctl_data dctl = {.d32 = 0 }; -+ -+ /* Read the Device Status and Endpoint 0 Control registers */ -+ dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts); -+ diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); -+ doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl); -+ -+ /* Set the MPS of the IN EP based on the enumeration speed */ -+ switch (dsts.b.enumspd) { -+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: -+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: -+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: -+ diepctl.b.mps = DWC_DEP0CTL_MPS_64; -+ break; -+ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: -+ diepctl.b.mps = DWC_DEP0CTL_MPS_8; -+ break; -+ } -+ -+ dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); -+ -+ /* Enable OUT EP for receive */ -+ doepctl.b.epena = 1; -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); -+#endif -+ dctl.b.cgnpinnak = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", -+ dwc_read_reg32(&dev_if->dev_global_regs->dctl)); -+} -+ -+/** -+ * This function activates an EP. The Device EP control register for -+ * the EP is configured as defined in the ep structure. Note: This -+ * function is not used for EP0. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP to activate. -+ */ -+void dwc_otg_ep_activate(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) -+{ -+ struct dwc_otg_dev_if *dev_if = core_if->dev_if; -+ union depctl_data depctl; -+ uint32_t *addr; -+ union daint_data daintmsk = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, -+ (ep->is_in ? "IN" : "OUT")); -+ -+ /* Read DEPCTLn register */ -+ if (ep->is_in == 1) { -+ addr = &dev_if->in_ep_regs[ep->num]->diepctl; -+ daintmsk.ep.in = 1 << ep->num; -+ } else { -+ addr = &dev_if->out_ep_regs[ep->num]->doepctl; -+ daintmsk.ep.out = 1 << ep->num; -+ } -+ -+ /* If the EP is already active don't change the EP Control -+ * register. */ -+ depctl.d32 = dwc_read_reg32(addr); -+ if (!depctl.b.usbactep) { -+ depctl.b.mps = ep->maxpacket; -+ depctl.b.eptype = ep->type; -+ depctl.b.txfnum = ep->tx_fifo_num; -+ -+ if (ep->type != DWC_OTG_EP_TYPE_ISOC) -+ depctl.b.setd0pid = 1; -+ -+ depctl.b.usbactep = 1; -+ -+ dwc_write_reg32(addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", dwc_read_reg32(addr)); -+ } -+ -+ /* Enable the Interrupt for this EP */ -+ dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk, 0, daintmsk.d32); -+ DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", -+ dwc_read_reg32(&dev_if->dev_global_regs->daintmsk)); -+ return; -+} -+ -+/** -+ * This function deactivates an EP. This is done by clearing the USB Active -+ * EP bit in the Device EP control register. Note: This function is not used -+ * for EP0. EP0 cannot be deactivated. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP to deactivate. -+ */ -+void dwc_otg_ep_deactivate(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) -+{ -+ union depctl_data depctl = {.d32 = 0 }; -+ uint32_t *addr; -+ union daint_data daintmsk = {.d32 = 0 }; -+ -+ /* Read DEPCTLn register */ -+ if (ep->is_in == 1) { -+ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; -+ daintmsk.ep.in = 1 << ep->num; -+ } else { -+ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; -+ daintmsk.ep.out = 1 << ep->num; -+ } -+ -+ depctl.b.usbactep = 0; -+ dwc_write_reg32(addr, depctl.d32); -+ -+ /* Disable the Interrupt for this EP */ -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk, -+ daintmsk.d32, 0); -+ -+ return; -+} -+ -+/** -+ * This function does the setup for a data transfer for an EP and -+ * starts the transfer. For an IN transfer, the packets will be -+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, -+ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP to start the transfer on. -+ */ -+void dwc_otg_ep_start_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep) -+{ -+ /* -+ * @todo Refactor this funciton to check the transfer size -+ * count value does not execed the number bits in the Transfer -+ * count register. -+ */ -+ union depctl_data depctl; -+ union deptsiz_data deptsiz; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ -+#ifdef CHECK_PACKET_COUNTER_WIDTH -+ const uint32_t MAX_XFER_SIZE = core_if->core_params->max_transfer_size; -+ const uint32_t MAX_PKT_COUNT = core_if->core_params->max_packet_count; -+ uint32_t num_packets; -+ uint32_t transfer_len; -+ struct dwc_otg_dev_out_ep_regs *out_regs = -+ core_if->dev_if->out_ep_regs[ep->num]; -+ struct dwc_otg_dev_in_ep_regs *in_regs = -+ core_if->dev_if->in_ep_regs[ep->num]; -+ union gnptxsts_data txstatus; -+ -+ int lvl = SET_DEBUG_LEVEL(DBG_PCD); -+ -+ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " -+ "xfer_buff=%p start_xfer_buff=%p\n", -+ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, -+ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); -+ -+ transfer_len = ep->xfer_len - ep->xfer_count; -+ if (transfer_len > MAX_XFER_SIZE) -+ transfer_len = MAX_XFER_SIZE; -+ -+ if (transfer_len == 0) { -+ num_packets = 1; -+ /* OUT EP to recieve Zero-length packet set transfer -+ * size to maxpacket size. */ -+ if (!ep->is_in) -+ transfer_len = ep->maxpacket; -+ } else { -+ num_packets = -+ (transfer_len + ep->maxpacket - 1) / ep->maxpacket; -+ if (num_packets > MAX_PKT_COUNT) -+ num_packets = MAX_PKT_COUNT; -+ } -+ DWC_DEBUGPL(DBG_PCD, "transfer_len=%d #pckt=%d\n", transfer_len, -+ num_packets); -+ -+ deptsiz.b.xfersize = transfer_len; -+ deptsiz.b.pktcnt = num_packets; -+ -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ } else { /* OUT endpoint */ -+ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ txstatus.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ if (txstatus.b.nptxqspcavail == 0) { -+ DWC_DEBUGPL(DBG_ANY, "TX Queue Full (0x%0x)\n", -+ txstatus.d32); -+ return; -+ } -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ /* -+ * Enable the Non-Periodic Tx FIFO empty interrupt, the -+ * data will be written into the fifo by the ISR. -+ */ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(&in_regs->diepdma, -+ (uint32_t) ep->xfer_buff); -+ } else { -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintsts, -+ intr_mask.d32, 0); -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); -+ } -+ } else { /* OUT endpoint */ -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ if (core_if->dma_enable) { -+ dwc_write_reg32(&out_regs->doepdma, -+ (uint32_t) ep->xfer_buff); -+ } -+ } -+ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", -+ dwc_read_reg32(&out_regs->doepctl), -+ dwc_read_reg32(&out_regs->doeptsiz)); -+ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ daintmsk), -+ dwc_read_reg32(&core_if->core_global_regs->gintmsk)); -+ -+ SET_DEBUG_LEVEL(lvl); -+#endif -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); -+ -+ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " -+ "xfer_buff=%p start_xfer_buff=%p\n", -+ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, -+ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); -+ -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ struct dwc_otg_dev_in_ep_regs *in_regs = -+ core_if->dev_if->in_ep_regs[ep->num]; -+ union gnptxsts_data txstatus; -+ -+ txstatus.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ if (txstatus.b.nptxqspcavail == 0) { -+#ifdef DEBUG -+ DWC_PRINT("TX Queue Full (0x%0x)\n", txstatus.d32); -+#endif -+ return; -+ } -+ -+ depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); -+ -+ /* Zero Length Packet? */ -+ if (ep->xfer_len == 0) { -+ deptsiz.b.xfersize = 0; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ deptsiz.b.xfersize = ep->xfer_len; -+ deptsiz.b.pktcnt = -+ (ep->xfer_len - 1 + ep->maxpacket) / -+ ep->maxpacket; -+ } -+ -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } else { -+ /* -+ * Enable the Non-Periodic Tx FIFO empty interrupt, -+ * the data will be written into the fifo by the ISR. -+ */ -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintsts, -+ intr_mask.d32, 0); -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ depctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ depctl.b.nextep = ep->num; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -+ depctl.d32); -+ -+ } else { -+ /* OUT endpoint */ -+ struct dwc_otg_dev_out_ep_regs *out_regs = -+ core_if->dev_if->out_ep_regs[ep->num]; -+ -+ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); -+ -+ /* Program the transfer size and packet count as follows: -+ * -+ * pktcnt = N -+ * xfersize = N * maxpacket -+ */ -+ if (ep->xfer_len == 0) { -+ /* Zero Length Packet */ -+ deptsiz.b.xfersize = ep->maxpacket; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ deptsiz.b.pktcnt = -+ (ep->xfer_len + (ep->maxpacket - 1)) / -+ ep->maxpacket; -+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; -+ } -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ -+ DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", -+ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * @todo NGS: dpid is read-only. Use setd0pid -+ * or setd1pid. -+ */ -+ depctl.b.dpid = ep->even_odd_frame; -+ } -+ -+ /* EP enable */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ -+ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", -+ dwc_read_reg32(&out_regs->doepctl), -+ dwc_read_reg32(&out_regs->doeptsiz)); -+ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ daintmsk), -+ dwc_read_reg32(&core_if->core_global_regs-> -+ gintmsk)); -+ } -+} -+ -+/** -+ * This function does the setup for a data transfer for EP0 and starts -+ * the transfer. For an IN transfer, the packets will be loaded into -+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are -+ * unloaded from the Rx FIFO in the ISR. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP0 data. -+ */ -+void dwc_otg_ep0_start_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep) -+{ -+ union depctl_data depctl; -+ union deptsiz0_data deptsiz; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " -+ "xfer_buff=%p start_xfer_buff=%p total_len=%d\n", -+ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, -+ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, -+ ep->total_len); -+ ep->total_len = ep->xfer_len; -+ -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ struct dwc_otg_dev_in_ep_regs *in_regs = -+ core_if->dev_if->in_ep_regs[0]; -+ union gnptxsts_data tx_status = {.d32 = 0 }; -+ -+ tx_status.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ if (tx_status.b.nptxqspcavail == 0) { -+#ifdef DEBUG -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", -+ dwc_read_reg32(&in_regs->diepctl)); -+ DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", -+ deptsiz.d32, -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ DWC_PRINT("TX Queue or FIFO Full (0x%0x)\n", -+ tx_status.d32); -+#endif -+ -+ return; -+ } -+ -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ -+ /* Zero Length Packet? */ -+ if (ep->xfer_len == 0) { -+ deptsiz.b.xfersize = 0; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ if (ep->xfer_len > ep->maxpacket) { -+ ep->xfer_len = ep->maxpacket; -+ deptsiz.b.xfersize = ep->maxpacket; -+ } else { -+ deptsiz.b.xfersize = ep->xfer_len; -+ } -+ deptsiz.b.pktcnt = 1; -+ -+ } -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ DWC_DEBUGPL(DBG_PCDV, -+ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", -+ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, -+ deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ /* -+ * Enable the Non-Periodic Tx FIFO empty interrupt, the -+ * data will be written into the fifo by the ISR. -+ */ -+ if (!core_if->dma_enable) { -+ /* First clear it from GINTSTS */ -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintsts, -+ intr_mask.d32, 0); -+ -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); -+ } -+ -+ } else { /* OUT endpoint */ -+ struct dwc_otg_dev_out_ep_regs *out_regs = -+ core_if->dev_if->out_ep_regs[ep->num]; -+ -+ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -+ deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); -+ -+ /* Program the transfer size and packet count as follows: -+ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) -+ * pktcnt = N */ -+ if (ep->xfer_len == 0) { -+ /* Zero Length Packet */ -+ deptsiz.b.xfersize = ep->maxpacket; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ deptsiz.b.pktcnt = -+ (ep->xfer_len + (ep->maxpacket - 1)) / -+ ep->maxpacket; -+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; -+ } -+ -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", -+ ep->xfer_len, -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ -+ /* EP enable */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&(out_regs->doepctl), depctl.d32); -+ } -+} -+ -+/** -+ * This function continues control IN transfers started by -+ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a -+ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one -+ * bit for the packet count. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP0 data. -+ */ -+void dwc_otg_ep0_continue_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep) -+{ -+ union depctl_data depctl; -+ union deptsiz0_data deptsiz; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ -+ if (ep->is_in == 1) { -+ struct dwc_otg_dev_in_ep_regs *in_regs = -+ core_if->dev_if->in_ep_regs[0]; -+ union gnptxsts_data tx_status = {.d32 = 0 }; -+ -+ tx_status.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ /* -+ * @todo Should there be check for room in the Tx -+ * Status Queue. If not remove the code above this comment. -+ */ -+ -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ -+ /* -+ * Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ deptsiz.b.xfersize = -+ (ep->total_len - ep->xfer_count) > -+ ep->maxpacket ? ep->maxpacket : (ep->total_len - -+ ep->xfer_count); -+ deptsiz.b.pktcnt = 1; -+ ep->xfer_len += deptsiz.b.xfersize; -+ -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ DWC_DEBUGPL(DBG_PCDV, -+ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", -+ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, -+ deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ /* -+ * Enable the Non-Periodic Tx FIFO empty interrupt, the -+ * data will be written into the fifo by the ISR. -+ */ -+ if (!core_if->dma_enable) { -+ /* First clear it from GINTSTS */ -+ intr_mask.b.nptxfempty = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, -+ intr_mask.d32); -+ -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); -+ } -+ -+ } -+ -+} -+ -+#ifdef DEBUG -+void dump_msg(const u8 *buf, unsigned int length) -+{ -+ unsigned int start, num, i; -+ char line[52], *p; -+ -+ if (length >= 512) -+ return; -+ start = 0; -+ while (length > 0) { -+ num = min(length, 16u); -+ p = line; -+ for (i = 0; i < num; ++i) { -+ if (i == 8) -+ *p++ = ' '; -+ sprintf(p, " %02x", buf[i]); -+ p += 3; -+ } -+ *p = 0; -+ DWC_PRINT("%6x: %s\n", start, line); -+ buf += num; -+ start += num; -+ length -= num; -+ } -+} -+#else -+static inline void dump_msg(const u8 *buf, unsigned int length) -+{ -+} -+#endif -+ -+/** -+ * This function writes a packet into the Tx FIFO associated with the -+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For -+ * periodic EPs the periodic Tx FIFO associated with the EP is written -+ * with all packets for the next micro-frame. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP to write packet for. -+ * @_dma: Indicates if DMA is being used. -+ */ -+void dwc_otg_ep_write_packet(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep, -+ int _dma) -+{ -+ /** -+ * The buffer is padded to DWORD on a per packet basis in -+ * slave/dma mode if the MPS is not DWORD aligned. The last -+ * packet, if short, is also padded to a multiple of DWORD. -+ * -+ * ep->xfer_buff always starts DWORD aligned in memory and is a -+ * multiple of DWORD in length -+ * -+ * ep->xfer_len can be any number of bytes -+ * -+ * ep->xfer_count is a multiple of ep->maxpacket until the last -+ * packet -+ * -+ * FIFO access is DWORD */ -+ -+ uint32_t i; -+ uint32_t byte_count; -+ uint32_t dword_count; -+ uint32_t *fifo; -+ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; -+ -+ if (ep->xfer_count >= ep->xfer_len) { -+ DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); -+ return; -+ } -+ -+ /* Find the byte length of the packet either short packet or MPS */ -+ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) -+ byte_count = ep->xfer_len - ep->xfer_count; -+ else -+ byte_count = ep->maxpacket; -+ -+ /* Find the DWORD length, padded by extra bytes as neccessary if MPS -+ * is not a multiple of DWORD */ -+ dword_count = (byte_count + 3) / 4; -+ -+#ifdef VERBOSE -+ dump_msg(ep->xfer_buff, byte_count); -+#endif -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) -+ /* -+ *@todo NGS Where are the Periodic Tx FIFO addresses -+ * intialized? What should this be? -+ */ -+ fifo = core_if->data_fifo[ep->tx_fifo_num]; -+ else -+ fifo = core_if->data_fifo[ep->num]; -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", -+ fifo, data_buff, *data_buff, byte_count); -+ -+ if (!_dma) { -+ for (i = 0; i < dword_count; i++, data_buff++) -+ dwc_write_reg32(fifo, *data_buff); -+ } -+ -+ ep->xfer_count += byte_count; -+ ep->xfer_buff += byte_count; -+} -+ -+/** -+ * Set the EP STALL. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP to set the stall on. -+ */ -+void dwc_otg_ep_set_stall(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) -+{ -+ union depctl_data depctl; -+ uint32_t *depctl_addr; -+ -+ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, -+ (ep->is_in ? "IN" : "OUT")); -+ -+ if (ep->is_in == 1) { -+ depctl_addr = -+ &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); -+ depctl.d32 = dwc_read_reg32(depctl_addr); -+ -+ /* set the disable and stall bits */ -+ if (depctl.b.epena) -+ depctl.b.epdis = 1; -+ depctl.b.stall = 1; -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ -+ } else { -+ depctl_addr = -+ &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); -+ depctl.d32 = dwc_read_reg32(depctl_addr); -+ -+ /* set the stall bit */ -+ depctl.b.stall = 1; -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ } -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); -+ return; -+} -+ -+/** -+ * Clear the EP STALL. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @ep: The EP to clear stall from. -+ */ -+void dwc_otg_ep_clear_stall(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) -+{ -+ union depctl_data depctl; -+ uint32_t *depctl_addr; -+ -+ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, -+ (ep->is_in ? "IN" : "OUT")); -+ -+ if (ep->is_in == 1) { -+ depctl_addr = -+ &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); -+ } else { -+ depctl_addr = -+ &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); -+ } -+ -+ depctl.d32 = dwc_read_reg32(depctl_addr); -+ -+ /* clear the stall bits */ -+ depctl.b.stall = 0; -+ -+ /* -+ * USB Spec 9.4.5: For endpoints using data toggle, regardless -+ * of whether an endpoint has the Halt feature set, a -+ * ClearFeature(ENDPOINT_HALT) request always results in the -+ * data toggle being reinitialized to DATA0. -+ */ -+ if (ep->type == DWC_OTG_EP_TYPE_INTR || -+ ep->type == DWC_OTG_EP_TYPE_BULK) { -+ depctl.b.setd0pid = 1; /* DATA0 */ -+ } -+ -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); -+ return; -+} -+ -+/** -+ * This function reads a packet from the Rx FIFO into the destination -+ * buffer. To read SETUP data use dwc_otg_read_setup_packet. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @dest: Destination buffer for the packet. -+ * @bytes: Number of bytes to copy to the destination. -+ */ -+void dwc_otg_read_packet(struct dwc_otg_core_if *core_if, -+ uint8_t *dest, uint16_t bytes) -+{ -+ int i; -+ int word_count = (bytes + 3) / 4; -+ -+ uint32_t *fifo = core_if->data_fifo[0]; -+ uint32_t *data_buff = (uint32_t *) dest; -+ -+ /** -+ * @todo Account for the case where dest is not dword aligned. This -+ * requires reading data from the FIFO into a uint32_t temp buffer, -+ * then moving it into the data buffer. -+ */ -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, -+ core_if, dest, bytes); -+ -+ for (i = 0; i < word_count; i++, data_buff++) -+ *data_buff = dwc_read_reg32(fifo); -+ return; -+} -+ -+/** -+ * This functions reads the device registers and prints them -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_dev_registers(struct dwc_otg_core_if *core_if) -+{ -+ int i; -+ uint32_t *addr; -+ -+ DWC_PRINT("Device Global Registers\n"); -+ addr = &core_if->dev_if->dev_global_regs->dcfg; -+ DWC_PRINT("DCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dctl; -+ DWC_PRINT("DCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dsts; -+ DWC_PRINT("DSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->diepmsk; -+ DWC_PRINT("DIEPMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->doepmsk; -+ DWC_PRINT("DOEPMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->daint; -+ DWC_PRINT("DAINT @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dtknqr1; -+ DWC_PRINT("DTKNQR1 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { -+ addr = &core_if->dev_if->dev_global_regs->dtknqr2; -+ DWC_PRINT("DTKNQR2 @%p : 0x%08X\n", -+ addr, dwc_read_reg32(addr)); -+ } -+ -+ addr = &core_if->dev_if->dev_global_regs->dvbusdis; -+ DWC_PRINT("DVBUSID @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ -+ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; -+ DWC_PRINT("DVBUSPULSE @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ -+ if (core_if->hwcfg2.b.dev_token_q_depth > 14) { -+ addr = &core_if->dev_if->dev_global_regs->dtknqr3; -+ DWC_PRINT("DTKNQR3 @%p : 0x%08X\n", -+ addr, dwc_read_reg32(addr)); -+ } -+ -+ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { -+ addr = &core_if->dev_if->dev_global_regs->dtknqr4; -+ DWC_PRINT("DTKNQR4 @%p : 0x%08X\n", -+ addr, dwc_read_reg32(addr)); -+ } -+ -+ for (i = 0; i < core_if->dev_if->num_eps; i++) { -+ DWC_PRINT("Device IN EP %d Registers\n", i); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; -+ DWC_PRINT("DIEPCTL @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepint; -+ DWC_PRINT("DIEPINT @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; -+ DWC_PRINT("DIETSIZ @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; -+ DWC_PRINT("DIEPDMA @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ -+ DWC_PRINT("Device OUT EP %d Registers\n", i); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; -+ DWC_PRINT("DOEPCTL @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepfn; -+ DWC_PRINT("DOEPFN @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepint; -+ DWC_PRINT("DOEPINT @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; -+ DWC_PRINT("DOETSIZ @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; -+ DWC_PRINT("DOEPDMA @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ } -+ return; -+} -+ -+/** -+ * This function reads the host registers and prints them -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_host_registers(struct dwc_otg_core_if *core_if) -+{ -+ int i; -+ uint32_t *addr; -+ -+ DWC_PRINT("Host Global Registers\n"); -+ addr = &core_if->host_if->host_global_regs->hcfg; -+ DWC_PRINT("HCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->hfir; -+ DWC_PRINT("HFIR @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->hfnum; -+ DWC_PRINT("HFNUM @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->hptxsts; -+ DWC_PRINT("HPTXSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->haint; -+ DWC_PRINT("HAINT @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->haintmsk; -+ DWC_PRINT("HAINTMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = core_if->host_if->hprt0; -+ DWC_PRINT("HPRT0 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ -+ for (i = 0; i < core_if->core_params->host_channels; i++) { -+ DWC_PRINT("Host Channel %d Specific Registers\n", i); -+ addr = &core_if->host_if->hc_regs[i]->hcchar; -+ DWC_PRINT("HCCHAR @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcsplt; -+ DWC_PRINT("HCSPLT @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcint; -+ DWC_PRINT("HCINT @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcintmsk; -+ DWC_PRINT("HCINTMSK @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hctsiz; -+ DWC_PRINT("HCTSIZ @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcdma; -+ DWC_PRINT("HCDMA @%p : 0x%08X\n", addr, -+ dwc_read_reg32(addr)); -+ -+ } -+ return; -+} -+ -+/** -+ * This function reads the core global registers and prints them -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_global_registers(struct dwc_otg_core_if *core_if) -+{ -+ int i; -+ uint32_t *addr; -+ -+ DWC_PRINT("Core Global Registers\n"); -+ addr = &core_if->core_global_regs->gotgctl; -+ DWC_PRINT("GOTGCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gotgint; -+ DWC_PRINT("GOTGINT @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gahbcfg; -+ DWC_PRINT("GAHBCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gusbcfg; -+ DWC_PRINT("GUSBCFG @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->grstctl; -+ DWC_PRINT("GRSTCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gintsts; -+ DWC_PRINT("GINTSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gintmsk; -+ DWC_PRINT("GINTMSK @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->grxstsr; -+ DWC_PRINT("GRXSTSR @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->grxfsiz; -+ DWC_PRINT("GRXFSIZ @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gnptxfsiz; -+ DWC_PRINT("GNPTXFSIZ @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gnptxsts; -+ DWC_PRINT("GNPTXSTS @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gi2cctl; -+ DWC_PRINT("GI2CCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gpvndctl; -+ DWC_PRINT("GPVNDCTL @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ggpio; -+ DWC_PRINT("GGPIO @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->guid; -+ DWC_PRINT("GUID @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gsnpsid; -+ DWC_PRINT("GSNPSID @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg1; -+ DWC_PRINT("GHWCFG1 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg2; -+ DWC_PRINT("GHWCFG2 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg3; -+ DWC_PRINT("GHWCFG3 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg4; -+ DWC_PRINT("GHWCFG4 @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->hptxfsiz; -+ DWC_PRINT("HPTXFSIZ @%p : 0x%08X\n", addr, dwc_read_reg32(addr)); -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { -+ addr = &core_if->core_global_regs->dptxfsiz[i]; -+ DWC_PRINT("DPTXFSIZ[%d] @%p : 0x%08X\n", i, addr, -+ dwc_read_reg32(addr)); -+ } -+ -+} -+ -+/** -+ * Flush a Tx FIFO. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @_num: Tx FIFO to flush. -+ */ -+extern void dwc_otg_flush_tx_fifo(struct dwc_otg_core_if *core_if, const int _num) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ union grstctl_data greset = {.d32 = 0 }; -+ int count = 0; -+ -+ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", _num); -+ -+ greset.b.txfflsh = 1; -+ greset.b.txfnum = _num; -+ dwc_write_reg32(&global_regs->grstctl, greset.d32); -+ -+ do { -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ if (++count > 10000) { -+ DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", -+ __func__, greset.d32, -+ dwc_read_reg32(&global_regs->gnptxsts)); -+ break; -+ } -+ -+ } while (greset.b.txfflsh == 1); -+ /* Wait for 3 PHY Clocks */ -+ udelay(1); -+} -+ -+/** -+ * Flush Rx FIFO. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+extern void dwc_otg_flush_rx_fifo(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ union grstctl_data greset = {.d32 = 0 }; -+ int count = 0; -+ -+ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); -+ /* -+ * -+ */ -+ greset.b.rxfflsh = 1; -+ dwc_write_reg32(&global_regs->grstctl, greset.d32); -+ -+ do { -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ if (++count > 10000) { -+ DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, -+ greset.d32); -+ break; -+ } -+ } while (greset.b.rxfflsh == 1); -+ /* Wait for 3 PHY Clocks */ -+ udelay(1); -+} -+ -+/** -+ * Do core a soft reset of the core. Be careful with this because it -+ * resets all the internal state machines of the core. -+ */ -+void dwc_otg_core_reset(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ union grstctl_data greset = {.d32 = 0 }; -+ int count = 0; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s\n", __func__); -+ /* Wait for AHB master IDLE state. */ -+ do { -+ udelay(10); -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ if (++count > 100000) { -+ DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, -+ greset.d32); -+ return; -+ } -+ } while (greset.b.ahbidle == 0); -+ -+ /* Core Soft Reset */ -+ count = 0; -+ greset.b.csftrst = 1; -+ dwc_write_reg32(&global_regs->grstctl, greset.d32); -+ do { -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ if (++count > 10000) { -+ DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", -+ __func__, greset.d32); -+ break; -+ } -+ } while (greset.b.csftrst == 1); -+ /* Wait for 3 PHY Clocks */ -+ mdelay(100); -+} -+ -+/** -+ * Register HCD callbacks. The callbacks are used to start and stop -+ * the HCD for interrupt processing. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @_cb: the HCD callback structure. -+ * @_p: pointer to be passed to callback function (usb_hcd*). -+ */ -+extern void dwc_otg_cil_register_hcd_callbacks(struct dwc_otg_core_if *core_if, -+ struct dwc_otg_cil_callbacks *_cb, -+ void *_p) -+{ -+ core_if->hcd_cb = _cb; -+ _cb->p = _p; -+} -+ -+/** -+ * Register PCD callbacks. The callbacks are used to start and stop -+ * the PCD for interrupt processing. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ * @_cb: the PCD callback structure. -+ * @_p: pointer to be passed to callback function (pcd*). -+ */ -+extern void dwc_otg_cil_register_pcd_callbacks(struct dwc_otg_core_if *core_if, -+ struct dwc_otg_cil_callbacks *_cb, -+ void *_p) -+{ -+ core_if->pcd_cb = _cb; -+ _cb->p = _p; -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -new file mode 100644 -index 0000000..36ef561 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -@@ -0,0 +1,866 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_CIL_H__) -+#define __DWC_CIL_H__ -+ -+#include "dwc_otg_plat.h" -+#include "dwc_otg_regs.h" -+#ifdef DEBUG -+#include "linux/timer.h" -+#endif -+ -+/* -+ * This file contains the interface to the Core Interface Layer. -+ */ -+ -+/** -+ * The dwc_ep structure represents the state of a single -+ * endpoint when acting in device mode. It contains the data items -+ * needed for an endpoint to be activated and transfer packets. -+ */ -+struct dwc_ep { -+ /** EP number used for register address lookup */ -+ uint8_t num; -+ /** EP direction 0 = OUT */ -+ unsigned is_in:1; -+ /** EP active. */ -+ unsigned active:1; -+ -+ /* -+ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use -+ * non-periodic Tx FIFO -+ */ -+ unsigned tx_fifo_num:4; -+ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ -+ unsigned type:2; -+#define DWC_OTG_EP_TYPE_CONTROL 0 -+#define DWC_OTG_EP_TYPE_ISOC 1 -+#define DWC_OTG_EP_TYPE_BULK 2 -+#define DWC_OTG_EP_TYPE_INTR 3 -+ -+ /** DATA start PID for INTR and BULK EP */ -+ unsigned data_pid_start:1; -+ /** Frame (even/odd) for ISOC EP */ -+ unsigned even_odd_frame:1; -+ /** Max Packet bytes */ -+ unsigned maxpacket:11; -+ -+ /** @name Transfer state */ -+ /** @{ */ -+ -+ /** -+ * Pointer to the beginning of the transfer buffer -- do not modify -+ * during transfer. -+ */ -+ -+ uint32_t dma_addr; -+ -+ uint8_t *start_xfer_buff; -+ /** pointer to the transfer buffer */ -+ uint8_t *xfer_buff; -+ /** Number of bytes to transfer */ -+ unsigned xfer_len:19; -+ /** Number of bytes transferred. */ -+ unsigned xfer_count:19; -+ /** Sent ZLP */ -+ unsigned sent_zlp:1; -+ /** Total len for control transfer */ -+ unsigned total_len:19; -+ -+ /** @} */ -+}; -+ -+/* -+ * Reasons for halting a host channel. -+ */ -+enum dwc_otg_halt_status { -+ DWC_OTG_HC_XFER_NO_HALT_STATUS, -+ DWC_OTG_HC_XFER_COMPLETE, -+ DWC_OTG_HC_XFER_URB_COMPLETE, -+ DWC_OTG_HC_XFER_ACK, -+ DWC_OTG_HC_XFER_NAK, -+ DWC_OTG_HC_XFER_NYET, -+ DWC_OTG_HC_XFER_STALL, -+ DWC_OTG_HC_XFER_XACT_ERR, -+ DWC_OTG_HC_XFER_FRAME_OVERRUN, -+ DWC_OTG_HC_XFER_BABBLE_ERR, -+ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR, -+ DWC_OTG_HC_XFER_AHB_ERR, -+ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, -+ DWC_OTG_HC_XFER_URB_DEQUEUE -+}; -+ -+/** -+ * Host channel descriptor. This structure represents the state of a single -+ * host channel when acting in host mode. It contains the data items needed to -+ * transfer packets to an endpoint via a host channel. -+ */ -+struct dwc_hc { -+ /** Host channel number used for register address lookup */ -+ uint8_t hc_num; -+ -+ /** Device to access */ -+ unsigned dev_addr:7; -+ -+ /** EP to access */ -+ unsigned ep_num:4; -+ -+ /** EP direction. 0: OUT, 1: IN */ -+ unsigned ep_is_in:1; -+ -+ /** -+ * EP speed. -+ * One of the following values: -+ * - DWC_OTG_EP_SPEED_LOW -+ * - DWC_OTG_EP_SPEED_FULL -+ * - DWC_OTG_EP_SPEED_HIGH -+ */ -+ unsigned speed:2; -+#define DWC_OTG_EP_SPEED_LOW 0 -+#define DWC_OTG_EP_SPEED_FULL 1 -+#define DWC_OTG_EP_SPEED_HIGH 2 -+ -+ /** -+ * Endpoint type. -+ * One of the following values: -+ * - DWC_OTG_EP_TYPE_CONTROL: 0 -+ * - DWC_OTG_EP_TYPE_ISOC: 1 -+ * - DWC_OTG_EP_TYPE_BULK: 2 -+ * - DWC_OTG_EP_TYPE_INTR: 3 -+ */ -+ unsigned ep_type:2; -+ -+ /** Max packet size in bytes */ -+ unsigned max_packet:11; -+ -+ /** -+ * PID for initial transaction. -+ * 0: DATA0,
-+ * 1: DATA2,
-+ * 2: DATA1,
-+ * 3: MDATA (non-Control EP), -+ * SETUP (Control EP) -+ */ -+ unsigned data_pid_start:2; -+#define DWC_OTG_HC_PID_DATA0 0 -+#define DWC_OTG_HC_PID_DATA2 1 -+#define DWC_OTG_HC_PID_DATA1 2 -+#define DWC_OTG_HC_PID_MDATA 3 -+#define DWC_OTG_HC_PID_SETUP 3 -+ -+ /** Number of periodic transactions per (micro)frame */ -+ unsigned multi_count:2; -+ -+ /** @name Transfer State */ -+ /** @{ */ -+ -+ /** Pointer to the current transfer buffer position. */ -+ uint8_t *xfer_buff; -+ /** Total number of bytes to transfer. */ -+ uint32_t xfer_len; -+ /** Number of bytes transferred so far. */ -+ uint32_t xfer_count; -+ /** Packet count at start of transfer.*/ -+ uint16_t start_pkt_count; -+ -+ /** -+ * Flag to indicate whether the transfer has been started. Set to 1 if -+ * it has been started, 0 otherwise. -+ */ -+ uint8_t xfer_started; -+ -+ /** -+ * Set to 1 to indicate that a PING request should be issued on this -+ * channel. If 0, process normally. -+ */ -+ uint8_t do_ping; -+ -+ /** -+ * Set to 1 to indicate that the error count for this transaction is -+ * non-zero. Set to 0 if the error count is 0. -+ */ -+ uint8_t error_state; -+ -+ /** -+ * Set to 1 to indicate that this channel should be halted the next -+ * time a request is queued for the channel. This is necessary in -+ * slave mode if no request queue space is available when an attempt -+ * is made to halt the channel. -+ */ -+ uint8_t halt_on_queue; -+ -+ /** -+ * Set to 1 if the host channel has been halted, but the core is not -+ * finished flushing queued requests. Otherwise 0. -+ */ -+ uint8_t halt_pending; -+ -+ /** -+ * Reason for halting the host channel. -+ */ -+ enum dwc_otg_halt_status halt_status; -+ -+ /* -+ * Split settings for the host channel -+ */ -+ uint8_t do_split; /**< Enable split for the channel */ -+ uint8_t complete_split; /**< Enable complete split */ -+ uint8_t hub_addr; /**< Address of high speed hub */ -+ -+ uint8_t port_addr; /**< Port of the low/full speed device */ -+ /** Split transaction position -+ * One of the following values: -+ * - DWC_HCSPLIT_XACTPOS_MID -+ * - DWC_HCSPLIT_XACTPOS_BEGIN -+ * - DWC_HCSPLIT_XACTPOS_END -+ * - DWC_HCSPLIT_XACTPOS_ALL */ -+ uint8_t xact_pos; -+ -+ /** Set when the host channel does a short read. */ -+ uint8_t short_read; -+ -+ /** -+ * Number of requests issued for this channel since it was assigned to -+ * the current transfer (not counting PINGs). -+ */ -+ uint8_t requests; -+ -+ /** -+ * Queue Head for the transfer being processed by this channel. -+ */ -+ struct dwc_otg_qh *qh; -+ -+ /** @} */ -+ -+ /** Entry in list of host channels. */ -+ struct list_head hc_list_entry; -+}; -+ -+/** -+ * The following parameters may be specified when starting the module. These -+ * parameters define how the DWC_otg controller should be configured. -+ * Parameter values are passed to the CIL initialization function -+ * dwc_otg_cil_init. -+ */ -+struct dwc_otg_core_params { -+ int32_t opt; -+#define dwc_param_opt_default 1 -+ -+ /* -+ * Specifies the OTG capabilities. The driver will automatically -+ * detect the value for this parameter if none is specified. -+ * 0 - HNP and SRP capable (default) -+ * 1 - SRP Only capable -+ * 2 - No HNP/SRP capable -+ */ -+ int32_t otg_cap; -+#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0 -+#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1 -+#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 -+#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE -+ -+ /* -+ * Specifies whether to use slave or DMA mode for accessing the data -+ * FIFOs. The driver will automatically detect the value for this -+ * parameter if none is specified. -+ * 0 - Slave -+ * 1 - DMA (default, if available) -+ */ -+ int32_t dma_enable; -+#define dwc_param_dma_enable_default 1 -+ -+ /* -+ * The DMA Burst size (applicable only for External DMA -+ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) -+ */ -+ int32_t dma_burst_size; /* Translate this to GAHBCFG values */ -+#define dwc_param_dma_burst_size_default 32 -+ -+ /* -+ * Specifies the maximum speed of operation in host and device mode. -+ * The actual speed depends on the speed of the attached device and -+ * the value of phy_type. The actual speed depends on the speed of the -+ * attached device. -+ * 0 - High Speed (default) -+ * 1 - Full Speed -+ */ -+ int32_t speed; -+#define dwc_param_speed_default 0 -+#define DWC_SPEED_PARAM_HIGH 0 -+#define DWC_SPEED_PARAM_FULL 1 -+ -+ /** Specifies whether low power mode is supported when attached -+ * to a Full Speed or Low Speed device in host mode. -+ * 0 - Don't support low power mode (default) -+ * 1 - Support low power mode -+ */ -+ int32_t host_support_fs_ls_low_power; -+#define dwc_param_host_support_fs_ls_low_power_default 0 -+ -+ /** Specifies the PHY clock rate in low power mode when connected to a -+ * Low Speed device in host mode. This parameter is applicable only if -+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS -+ * then defaults to 6 MHZ otherwise 48 MHZ. -+ * -+ * 0 - 48 MHz -+ * 1 - 6 MHz -+ */ -+ int32_t host_ls_low_power_phy_clk; -+#define dwc_param_host_ls_low_power_phy_clk_default 0 -+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 -+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 -+ -+ /** -+ * 0 - Use cC FIFO size parameters -+ * 1 - Allow dynamic FIFO sizing (default) -+ */ -+ int32_t enable_dynamic_fifo; -+#define dwc_param_enable_dynamic_fifo_default 1 -+ -+ /** Total number of 4-byte words in the data FIFO memory. This -+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic -+ * Tx FIFOs. -+ * 32 to 32768 (default 8192) -+ * Note: The total FIFO memory depth in the FPGA configuration is 8192. -+ */ -+ int32_t data_fifo_size; -+#define dwc_param_data_fifo_size_default 8192 -+ -+ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic -+ * FIFO sizing is enabled. -+ * 16 to 32768 (default 1064) -+ */ -+ int32_t dev_rx_fifo_size; -+#define dwc_param_dev_rx_fifo_size_default 1064 -+ -+ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode -+ * when dynamic FIFO sizing is enabled. -+ * 16 to 32768 (default 1024) -+ */ -+ int32_t dev_nperio_tx_fifo_size; -+#define dwc_param_dev_nperio_tx_fifo_size_default 1024 -+ -+ /** Number of 4-byte words in each of the periodic Tx FIFOs in device -+ * mode when dynamic FIFO sizing is enabled. -+ * 4 to 768 (default 256) -+ */ -+ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; -+#define dwc_param_dev_perio_tx_fifo_size_default 256 -+ -+ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic -+ * FIFO sizing is enabled. -+ * 16 to 32768 (default 1024) -+ */ -+ int32_t host_rx_fifo_size; -+#define dwc_param_host_rx_fifo_size_default 1024 -+#define dwc_param_host_rx_fifo_size_percentage 30 -+ -+ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode -+ * when Dynamic FIFO sizing is enabled in the core. -+ * 16 to 32768 (default 1024) -+ */ -+ int32_t host_nperio_tx_fifo_size; -+#define dwc_param_host_nperio_tx_fifo_size_default 1024 -+#define dwc_param_host_nperio_tx_fifo_size_percentage 40 -+ -+ /* -+ * Number of 4-byte words in the host periodic Tx FIFO when dynamic -+ * FIFO sizing is enabled. -+ * 16 to 32768 (default 1024) -+ */ -+ int32_t host_perio_tx_fifo_size; -+#define dwc_param_host_perio_tx_fifo_size_default 1024 -+#define dwc_param_host_perio_tx_fifo_size_percentage 30 -+ -+ /* -+ * The maximum transfer size supported in bytes. -+ * 2047 to 65,535 (default 65,535) -+ */ -+ int32_t max_transfer_size; -+#define dwc_param_max_transfer_size_default 65535 -+ -+ /* -+ * The maximum number of packets in a transfer. -+ * 15 to 511 (default 511) -+ */ -+ int32_t max_packet_count; -+#define dwc_param_max_packet_count_default 511 -+ -+ /* -+ * The number of host channel registers to use. -+ * 1 to 16 (default 12) -+ * Note: The FPGA configuration supports a maximum of 12 host channels. -+ */ -+ int32_t host_channels; -+#define dwc_param_host_channels_default 12 -+ -+ /* -+ * The number of endpoints in addition to EP0 available for device -+ * mode operations. -+ * 1 to 15 (default 6 IN and OUT) -+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT -+ * endpoints in addition to EP0. -+ */ -+ int32_t dev_endpoints; -+#define dwc_param_dev_endpoints_default 6 -+ -+ /* -+ * Specifies the type of PHY interface to use. By default, the driver -+ * will automatically detect the phy_type. -+ * -+ * 0 - Full Speed PHY -+ * 1 - UTMI+ (default) -+ * 2 - ULPI -+ */ -+ int32_t phy_type; -+#define DWC_PHY_TYPE_PARAM_FS 0 -+#define DWC_PHY_TYPE_PARAM_UTMI 1 -+#define DWC_PHY_TYPE_PARAM_ULPI 2 -+#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI -+ -+ /* -+ * Specifies the UTMI+ Data Width. This parameter is -+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI -+ * PHY_TYPE, this parameter indicates the data width between -+ * the MAC and the ULPI Wrapper.) Also, this parameter is -+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set -+ * to "8 and 16 bits", meaning that the core has been -+ * configured to work at either data path width. -+ * -+ * 8 or 16 bits (default 16) -+ */ -+ int32_t phy_utmi_width; -+#define dwc_param_phy_utmi_width_default 16 -+ -+ /* -+ * Specifies whether the ULPI operates at double or single -+ * data rate. This parameter is only applicable if PHY_TYPE is -+ * ULPI. -+ * -+ * 0 - single data rate ULPI interface with 8 bit wide data -+ * bus (default) -+ * 1 - double data rate ULPI interface with 4 bit wide data -+ * bus -+ */ -+ int32_t phy_ulpi_ddr; -+#define dwc_param_phy_ulpi_ddr_default 0 -+ -+ /* -+ * Specifies whether to use the internal or external supply to -+ * drive the vbus with a ULPI phy. -+ */ -+ int32_t phy_ulpi_ext_vbus; -+#define DWC_PHY_ULPI_INTERNAL_VBUS 0 -+#define DWC_PHY_ULPI_EXTERNAL_VBUS 1 -+#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS -+ -+ /* -+ * Specifies whether to use the I2Cinterface for full speed PHY. This -+ * parameter is only applicable if PHY_TYPE is FS. -+ * 0 - No (default) -+ * 1 - Yes -+ */ -+ int32_t i2c_enable; -+#define dwc_param_i2c_enable_default 0 -+ -+ int32_t ulpi_fs_ls; -+#define dwc_param_ulpi_fs_ls_default 0 -+ -+ int32_t ts_dline; -+#define dwc_param_ts_dline_default 0 -+ -+}; -+ -+/** -+ * The FIFOs are established based on a default percentage of the total -+ * FIFO depth. This check insures that the defaults are reasonable. -+ */ -+#if (((dwc_param_host_rx_fifo_size_percentage) \ -+ +(dwc_param_host_nperio_tx_fifo_size_percentage) \ -+ +(dwc_param_host_perio_tx_fifo_size_percentage)) > 100) -+#error Invalid FIFO allocation -+#endif -+ -+#ifdef DEBUG -+struct dwc_otg_core_if; -+struct hc_xfer_info { -+ struct dwc_otg_core_if *core_if; -+ struct dwc_hc *hc; -+}; -+#endif -+ -+/* -+ * The dwc_otg_core_if structure contains information -+ * needed to manage the DWC_otg controller acting in either host or -+ * device mode. It represents the programming view of the controller -+ * as a whole. -+ */ -+struct dwc_otg_core_if { -+ /** USB block index number for Octeon's that support multiple */ -+ int usb_num; -+ -+ /** Parameters that define how the core should be configured.*/ -+ struct dwc_otg_core_params *core_params; -+ -+ /** Core Global registers starting at offset 000h. */ -+ struct dwc_otg_core_global_regs *core_global_regs; -+ -+ /** Device-specific information */ -+ struct dwc_otg_dev_if *dev_if; -+ /** Host-specific information */ -+ struct dwc_otg_host_if *host_if; -+ -+ /* -+ * Set to 1 if the core PHY interface bits in USBCFG have been -+ * initialized. -+ */ -+ uint8_t phy_init_done; -+ -+ /* -+ * SRP Success flag, set by srp success interrupt in FS I2C mode -+ */ -+ uint8_t srp_success; -+ uint8_t srp_timer_started; -+ -+ /* Common configuration information */ -+ /** Power and Clock Gating Control Register */ -+ uint32_t *pcgcctl; -+#define DWC_OTG_PCGCCTL_OFFSET 0xE00 -+ -+ /** Push/pop addresses for endpoints or host channels.*/ -+ uint32_t *data_fifo[MAX_EPS_CHANNELS]; -+#define DWC_OTG_DATA_FIFO_OFFSET 0x1000 -+#define DWC_OTG_DATA_FIFO_SIZE 0x1000 -+ -+ /** Total RAM for FIFOs (Bytes) */ -+ uint16_t total_fifo_size; -+ /** Size of Rx FIFO (Bytes) */ -+ uint16_t rx_fifo_size; -+ /** Size of Non-periodic Tx FIFO (Bytes) */ -+ uint16_t nperio_tx_fifo_size; -+ -+ /** 1 if DMA is enabled, 0 otherwise. */ -+ uint8_t dma_enable; -+ -+ /** Set to 1 if multiple packets of a high-bandwidth transfer is in -+ * process of being queued */ -+ uint8_t queuing_high_bandwidth; -+ -+ /** Hardware Configuration -- stored here for convenience.*/ -+ union hwcfg1_data hwcfg1; -+ union hwcfg2_data hwcfg2; -+ union hwcfg3_data hwcfg3; -+ union hwcfg4_data hwcfg4; -+ -+ /* -+ * The operational State, during transations -+ * (a_host>>a_peripherial and b_device=>b_host) this may not -+ * match the core but allows the software to determine -+ * transitions. -+ */ -+ uint8_t op_state; -+ -+ /* -+ * Set to 1 if the HCD needs to be restarted on a session request -+ * interrupt. This is required if no connector ID status change has -+ * occurred since the HCD was last disconnected. -+ */ -+ uint8_t restart_hcd_on_session_req; -+ -+ /** HCD callbacks */ -+ /** A-Device is a_host */ -+#define A_HOST (1) -+ /** A-Device is a_suspend */ -+#define A_SUSPEND (2) -+ /** A-Device is a_peripherial */ -+#define A_PERIPHERAL (3) -+ /** B-Device is operating as a Peripheral. */ -+#define B_PERIPHERAL (4) -+ /** B-Device is operating as a Host. */ -+#define B_HOST (5) -+ -+ /** HCD callbacks */ -+ struct dwc_otg_cil_callbacks *hcd_cb; -+ /** PCD callbacks */ -+ struct dwc_otg_cil_callbacks *pcd_cb; -+ -+#ifdef DEBUG -+ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; -+ -+ struct hc_xfer_info hc_xfer_info[MAX_EPS_CHANNELS]; -+ struct timer_list hc_xfer_timer[MAX_EPS_CHANNELS]; -+ -+ uint32_t hfnum_7_samples; -+ uint64_t hfnum_7_frrem_accum; -+ uint32_t hfnum_0_samples; -+ uint64_t hfnum_0_frrem_accum; -+ uint32_t hfnum_other_samples; -+ uint64_t hfnum_other_frrem_accum; -+#endif -+ -+}; -+ -+/* -+ * The following functions support initialization of the CIL driver component -+ * and the DWC_otg controller. -+ */ -+extern struct dwc_otg_core_if *dwc_otg_cil_init(const uint32_t *reg_base_addr, -+ struct dwc_otg_core_params * -+ _core_params); -+extern void dwc_otg_cil_remove(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_core_init(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_core_host_init(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_core_dev_init(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_enable_global_interrupts(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_disable_global_interrupts(struct dwc_otg_core_if *core_if); -+ -+/* Device CIL Functions -+ * The following functions support managing the DWC_otg controller in device -+ * mode. -+ */ -+ -+extern void dwc_otg_wakeup(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_read_setup_packet(struct dwc_otg_core_if *core_if, -+ uint32_t *dest); -+extern uint32_t dwc_otg_get_frame_number(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_ep0_activate(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep_activate(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep_deactivate(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep_start_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep0_start_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep0_continue_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep_write_packet(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep, int _dma); -+extern void dwc_otg_ep_set_stall(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_ep_clear_stall(struct dwc_otg_core_if *core_if, -+ struct dwc_ep *ep); -+extern void dwc_otg_enable_device_interrupts(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_dump_dev_registers(struct dwc_otg_core_if *core_if); -+ -+/* Host CIL Functions -+ * The following functions support managing the DWC_otg controller in host -+ * mode. -+ */ -+ -+extern void dwc_otg_hc_init(struct dwc_otg_core_if *core_if, struct dwc_hc *hc); -+extern void dwc_otg_hc_halt(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc, -+ enum dwc_otg_halt_status halt_status); -+extern void dwc_otg_hc_cleanup(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc); -+extern void dwc_otg_hc_start_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc); -+extern int dwc_otg_hc_continue_transfer(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc); -+extern void dwc_otg_hc_do_ping(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc); -+extern void dwc_otg_hc_write_packet(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc); -+extern void dwc_otg_enable_host_interrupts(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_disable_host_interrupts(struct dwc_otg_core_if *core_if); -+ -+/** -+ * This function Reads HPRT0 in preparation to modify. It keeps the -+ * WC bits 0 so that if they are read as 1, they won't clear when you -+ * write it back -+ */ -+static inline uint32_t dwc_otg_read_hprt0(struct dwc_otg_core_if *core_if) -+{ -+ union hprt0_data hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); -+ hprt0.b.prtena = 0; -+ hprt0.b.prtconndet = 0; -+ hprt0.b.prtenchng = 0; -+ hprt0.b.prtovrcurrchng = 0; -+ return hprt0.d32; -+} -+ -+extern void dwc_otg_dump_host_registers(struct dwc_otg_core_if *core_if); -+ -+/* Common CIL Functions -+ * The following functions support managing the DWC_otg controller in either -+ * device or host mode. -+ */ -+ -+ -+extern void dwc_otg_read_packet(struct dwc_otg_core_if *core_if, -+ uint8_t *dest, uint16_t bytes); -+ -+extern void dwc_otg_dump_global_registers(struct dwc_otg_core_if *core_if); -+ -+extern void dwc_otg_flush_tx_fifo(struct dwc_otg_core_if *core_if, -+ const int _num); -+extern void dwc_otg_flush_rx_fifo(struct dwc_otg_core_if *core_if); -+extern void dwc_otg_core_reset(struct dwc_otg_core_if *core_if); -+ -+/** -+ * This function returns the Core Interrupt register. -+ */ -+static inline uint32_t dwc_otg_read_core_intr(struct dwc_otg_core_if *core_if) -+{ -+ return dwc_read_reg32(&core_if->core_global_regs->gintsts) & -+ dwc_read_reg32(&core_if->core_global_regs->gintmsk); -+} -+ -+/** -+ * This function returns the OTG Interrupt register. -+ */ -+static inline uint32_t dwc_otg_read_otg_intr(struct dwc_otg_core_if *core_if) -+{ -+ return dwc_read_reg32(&core_if->core_global_regs->gotgint); -+} -+ -+/** -+ * This function reads the Device All Endpoints Interrupt register and -+ * returns the IN endpoint interrupt bits. -+ */ -+static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(struct dwc_otg_core_if * -+ core_if) -+{ -+ uint32_t v; -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); -+ return v & 0xffff; -+ -+} -+ -+/** -+ * This function reads the Device All Endpoints Interrupt register and -+ * returns the OUT endpoint interrupt bits. -+ */ -+static inline uint32_t -+dwc_otg_read_dev_all_out_ep_intr(struct dwc_otg_core_if *core_if) -+{ -+ uint32_t v; -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); -+ return (v & 0xffff0000) >> 16; -+} -+ -+/** -+ * This function returns the Device IN EP Interrupt register -+ */ -+static inline uint32_t -+dwc_otg_read_dev_in_ep_intr(struct dwc_otg_core_if *core_if, struct dwc_ep *ep) -+{ -+ struct dwc_otg_dev_if *dev_if = core_if->dev_if; -+ uint32_t v; -+ v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & -+ dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); -+ return v; -+} -+ -+/** -+ * This function returns the Device OUT EP Interrupt register -+ */ -+static inline uint32_t dwc_otg_read_dev_out_ep_intr(struct dwc_otg_core_if * -+ core_if, struct dwc_ep *ep) -+{ -+ struct dwc_otg_dev_if *dev_if = core_if->dev_if; -+ uint32_t v; -+ v = dwc_read_reg32(&dev_if->out_ep_regs[ep->num]->doepint) & -+ dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); -+ return v; -+} -+ -+/** -+ * This function returns the Host All Channel Interrupt register -+ */ -+static inline uint32_t -+dwc_otg_read_host_all_channels_intr(struct dwc_otg_core_if *core_if) -+{ -+ return dwc_read_reg32(&core_if->host_if->host_global_regs->haint); -+} -+ -+static inline uint32_t -+dwc_otg_read_host_channel_intr(struct dwc_otg_core_if *core_if, -+ struct dwc_hc *hc) -+{ -+ return dwc_read_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcint); -+} -+ -+/** -+ * This function returns the mode of the operation, host or device. -+ * -+ * Returns 0 - Device Mode, 1 - Host Mode -+ */ -+static inline uint32_t dwc_otg_mode(struct dwc_otg_core_if *core_if) -+{ -+ return dwc_read_reg32(&core_if->core_global_regs->gintsts) & 0x1; -+} -+ -+static inline uint8_t dwc_otg_is_device_mode(struct dwc_otg_core_if *core_if) -+{ -+ return dwc_otg_mode(core_if) != DWC_HOST_MODE; -+} -+ -+static inline uint8_t dwc_otg_is_host_mode(struct dwc_otg_core_if *core_if) -+{ -+ return dwc_otg_mode(core_if) == DWC_HOST_MODE; -+} -+ -+extern int32_t dwc_otg_handle_common_intr(struct dwc_otg_core_if *core_if); -+ -+/* -+ * DWC_otg CIL callback structure. This structure allows the HCD and -+ * PCD to register functions used for starting and stopping the PCD -+ * and HCD for role change on for a DRD. -+ */ -+struct dwc_otg_cil_callbacks { -+ /* Start function for role change */ -+ int (*start) (void *p); -+ /* Stop Function for role change */ -+ int (*stop) (void *p); -+ /* Disconnect Function for role change */ -+ int (*disconnect) (void *p); -+ /* Resume/Remote wakeup Function */ -+ int (*resume_wakeup) (void *p); -+ /* Suspend function */ -+ int (*suspend) (void *p); -+ /* Session Start (SRP) */ -+ int (*session_start) (void *p); -+ /* Pointer passed to start() and stop() */ -+ void *p; -+}; -+ -+extern void dwc_otg_cil_register_pcd_callbacks(struct dwc_otg_core_if *core_if, -+ struct dwc_otg_cil_callbacks *cb, -+ void *p); -+extern void dwc_otg_cil_register_hcd_callbacks(struct dwc_otg_core_if *core_if, -+ struct dwc_otg_cil_callbacks *cb, -+ void *p); -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -new file mode 100644 -index 0000000..38c46df ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -@@ -0,0 +1,689 @@ -+/* ========================================================================== -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+/** -+ * -+ * The Core Interface Layer provides basic services for accessing and -+ * managing the DWC_otg hardware. These services are used by both the -+ * Host Controller Driver and the Peripheral Controller Driver. -+ * -+ * This file contains the Common Interrupt handlers. -+ */ -+#include "dwc_otg_plat.h" -+#include "dwc_otg_regs.h" -+#include "dwc_otg_cil.h" -+ -+#ifdef DEBUG -+inline const char *op_state_str(struct dwc_otg_core_if *core_if) -+{ -+ return (core_if->op_state == A_HOST ? "a_host" : -+ (core_if->op_state == A_SUSPEND ? "a_suspend" : -+ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : -+ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : -+ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); -+} -+#endif -+ -+/** This function will log a debug message -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_mode_mismatch_intr(struct dwc_otg_core_if *core_if) -+{ -+ union gintsts_data gintsts; -+ DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", -+ dwc_otg_mode(core_if) ? "Host" : "Device"); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.modemismatch = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ return 1; -+} -+ -+/** Start the HCD. Helper function for using the HCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void hcd_start(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->start) -+ core_if->hcd_cb->start(core_if->hcd_cb->p); -+} -+ -+/** Stop the HCD. Helper function for using the HCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void hcd_stop(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->stop) -+ core_if->hcd_cb->stop(core_if->hcd_cb->p); -+} -+ -+/** Disconnect the HCD. Helper function for using the HCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void hcd_disconnect(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) -+ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); -+} -+ -+/** Inform the HCD the a New Session has begun. Helper function for -+ * using the HCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void hcd_session_start(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->session_start) -+ core_if->hcd_cb->session_start(core_if->hcd_cb->p); -+} -+ -+/** Start the PCD. Helper function for using the PCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void pcd_start(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->start) -+ core_if->pcd_cb->start(core_if->pcd_cb->p); -+} -+ -+/** Stop the PCD. Helper function for using the PCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void pcd_stop(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->stop) -+ core_if->pcd_cb->stop(core_if->pcd_cb->p); -+} -+ -+/** Suspend the PCD. Helper function for using the PCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void pcd_suspend(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->suspend) -+ core_if->pcd_cb->suspend(core_if->pcd_cb->p); -+} -+ -+/** Resume the PCD. Helper function for using the PCD callbacks. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+static inline void pcd_resume(struct dwc_otg_core_if *core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); -+} -+ -+/** -+ * This function handles the OTG Interrupts. It reads the OTG -+ * Interrupt Register (GOTGINT) to determine what interrupt has -+ * occurred. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_otg_intr(struct dwc_otg_core_if *core_if) -+{ -+ struct dwc_otg_core_global_regs *global_regs = core_if->core_global_regs; -+ union gotgint_data gotgint; -+ union gotgctl_data gotgctl; -+ union gintmsk_data gintmsk; -+ -+ gotgint.d32 = dwc_read_reg32(&global_regs->gotgint); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, -+ op_state_str(core_if)); -+ -+ if (gotgint.b.sesenddet) { -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "Session End Detected++ (%s)\n", -+ op_state_str(core_if)); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ -+ if (core_if->op_state == B_HOST) { -+ pcd_start(core_if); -+ core_if->op_state = B_PERIPHERAL; -+ } else { -+ /* If not B_HOST and Device HNP still set. HNP -+ * Did not succeed!*/ -+ if (gotgctl.b.devhnpen) { -+ DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); -+ DWC_ERROR("Device Not Connected/Responding!\n"); -+ } -+ -+ /* If Session End Detected the B-Cable has -+ * been disconnected. */ -+ /* Reset PCD and Gadget driver to a -+ * clean state. */ -+ pcd_stop(core_if); -+ } -+ gotgctl.d32 = 0; -+ gotgctl.b.devhnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ } -+ if (gotgint.b.sesreqsucstschng) { -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "Session Reqeust Success Status Change++\n"); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ if (gotgctl.b.sesreqscs) { -+ if ((core_if->core_params->phy_type == -+ DWC_PHY_TYPE_PARAM_FS) -+ && (core_if->core_params->i2c_enable)) { -+ core_if->srp_success = 1; -+ } else { -+ pcd_resume(core_if); -+ /* Clear Session Request */ -+ gotgctl.d32 = 0; -+ gotgctl.b.sesreq = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, -+ gotgctl.d32, 0); -+ } -+ } -+ } -+ if (gotgint.b.hstnegsucstschng) { -+ /* Print statements during the HNP interrupt handling -+ * can cause it to fail.*/ -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ if (gotgctl.b.hstnegscs) { -+ if (dwc_otg_is_host_mode(core_if)) { -+ core_if->op_state = B_HOST; -+ /* -+ * Need to disable SOF interrupt immediately. -+ * When switching from device to host, the PCD -+ * interrupt handler won't handle the -+ * interrupt if host mode is already set. The -+ * HCD interrupt handler won't get called if -+ * the HCD state is HALT. This means that the -+ * interrupt does not get handled and Linux -+ * complains loudly. -+ */ -+ gintmsk.d32 = 0; -+ gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, -+ gintmsk.d32, 0); -+ pcd_stop(core_if); -+ /* -+ * Initialize the Core for Host mode. -+ */ -+ hcd_start(core_if); -+ core_if->op_state = B_HOST; -+ } -+ } else { -+ gotgctl.d32 = 0; -+ gotgctl.b.hnpreq = 1; -+ gotgctl.b.devhnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); -+ DWC_ERROR("Device Not Connected/Responding\n"); -+ } -+ } -+ if (gotgint.b.hstnegdet) { -+ /* The disconnect interrupt is set at the same time as -+ * Host Negotiation Detected. During the mode -+ * switch all interrupts are cleared so the disconnect -+ * interrupt handler will not get executed. -+ */ -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "Host Negotiation Detected++ (%s)\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : -+ "Device")); -+ if (dwc_otg_is_device_mode(core_if)) { -+ DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", -+ core_if->op_state); -+ hcd_disconnect(core_if); -+ pcd_start(core_if); -+ core_if->op_state = A_PERIPHERAL; -+ } else { -+ /* -+ * Need to disable SOF interrupt immediately. When -+ * switching from device to host, the PCD interrupt -+ * handler won't handle the interrupt if host mode is -+ * already set. The HCD interrupt handler won't get -+ * called if the HCD state is HALT. This means that -+ * the interrupt does not get handled and Linux -+ * complains loudly. -+ */ -+ gintmsk.d32 = 0; -+ gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); -+ pcd_stop(core_if); -+ hcd_start(core_if); -+ core_if->op_state = A_HOST; -+ } -+ } -+ if (gotgint.b.adevtoutchng) -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "A-Device Timeout Change++\n"); -+ if (gotgint.b.debdone) -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); -+ -+ /* Clear GOTGINT */ -+ dwc_write_reg32(&core_if->core_global_regs->gotgint, gotgint.d32); -+ -+ return 1; -+} -+ -+/** -+ * This function handles the Connector ID Status Change Interrupt. It -+ * reads the OTG Interrupt Register (GOTCTL) to determine whether this -+ * is a Device to Host Mode transition or a Host Mode to Device -+ * Transition. -+ * -+ * This only occurs when the cable is connected/removed from the PHY -+ * connector. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_conn_id_status_change_intr(struct dwc_otg_core_if *core_if) -+{ -+ uint32_t count = 0; -+ -+ union gintsts_data gintsts = {.d32 = 0 }; -+ union gintmsk_data gintmsk = {.d32 = 0 }; -+ union gotgctl_data gotgctl = {.d32 = 0 }; -+ -+ /* -+ * Need to disable SOF interrupt immediately. If switching from device -+ * to host, the PCD interrupt handler won't handle the interrupt if -+ * host mode is already set. The HCD interrupt handler won't get -+ * called if the HCD state is HALT. This means that the interrupt does -+ * not get handled and Linux complains loudly. -+ */ -+ gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); -+ -+ DWC_DEBUGPL(DBG_CIL, -+ " ++Connector ID Status Change Interrupt++ (%s)\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); -+ gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); -+ DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); -+ -+ /* B-Device connector (Device Mode) */ -+ if (gotgctl.b.conidsts) { -+ /* Wait for switch to device mode. */ -+ while (!dwc_otg_is_device_mode(core_if)) { -+ DWC_PRINT("Waiting for Peripheral Mode, Mode=%s\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : -+ "Peripheral")); -+ mdelay(100); -+ if (++count > 10000) -+ *(uint32_t *) NULL = 0; -+ } -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ pcd_start(core_if); -+ } else { -+ /* A-Device connector (Host Mode) */ -+ while (!dwc_otg_is_host_mode(core_if)) { -+ DWC_PRINT("Waiting for Host Mode, Mode=%s\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : -+ "Peripheral")); -+ mdelay(100); -+ if (++count > 10000) -+ *(uint32_t *) NULL = 0; -+ } -+ core_if->op_state = A_HOST; -+ /* -+ * Initialize the Core for Host mode. -+ */ -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ hcd_start(core_if); -+ } -+ -+ /* Set flag and clear interrupt */ -+ gintsts.b.conidstschng = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that a device is initiating the Session -+ * Request Protocol to request the host to turn on bus power so a new -+ * session can begin. The handler responds by turning on bus power. If -+ * the DWC_otg controller is in low power mode, the handler brings the -+ * controller out of low power mode before turning on bus power. -+ * -+ * @core_if: Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_session_req_intr(struct dwc_otg_core_if *core_if) -+{ -+ union gintsts_data gintsts; -+#ifndef DWC_HOST_ONLY -+ union hprt0_data hprt0; -+ -+ DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ DWC_PRINT("SRP: Device mode\n"); -+ } else { -+ DWC_PRINT("SRP: Host mode\n"); -+ -+ /* Turn on the port power bit. */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ -+ /* Start the Connection timer. So a message can be displayed -+ * if connect does not occur within 10 seconds. */ -+ hcd_session_start(core_if); -+ } -+#endif -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.sessreqintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that the DWC_otg controller has detected a -+ * resume or remote wakeup sequence. If the DWC_otg controller is in -+ * low power mode, the handler must brings the controller out of low -+ * power mode. The controller automatically begins resume -+ * signaling. The handler schedules a time to stop resume signaling. -+ */ -+int32_t dwc_otg_handle_wakeup_detected_intr(struct dwc_otg_core_if *core_if) -+{ -+ union gintsts_data gintsts; -+ -+ DWC_DEBUGPL(DBG_ANY, -+ "++Resume and Remote Wakeup Detected Interrupt++\n"); -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ union dctl_data dctl = {.d32 = 0 }; -+ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ dsts)); -+#ifdef PARTIAL_POWER_DOWN -+ if (core_if->hwcfg4.b.power_optimiz) { -+ union pcgcctl_data power = {.d32 = 0 }; -+ -+ power.d32 = dwc_read_reg32(core_if->pcgcctl); -+ DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", power.d32); -+ -+ power.b.stoppclk = 0; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ -+ power.b.pwrclmp = 0; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ -+ power.b.rstpdwnmodule = 0; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ } -+#endif -+ /* Clear the Remote Wakeup Signalling */ -+ dctl.b.rmtwkupsig = 1; -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, -+ dctl.d32, 0); -+ -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); -+ } else { -+ /* -+ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms -+ * so that OPT tests pass with all PHYs). -+ */ -+ union hprt0_data hprt0 = {.d32 = 0 }; -+ union pcgcctl_data pcgcctl = {.d32 = 0 }; -+ /* Restart the Phy Clock */ -+ pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); -+ udelay(10); -+ -+ /* Now wait for 70 ms. */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); -+ mdelay(70); -+ hprt0.b.prtres = 0; /* Resume */ -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", -+ dwc_read_reg32(core_if->host_if->hprt0)); -+ } -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.wkupintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that a device has been disconnected from -+ * the root port. -+ */ -+int32_t dwc_otg_handle_disconnect_intr(struct dwc_otg_core_if *core_if) -+{ -+ union gintsts_data gintsts; -+ -+ DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"), -+ op_state_str(core_if)); -+ -+/** @todo Consolidate this if statement. */ -+#ifndef DWC_HOST_ONLY -+ if (core_if->op_state == B_HOST) { -+ /* If in device mode Disconnect and stop the HCD, then -+ * start the PCD. */ -+ hcd_disconnect(core_if); -+ pcd_start(core_if); -+ core_if->op_state = B_PERIPHERAL; -+ } else if (dwc_otg_is_device_mode(core_if)) { -+ union gotgctl_data gotgctl = {.d32 = 0 }; -+ gotgctl.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ if (gotgctl.b.hstsethnpen == 1) { -+ /* Do nothing, if HNP in process the OTG -+ * interrupt "Host Negotiation Detected" -+ * interrupt will do the mode switch. -+ */ -+ } else if (gotgctl.b.devhnpen == 0) { -+ /* If in device mode Disconnect and stop the HCD, then -+ * start the PCD. */ -+ hcd_disconnect(core_if); -+ pcd_start(core_if); -+ core_if->op_state = B_PERIPHERAL; -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); -+ } -+ } else { -+ if (core_if->op_state == A_HOST) { -+ /* A-Cable still connected but device disconnected. */ -+ hcd_disconnect(core_if); -+ } -+ } -+#endif -+ -+ gintsts.d32 = 0; -+ gintsts.b.disconnect = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that SUSPEND state has been detected on -+ * the USB. -+ * -+ * For HNP the USB Suspend interrupt signals the change from -+ * "a_peripheral" to "a_host". -+ * -+ * When power management is enabled the core will be put in low power -+ * mode. -+ */ -+int32_t dwc_otg_handle_usb_suspend_intr(struct dwc_otg_core_if *core_if) -+{ -+ union dsts_data dsts; -+ union gintsts_data gintsts; -+ -+ DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ /* Check the Device status register to determine if the Suspend -+ * state is active. */ -+ dsts.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); -+ DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " -+ "HWCFG4.power Optimize=%d\n", -+ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); -+ -+#ifdef PARTIAL_POWER_DOWN -+/** @todo Add a module parameter for power management. */ -+ -+ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { -+ union pcgcctl_data_t power = {.d32 = 0 }; -+ DWC_DEBUGPL(DBG_CIL, "suspend\n"); -+ -+ power.b.pwrclmp = 1; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ -+ power.b.rstpdwnmodule = 1; -+ dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); -+ -+ power.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); -+ -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); -+ } -+#endif -+ /* PCD callback for suspend. */ -+ pcd_suspend(core_if); -+ } else { -+ if (core_if->op_state == A_PERIPHERAL) { -+ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); -+ /* Clear the a_peripheral flag, back to a_host. */ -+ pcd_stop(core_if); -+ hcd_start(core_if); -+ core_if->op_state = A_HOST; -+ } -+ } -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.usbsuspend = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This function returns the Core Interrupt register. -+ */ -+static inline uint32_t dwc_otg_read_common_intr(struct dwc_otg_core_if *core_if) -+{ -+ union gintsts_data gintsts; -+ union gintmsk_data gintmsk; -+ union gintmsk_data gintmsk_common = {.d32 = 0 }; -+ gintmsk_common.b.wkupintr = 1; -+ gintmsk_common.b.sessreqintr = 1; -+ gintmsk_common.b.conidstschng = 1; -+ gintmsk_common.b.otgintr = 1; -+ gintmsk_common.b.modemismatch = 1; -+ gintmsk_common.b.disconnect = 1; -+ gintmsk_common.b.usbsuspend = 1; -+ /* -+ * @todo: The port interrupt occurs while in device -+ * mode. Added code to CIL to clear the interrupt for now! -+ */ -+ gintmsk_common.b.portintr = 1; -+ -+ gintsts.d32 = dwc_read_reg32(&core_if->core_global_regs->gintsts); -+ gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk); -+#ifdef DEBUG -+ /* if any common interrupts set */ -+ if (gintsts.d32 & gintmsk_common.d32) { -+ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", -+ gintsts.d32, gintmsk.d32); -+ } -+#endif -+ -+ return (gintsts.d32 & gintmsk.d32) & gintmsk_common.d32; -+ -+} -+ -+/** -+ * Common interrupt handler. -+ * -+ * The common interrupts are those that occur in both Host and Device mode. -+ * This handler handles the following interrupts: -+ * - Mode Mismatch Interrupt -+ * - Disconnect Interrupt -+ * - OTG Interrupt -+ * - Connector ID Status Change Interrupt -+ * - Session Request Interrupt. -+ * - Resume / Remote Wakeup Detected Interrupt. -+ * -+ */ -+extern int32_t dwc_otg_handle_common_intr(struct dwc_otg_core_if *core_if) -+{ -+ int retval = 0; -+ union gintsts_data gintsts; -+ -+ gintsts.d32 = dwc_otg_read_common_intr(core_if); -+ -+ if (gintsts.b.modemismatch) -+ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); -+ if (gintsts.b.otgintr) -+ retval |= dwc_otg_handle_otg_intr(core_if); -+ if (gintsts.b.conidstschng) -+ retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); -+ if (gintsts.b.disconnect) -+ retval |= dwc_otg_handle_disconnect_intr(core_if); -+ if (gintsts.b.sessreqintr) -+ retval |= dwc_otg_handle_session_req_intr(core_if); -+ if (gintsts.b.wkupintr) -+ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); -+ if (gintsts.b.usbsuspend) -+ retval |= dwc_otg_handle_usb_suspend_intr(core_if); -+ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { -+ /* The port interrupt occurs while in device mode with HPRT0 -+ * Port Enable/Disable. -+ */ -+ gintsts.d32 = 0; -+ gintsts.b.portintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, -+ gintsts.d32); -+ retval |= 1; -+ -+ } -+ return retval; -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h -new file mode 100644 -index 0000000..1cc116d ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h -@@ -0,0 +1,63 @@ -+/* ========================================================================== -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+#ifndef __DWC_OTG_DRIVER_H__ -+#define __DWC_OTG_DRIVER_H__ -+ -+#include "dwc_otg_cil.h" -+ -+/* Type declarations */ -+struct dwc_otg_pcd; -+struct dwc_otg_hcd; -+ -+/** -+ * This structure is a wrapper that encapsulates the driver components used to -+ * manage a single DWC_otg controller. -+ */ -+struct dwc_otg_device { -+ /** Base address returned from ioremap() */ -+ void *base; -+ -+ /** Pointer to the core interface structure. */ -+ struct dwc_otg_core_if *core_if; -+ -+ /** Register offset for Diagnostic API.*/ -+ uint32_t reg_offset; -+ -+ /** Pointer to the PCD structure. */ -+ struct dwc_otg_pcd *pcd; -+ -+ /** Pointer to the HCD structure. */ -+ struct dwc_otg_hcd *hcd; -+ -+ /** Flag to indicate whether the common IRQ handler is installed. */ -+ uint8_t common_irq_installed; -+ -+}; -+ -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -new file mode 100644 -index 0000000..a4392f5 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -0,0 +1,2878 @@ -+/* ========================================================================== -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+#ifndef DWC_DEVICE_ONLY -+ -+/** -+ * -+ * This file contains the implementation of the HCD. In Linux, the HCD -+ * implements the hc_driver API. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dwc_otg_driver.h" -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; -+ -+static const struct hc_driver dwc_otg_hc_driver = { -+ -+ .description = dwc_otg_hcd_name, -+ .product_desc = "DWC OTG Controller", -+ .hcd_priv_size = sizeof(struct dwc_otg_hcd), -+ -+ .irq = dwc_otg_hcd_irq, -+ -+ .flags = HCD_MEMORY | HCD_USB2, -+ -+ .start = dwc_otg_hcd_start, -+ .stop = dwc_otg_hcd_stop, -+ -+ .urb_enqueue = dwc_otg_hcd_urb_enqueue, -+ .urb_dequeue = dwc_otg_hcd_urb_dequeue, -+ .endpoint_disable = dwc_otg_hcd_endpoint_disable, -+ -+ .get_frame_number = dwc_otg_hcd_get_frame_number, -+ -+ .hub_status_data = dwc_otg_hcd_hub_status_data, -+ .hub_control = dwc_otg_hcd_hub_control, -+}; -+ -+/** -+ * Work queue function for starting the HCD when A-Cable is connected. -+ * The dwc_otg_hcd_start() must be called in a process context. -+ */ -+static void hcd_start_func(struct work_struct *work) -+{ -+ void *_vp = -+ (void *)(atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK); -+ struct usb_hcd *usb_hcd = (struct usb_hcd *)_vp; -+ DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, usb_hcd); -+ if (usb_hcd) -+ dwc_otg_hcd_start(usb_hcd); -+} -+ -+/** -+ * HCD Callback function for starting the HCD when A-Cable is -+ * connected. -+ * -+ * @_p: void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_start_cb(void *_p) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); -+ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; -+ union hprt0_data hprt0; -+ -+ if (core_if->op_state == B_HOST) { -+ /* -+ * Reset the port. During a HNP mode switch the reset -+ * needs to occur within 1ms and have a duration of at -+ * least 50ms. -+ */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ ((struct usb_hcd *)_p)->self.is_b_host = 1; -+ } else { -+ ((struct usb_hcd *)_p)->self.is_b_host = 0; -+ } -+ -+ /* Need to start the HCD in a non-interrupt context. */ -+ INIT_WORK(&dwc_otg_hcd->start_work, hcd_start_func); -+ atomic_long_set(&dwc_otg_hcd->start_work.data, (long)_p); -+ schedule_work(&dwc_otg_hcd->start_work); -+ -+ return 1; -+} -+ -+/** -+ * HCD Callback function for stopping the HCD. -+ * -+ * @_p: void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_stop_cb(void *_p) -+{ -+ struct usb_hcd *usb_hcd = (struct usb_hcd *)_p; -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); -+ dwc_otg_hcd_stop(usb_hcd); -+ return 1; -+} -+ -+static void del_xfer_timers(struct dwc_otg_hcd *hcd) -+{ -+#ifdef DEBUG -+ int i; -+ int num_channels = hcd->core_if->core_params->host_channels; -+ for (i = 0; i < num_channels; i++) -+ del_timer(&hcd->core_if->hc_xfer_timer[i]); -+#endif -+} -+ -+static void del_timers(struct dwc_otg_hcd *hcd) -+{ -+ del_xfer_timers(hcd); -+ del_timer(&hcd->conn_timer); -+} -+ -+/** -+ * Processes all the URBs in a single list of QHs. Completes them with -+ * -ETIMEDOUT and frees the QTD. -+ */ -+static void kill_urbs_in_qh_list(struct dwc_otg_hcd *hcd, -+ struct list_head *_qh_list) -+{ -+ struct dwc_otg_qh *qh; -+ struct dwc_otg_qtd *qtd; -+ struct dwc_otg_qtd *qtd_next; -+ -+ list_for_each_entry(qh, _qh_list, qh_list_entry) { -+ list_for_each_entry_safe(qtd, qtd_next, &qh->qtd_list, -+ qtd_list_entry) { -+ if (qtd->urb != NULL) { -+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -+ -ETIMEDOUT); -+ qtd->urb = NULL; -+ } -+ dwc_otg_hcd_qtd_remove_and_free(qtd); -+ } -+ } -+} -+ -+/** -+ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic -+ * and periodic schedules. The QTD associated with each URB is removed from -+ * the schedule and freed. This function may be called when a disconnect is -+ * detected or when the HCD is being stopped. -+ */ -+static void kill_all_urbs(struct dwc_otg_hcd *hcd) -+{ -+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); -+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); -+} -+ -+/** -+ * HCD Callback function for disconnect of the HCD. -+ * -+ * @_p: void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_disconnect_cb(void *_p) -+{ -+ union gintsts_data intr; -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); -+ -+ /* -+ * Set status flags for the hub driver. -+ */ -+ dwc_otg_hcd->flags.b.port_connect_status_change = 1; -+ dwc_otg_hcd->flags.b.port_connect_status = 0; -+ -+ /* -+ * Shutdown any transfers in process by clearing the Tx FIFO Empty -+ * interrupt mask and status bits and disabling subsequent host -+ * channel interrupts. -+ */ -+ intr.d32 = 0; -+ intr.b.nptxfempty = 1; -+ intr.b.ptxfempty = 1; -+ intr.b.hcintr = 1; -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, -+ intr.d32, 0); -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, -+ intr.d32, 0); -+ -+ del_timers(dwc_otg_hcd); -+ -+ /* -+ * Turn off the vbus power only if the core has transitioned to device -+ * mode. If still in host mode, need to keep power on to detect a -+ * reconnection. -+ */ -+ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { -+ if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { -+ union hprt0_data hprt0 = {.d32 = 0 }; -+ DWC_PRINT("Disconnect: PortPower off\n"); -+ hprt0.b.prtpwr = 0; -+ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, -+ hprt0.d32); -+ } -+ -+ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); -+ } -+ -+ /* Respond with an error status to all URBs in the schedule. */ -+ kill_all_urbs(dwc_otg_hcd); -+ -+ if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) { -+ /* Clean up any host channels that were in use. */ -+ int num_channels; -+ int i; -+ struct dwc_hc *channel; -+ struct dwc_otg_hc_regs *hc_regs; -+ union hcchar_data hcchar; -+ -+ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; -+ -+ if (!dwc_otg_hcd->core_if->dma_enable) { -+ /* Flush out any channel requests in slave mode. */ -+ for (i = 0; i < num_channels; i++) { -+ channel = dwc_otg_hcd->hc_ptr_array[i]; -+ if (list_empty(&channel->hc_list_entry)) { -+ hc_regs = -+ dwc_otg_hcd->core_if->host_if-> -+ hc_regs[i]; -+ hcchar.d32 = -+ dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chen = 0; -+ hcchar.b.chdis = 1; -+ hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs-> -+ hcchar, -+ hcchar.d32); -+ } -+ } -+ } -+ } -+ -+ for (i = 0; i < num_channels; i++) { -+ channel = dwc_otg_hcd->hc_ptr_array[i]; -+ if (list_empty(&channel->hc_list_entry)) { -+ hc_regs = -+ dwc_otg_hcd->core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ /* Halt the channel. */ -+ hcchar.b.chdis = 1; -+ dwc_write_reg32(&hc_regs->hcchar, -+ hcchar.d32); -+ } -+ -+ dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, -+ channel); -+ list_add_tail(&channel->hc_list_entry, -+ &dwc_otg_hcd->free_hc_list); -+ } -+ } -+ } -+ -+ /* A disconnect will end the session so the B-Device is no -+ * longer a B-host. */ -+ ((struct usb_hcd *)_p)->self.is_b_host = 0; -+ return 1; -+} -+ -+/** -+ * Connection timeout function. An OTG host is required to display a -+ * message if the device does not connect within 10 seconds. -+ */ -+void dwc_otg_hcd_connect_timeout(unsigned long _ptr) -+{ -+ DWC_DEBUGPL(DBG_HCDV, "%s(%x)\n", __func__, (int)_ptr); -+ DWC_PRINT("Connect Timeout\n"); -+ DWC_ERROR("Device Not Connected/Responding\n"); -+} -+ -+/** -+ * Start the connection timer. An OTG host is required to display a -+ * message if the device does not connect within 10 seconds. The -+ * timer is deleted if a port connect interrupt occurs before the -+ * timer expires. -+ */ -+static void dwc_otg_hcd_start_connect_timer(struct dwc_otg_hcd *hcd) -+{ -+ init_timer(&hcd->conn_timer); -+ hcd->conn_timer.function = dwc_otg_hcd_connect_timeout; -+ hcd->conn_timer.data = (unsigned long)0; -+ hcd->conn_timer.expires = jiffies + (HZ * 10); -+ add_timer(&hcd->conn_timer); -+} -+ -+/** -+ * HCD Callback function for disconnect of the HCD. -+ * -+ * @_p: void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_session_start_cb(void *_p) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_p); -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _p); -+ dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); -+ return 1; -+} -+ -+/** -+ * HCD Callback structure for handling mode switching. -+ */ -+static struct dwc_otg_cil_callbacks hcd_cil_callbacks = { -+ .start = dwc_otg_hcd_start_cb, -+ .stop = dwc_otg_hcd_stop_cb, -+ .disconnect = dwc_otg_hcd_disconnect_cb, -+ .session_start = dwc_otg_hcd_session_start_cb, -+ .p = 0, -+}; -+ -+/** -+ * Reset tasklet function -+ */ -+static void reset_tasklet_func(unsigned long data) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = (struct dwc_otg_hcd *)data; -+ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; -+ union hprt0_data hprt0; -+ -+ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); -+ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ mdelay(60); -+ -+ hprt0.b.prtrst = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ dwc_otg_hcd->flags.b.port_reset_change = 1; -+ -+ return; -+} -+ -+static struct tasklet_struct reset_tasklet = { -+ .next = NULL, -+ .state = 0, -+ .count = ATOMIC_INIT(0), -+ .func = reset_tasklet_func, -+ .data = 0, -+}; -+ -+static enum hrtimer_restart delayed_enable(struct hrtimer *t) -+{ -+ struct dwc_otg_hcd *hcd = container_of(t, struct dwc_otg_hcd, -+ poll_rate_limit); -+ struct dwc_otg_core_global_regs *global_regs = -+ hcd->core_if->core_global_regs; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, intr_mask.d32); -+ -+ return HRTIMER_NORESTART; -+} -+ -+/** -+ * Initializes the HCD. This function allocates memory for and initializes the -+ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the -+ * USB bus with the core and calls the hc_driver->start() function. It returns -+ * a negative error on failure. -+ */ -+int __devinit dwc_otg_hcd_init(struct device *dev) -+{ -+ struct usb_hcd *hcd = NULL; -+ struct dwc_otg_hcd *dwc_otg_hcd = NULL; -+ struct dwc_otg_device *otg_dev = dev->platform_data; -+ -+ int num_channels; -+ int i; -+ struct dwc_hc *channel; -+ -+ int retval = 0; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n"); -+ -+ /* Set device flags indicating whether the HCD supports DMA. */ -+ if (otg_dev->core_if->dma_enable) { -+ DWC_PRINT("Using DMA mode\n"); -+ dev->coherent_dma_mask = ~0; -+ dev->dma_mask = &dev->coherent_dma_mask; -+ } else { -+ DWC_PRINT("Using Slave mode\n"); -+ dev->coherent_dma_mask = 0; -+ dev->dma_mask = NULL; -+ } -+ -+ /* -+ * Allocate memory for the base HCD plus the DWC OTG HCD. -+ * Initialize the base HCD. -+ */ -+ hcd = usb_create_hcd(&dwc_otg_hc_driver, dev, dev_name(dev)); -+ if (hcd == NULL) { -+ retval = -ENOMEM; -+ goto error1; -+ } -+ hcd->regs = otg_dev->base; -+ hcd->self.otg_port = 1; -+ -+ /* Integrate TT in root hub, by default this is disbled. */ -+ hcd->has_tt = 1; -+ -+ /* Initialize the DWC OTG HCD. */ -+ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ spin_lock_init(&dwc_otg_hcd->global_lock); -+ -+ dwc_otg_hcd->core_if = otg_dev->core_if; -+ otg_dev->hcd = dwc_otg_hcd; -+ -+ /* Register the HCD CIL Callbacks */ -+ dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if, -+ &hcd_cil_callbacks, hcd); -+ -+ /* Initialize the non-periodic schedule. */ -+ INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_inactive); -+ INIT_LIST_HEAD(&dwc_otg_hcd->non_periodic_sched_active); -+ -+ /* Initialize the periodic schedule. */ -+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_inactive); -+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_ready); -+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_assigned); -+ INIT_LIST_HEAD(&dwc_otg_hcd->periodic_sched_queued); -+ -+ /* -+ * Create a host channel descriptor for each host channel implemented -+ * in the controller. Initialize the channel descriptor array. -+ */ -+ INIT_LIST_HEAD(&dwc_otg_hcd->free_hc_list); -+ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; -+ for (i = 0; i < num_channels; i++) { -+ channel = kmalloc(sizeof(struct dwc_hc), GFP_KERNEL); -+ if (channel == NULL) { -+ retval = -ENOMEM; -+ DWC_ERROR("%s: host channel allocation failed\n", -+ __func__); -+ goto error2; -+ } -+ memset(channel, 0, sizeof(struct dwc_hc)); -+ channel->hc_num = i; -+ dwc_otg_hcd->hc_ptr_array[i] = channel; -+#ifdef DEBUG -+ init_timer(&dwc_otg_hcd->core_if->hc_xfer_timer[i]); -+#endif -+ -+ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, -+ channel); -+ } -+ -+ /* Initialize the Connection timeout timer. */ -+ init_timer(&dwc_otg_hcd->conn_timer); -+ -+ /* Initialize reset tasklet. */ -+ reset_tasklet.data = (unsigned long)dwc_otg_hcd; -+ dwc_otg_hcd->reset_tasklet = &reset_tasklet; -+ -+ hrtimer_init(&dwc_otg_hcd->poll_rate_limit, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ dwc_otg_hcd->poll_rate_limit.function = delayed_enable; -+ -+ /* -+ * Finish generic HCD initialization and start the HCD. This function -+ * allocates the DMA buffer pool, registers the USB bus, requests the -+ * IRQ line, and calls dwc_otg_hcd_start method. -+ */ -+ retval = -+ usb_add_hcd(hcd, platform_get_irq(to_platform_device(dev), 0), -+ IRQF_SHARED); -+ if (retval < 0) -+ goto error2; -+ -+ /* -+ * Allocate space for storing data on status transactions. Normally no -+ * data is sent, but this space acts as a bit bucket. This must be -+ * done after usb_add_hcd since that function allocates the DMA buffer -+ * pool. -+ */ -+ if (otg_dev->core_if->dma_enable) { -+ dwc_otg_hcd->status_buf = -+ dma_alloc_coherent(dev, -+ DWC_OTG_HCD_STATUS_BUF_SIZE, -+ &dwc_otg_hcd->status_buf_dma, -+ GFP_KERNEL | GFP_DMA); -+ } else { -+ dwc_otg_hcd->status_buf = kmalloc(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ GFP_KERNEL); -+ } -+ if (dwc_otg_hcd->status_buf == NULL) { -+ retval = -ENOMEM; -+ DWC_ERROR("%s: status_buf allocation failed\n", __func__); -+ goto error3; -+ } -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, usbbus=%d\n", -+ hcd->self.busnum); -+ -+ return 0; -+ -+ /* Error conditions */ -+error3: -+ usb_remove_hcd(hcd); -+error2: -+ dwc_otg_hcd_free(hcd); -+ usb_put_hcd(hcd); -+error1: -+ return retval; -+} -+ -+/** -+ * Removes the HCD. -+ * Frees memory and resources associated with the HCD and deregisters the bus. -+ */ -+void dwc_otg_hcd_remove(struct device *dev) -+{ -+ struct dwc_otg_device *otg_dev = dev->platform_data; -+ struct dwc_otg_hcd *dwc_otg_hcd = otg_dev->hcd; -+ struct usb_hcd *hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n"); -+ -+ /* Turn off all interrupts */ -+ dwc_write_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0); -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gahbcfg, 1, -+ 0); -+ -+ usb_remove_hcd(hcd); -+ dwc_otg_hcd_free(hcd); -+ usb_put_hcd(hcd); -+ -+ return; -+} -+ -+/* ========================================================================= -+ * Linux HC Driver Functions -+ * ========================================================================= */ -+ -+/** -+ * Initializes dynamic portions of the DWC_otg HCD state. -+ */ -+static void hcd_reinit(struct dwc_otg_hcd *hcd) -+{ -+ struct list_head *item; -+ int num_channels; -+ int i; -+ struct dwc_hc *channel; -+ -+ hcd->flags.d32 = 0; -+ -+ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; -+ hcd->non_periodic_channels = 0; -+ hcd->periodic_channels = 0; -+ -+ /* -+ * Put all channels in the free channel list and clean up channel -+ * states. -+ */ -+ item = hcd->free_hc_list.next; -+ while (item != &hcd->free_hc_list) { -+ list_del(item); -+ item = hcd->free_hc_list.next; -+ } -+ num_channels = hcd->core_if->core_params->host_channels; -+ for (i = 0; i < num_channels; i++) { -+ channel = hcd->hc_ptr_array[i]; -+ list_add_tail(&channel->hc_list_entry, &hcd->free_hc_list); -+ dwc_otg_hc_cleanup(hcd->core_if, channel); -+ } -+ -+ /* Initialize the DWC core for host mode operation. */ -+ dwc_otg_core_host_init(hcd->core_if); -+} -+ -+/** Initializes the DWC_otg controller and its root hub and prepares it for host -+ * mode operation. Activates the root port. Returns 0 on success and a negative -+ * error code on failure. */ -+int dwc_otg_hcd_start(struct usb_hcd *hcd) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; -+ unsigned long flags; -+ -+ struct usb_bus *bus; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); -+ -+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); -+ -+ bus = hcd_to_bus(hcd); -+ -+ /* Initialize the bus state. If the core is in Device Mode -+ * HALT the USB bus and return. */ -+ if (dwc_otg_is_device_mode(core_if)) { -+ hcd->state = HC_STATE_HALT; -+ goto out; -+ } -+ hcd->state = HC_STATE_RUNNING; -+ -+ hcd_reinit(dwc_otg_hcd); -+out: -+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); -+ -+ return 0; -+} -+ -+static void qh_list_free(struct dwc_otg_hcd *hcd, struct list_head *_qh_list) -+{ -+ struct list_head *item; -+ struct dwc_otg_qh *qh; -+ -+ if (_qh_list->next == NULL) { -+ /* The list hasn't been initialized yet. */ -+ return; -+ } -+ -+ /* Ensure there are no QTDs or URBs left. */ -+ kill_urbs_in_qh_list(hcd, _qh_list); -+ -+ for (item = _qh_list->next; item != _qh_list; item = _qh_list->next) { -+ qh = list_entry(item, struct dwc_otg_qh, qh_list_entry); -+ dwc_otg_hcd_qh_remove_and_free(hcd, qh); -+ } -+} -+ -+/** -+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are -+ * stopped. -+ */ -+void dwc_otg_hcd_stop(struct usb_hcd *hcd) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ union hprt0_data hprt0 = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n"); -+ -+ /* Turn off all host-specific interrupts. */ -+ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); -+ -+ /* -+ * The root hub should be disconnected before this function is called. -+ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) -+ * and the QH lists (via ..._hcd_endpoint_disable). -+ */ -+ -+ /* Turn off the vbus power */ -+ DWC_PRINT("PortPower off\n"); -+ hprt0.b.prtpwr = 0; -+ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); -+ -+ return; -+} -+ -+/** Returns the current frame number. */ -+int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ union hfnum_data hfnum; -+ -+ hfnum.d32 = -+ dwc_read_reg32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> -+ hfnum); -+ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", -+ hfnum.b.frnum); -+#endif -+ return hfnum.b.frnum; -+} -+ -+/** -+ * Frees secondary storage associated with the dwc_otg_hcd structure contained -+ * in the struct usb_hcd field. -+ */ -+void dwc_otg_hcd_free(struct usb_hcd *hcd) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ int i; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); -+ -+ del_timers(dwc_otg_hcd); -+ -+ /* Free memory for QH/QTD lists */ -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued); -+ -+ /* Free memory for the host channels. */ -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ struct dwc_hc *hc = dwc_otg_hcd->hc_ptr_array[i]; -+ if (hc != NULL) { -+ DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", -+ i, hc); -+ kfree(hc); -+ } -+ } -+ -+ if (dwc_otg_hcd->core_if->dma_enable) { -+ if (dwc_otg_hcd->status_buf_dma) { -+ dma_free_coherent(hcd->self.controller, -+ DWC_OTG_HCD_STATUS_BUF_SIZE, -+ dwc_otg_hcd->status_buf, -+ dwc_otg_hcd->status_buf_dma); -+ } -+ } else if (dwc_otg_hcd->status_buf != NULL) { -+ kfree(dwc_otg_hcd->status_buf); -+ } -+ -+ return; -+} -+ -+#ifdef DEBUG -+static void dump_urb_info(struct urb *urb, char *_fn_name) -+{ -+ DWC_PRINT("%s, urb %p\n", _fn_name, urb); -+ DWC_PRINT(" Device address: %d\n", usb_pipedevice(urb->pipe)); -+ DWC_PRINT(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), -+ (usb_pipein(urb->pipe) ? "IN" : "OUT")); -+ DWC_PRINT(" Endpoint type: %s\n", -+ ({ -+ char *pipetype; -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_CONTROL: -+ pipetype = "CONTROL"; -+ break; -+ case PIPE_BULK: -+ pipetype = "BULK"; -+ break; -+ case PIPE_INTERRUPT: -+ pipetype = "INTERRUPT"; -+ break; -+ case PIPE_ISOCHRONOUS: -+ pipetype = "ISOCHRONOUS"; -+ break; -+ default: -+ pipetype = "UNKNOWN"; -+ break; -+ } -+ pipetype; -+ })) ; -+ DWC_PRINT(" Speed: %s\n", -+ ({ -+ char *speed; -+ switch (urb->dev->speed) { -+ case USB_SPEED_HIGH: -+ speed = "HIGH"; -+ break; -+ case USB_SPEED_FULL: -+ speed = "FULL"; -+ break; -+ case USB_SPEED_LOW: -+ speed = "LOW"; -+ break; -+ default: -+ speed = "UNKNOWN"; -+ break; -+ } -+ speed; -+ })); -+ DWC_PRINT(" Max packet size: %d\n", -+ usb_maxpacket(urb->dev, urb->pipe, -+ usb_pipeout(urb->pipe))); -+ DWC_PRINT(" Data buffer length: %d\n", urb->transfer_buffer_length); -+ DWC_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n", -+ urb->transfer_buffer, (void *)urb->transfer_dma); -+ DWC_PRINT(" Setup buffer: %p, Setup DMA: %p\n", -+ urb->setup_packet, (void *)urb->setup_dma); -+ DWC_PRINT(" Interval: %d\n", urb->interval); -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ int i; -+ for (i = 0; i < urb->number_of_packets; i++) { -+ DWC_PRINT(" ISO Desc %d:\n", i); -+ DWC_PRINT(" offset: %d, length %d\n", -+ urb->iso_frame_desc[i].offset, -+ urb->iso_frame_desc[i].length); -+ } -+ } -+} -+ -+static void dump_channel_info(struct dwc_otg_hcd *hcd, struct dwc_otg_qh * qh) -+{ -+ if (qh->channel != NULL) { -+ struct dwc_hc *hc = qh->channel; -+ struct list_head *item; -+ struct dwc_otg_qh *qh_item; -+ int num_channels = hcd->core_if->core_params->host_channels; -+ int i; -+ -+ struct dwc_otg_hc_regs *hc_regs; -+ union hcchar_data hcchar; -+ union hcsplt_data hcsplt; -+ union hctsiz_data hctsiz; -+ uint32_t hcdma; -+ -+ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcdma = dwc_read_reg32(&hc_regs->hcdma); -+ -+ DWC_PRINT(" Assigned to channel %p:\n", hc); -+ DWC_PRINT(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, -+ hcsplt.d32); -+ DWC_PRINT(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, -+ hcdma); -+ DWC_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", -+ hc->dev_addr, hc->ep_num, hc->ep_is_in); -+ DWC_PRINT(" ep_type: %d\n", hc->ep_type); -+ DWC_PRINT(" max_packet: %d\n", hc->max_packet); -+ DWC_PRINT(" data_pid_start: %d\n", hc->data_pid_start); -+ DWC_PRINT(" xfer_started: %d\n", hc->xfer_started); -+ DWC_PRINT(" halt_status: %d\n", hc->halt_status); -+ DWC_PRINT(" xfer_buff: %p\n", hc->xfer_buff); -+ DWC_PRINT(" xfer_len: %d\n", hc->xfer_len); -+ DWC_PRINT(" qh: %p\n", hc->qh); -+ DWC_PRINT(" NP inactive sched:\n"); -+ list_for_each(item, &hcd->non_periodic_sched_inactive) { -+ qh_item = list_entry(item, struct dwc_otg_qh, -+ qh_list_entry); -+ DWC_PRINT(" %p\n", qh_item); -+ } -+ DWC_PRINT(" NP active sched:\n"); -+ list_for_each(item, &hcd->non_periodic_sched_active) { -+ qh_item = list_entry(item, struct dwc_otg_qh, -+ qh_list_entry); -+ DWC_PRINT(" %p\n", qh_item); -+ } -+ DWC_PRINT(" Channels: \n"); -+ for (i = 0; i < num_channels; i++) { -+ struct dwc_hc *hc = hcd->hc_ptr_array[i]; -+ DWC_PRINT(" %2d: %p\n", i, hc); -+ } -+ } -+} -+#endif -+ -+/* Starts processing a USB transfer request specified by a USB Request Block -+ * (URB). mem_flags indicates the type of memory allocation to use while -+ * processing this URB. */ -+int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, -+ struct urb *urb, unsigned _mem_flags) -+{ -+ unsigned long flags; -+ int retval = 0; -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ struct dwc_otg_qtd *qtd; -+ -+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); -+ -+ /* -+ * Make sure the start of frame interrupt is enabled now that -+ * we know we should have queued data. The SOF interrupt -+ * handler automatically disables itself when idle to reduce -+ * the number of interrupts. See dwc_otg_hcd_handle_sof_intr() -+ * for the disable -+ */ -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, -+ DWC_SOF_INTR_MASK); -+ -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) -+ dump_urb_info(urb, "dwc_otg_hcd_urb_enqueue"); -+#endif -+ if (!dwc_otg_hcd->flags.b.port_connect_status) { -+ /* No longer connected. */ -+ retval = -ENODEV; -+ goto out; -+ } -+ -+ qtd = dwc_otg_hcd_qtd_create(urb); -+ if (qtd == NULL) { -+ DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); -+ retval = -ENOMEM; -+ goto out; -+ } -+ -+ retval = dwc_otg_hcd_qtd_add(qtd, dwc_otg_hcd); -+ if (retval < 0) { -+ DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " -+ "Error status %d\n", retval); -+ dwc_otg_hcd_qtd_free(qtd); -+ } -+out: -+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); -+ -+ return retval; -+} -+ -+/** Aborts/cancels a USB transfer request. Always returns 0 to indicate -+ * success. */ -+int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -+{ -+ unsigned long flags; -+ struct dwc_otg_hcd *dwc_otg_hcd; -+ struct dwc_otg_qtd *urb_qtd; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); -+ -+ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); -+ -+ urb_qtd = urb->hcpriv; -+ -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ dump_urb_info(urb, "dwc_otg_hcd_urb_dequeue"); -+ if (urb_qtd == urb_qtd->qh->qtd_in_process) -+ dump_channel_info(dwc_otg_hcd, urb_qtd->qh); -+ } -+#endif -+ -+ if (urb_qtd == urb_qtd->qh->qtd_in_process) { -+ /* The QTD is in process (it has been assigned to a channel). */ -+ -+ if (dwc_otg_hcd->flags.b.port_connect_status) { -+ /* -+ * If still connected (i.e. in host mode), halt the -+ * channel so it can be used for other transfers. If -+ * no longer connected, the host registers can't be -+ * written to halt the channel since the core is in -+ * device mode. -+ */ -+ dwc_otg_hc_halt(dwc_otg_hcd->core_if, -+ urb_qtd->qh->channel, -+ DWC_OTG_HC_XFER_URB_DEQUEUE); -+ } -+ } -+ -+ /* -+ * Free the QTD and clean up the associated QH. Leave the QH in the -+ * schedule if it has any remaining QTDs. -+ */ -+ dwc_otg_hcd_qtd_remove_and_free(urb_qtd); -+ if (urb_qtd == urb_qtd->qh->qtd_in_process) { -+ dwc_otg_hcd_qh_deactivate(dwc_otg_hcd, urb_qtd->qh, 0); -+ urb_qtd->qh->channel = NULL; -+ urb_qtd->qh->qtd_in_process = NULL; -+ } else if (list_empty(&urb_qtd->qh->qtd_list)) { -+ dwc_otg_hcd_qh_remove(dwc_otg_hcd, urb_qtd->qh); -+ } -+ -+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); -+ -+ urb->hcpriv = NULL; -+ -+ /* Higher layer software sets URB status. */ -+ usb_hcd_giveback_urb(hcd, urb, status); -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ DWC_PRINT("Called usb_hcd_giveback_urb()\n"); -+ DWC_PRINT(" urb->status = %d\n", urb->status); -+ } -+ -+ return 0; -+} -+ -+/* Frees resources in the DWC_otg controller related to a given endpoint. Also -+ * clears state in the HCD related to the endpoint. Any URBs for the endpoint -+ * must already be dequeued. */ -+void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd, -+ struct usb_host_endpoint *_ep) -+{ -+ unsigned long flags; -+ struct dwc_otg_qh *qh; -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); -+ -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " -+ "endpoint=%d\n", _ep->desc.bEndpointAddress, -+ dwc_ep_addr_to_endpoint(_ep->desc.bEndpointAddress)); -+ -+ qh = _ep->hcpriv; -+ if (qh != NULL) { -+#if 1 -+ /* -+ * FIXME: Kludge to not crash on Octeon in SMP -+ * mode. Normally dwc_otg_hcd_qh_remove_and_free() is -+ * called even if the list isn't empty. This causes a -+ * crash on SMP, so we don't call it now. It works -+ * better, but probably does evil things I don't know -+ * about. -+ */ -+ /* Check that the QTD list is really empty */ -+ if (!list_empty(&qh->qtd_list)) { -+ pr_err("DWC OTG HCD EP DISABLE:" -+ " QTD List for this endpoint is not empty\n"); -+ } else -+#endif -+ { -+ dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh); -+ _ep->hcpriv = NULL; -+ } -+ } -+ -+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); -+ -+ return; -+} -+ -+/* Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if -+ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid -+ * interrupt. -+ * -+ * This function is called by the USB core when an interrupt occurs */ -+irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) -+{ -+ irqreturn_t result; -+ unsigned long flags; -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); -+ -+ result = IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_otg_hcd)); -+ -+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); -+ -+ return result; -+} -+ -+/** Creates Status Change bitmap for the root hub and root port. The bitmap is -+ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 -+ * is the status change indicator for the single root port. Returns 1 if either -+ * change indicator is 1, otherwise returns 0. */ -+int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, char *_buf) -+{ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ _buf[0] = 0; -+ _buf[0] |= (dwc_otg_hcd->flags.b.port_connect_status_change || -+ dwc_otg_hcd->flags.b.port_reset_change || -+ dwc_otg_hcd->flags.b.port_enable_change || -+ dwc_otg_hcd->flags.b.port_suspend_change || -+ dwc_otg_hcd->flags.b.port_over_current_change) << 1; -+ -+#ifdef DEBUG -+ if (_buf[0]) { -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" -+ " Root port status changed\n"); -+ DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", -+ dwc_otg_hcd->flags.b.port_connect_status_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", -+ dwc_otg_hcd->flags.b.port_reset_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", -+ dwc_otg_hcd->flags.b.port_enable_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", -+ dwc_otg_hcd->flags.b.port_suspend_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", -+ dwc_otg_hcd->flags.b.port_over_current_change); -+ } -+#endif -+ return (_buf[0] != 0); -+} -+ -+#ifdef DWC_HS_ELECT_TST -+/* -+ * Quick and dirty hack to implement the HS Electrical Test -+ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. -+ * -+ * This code was copied from our userspace app "hset". It sends a -+ * Get Device Descriptor control sequence in two parts, first the -+ * Setup packet by itself, followed some time later by the In and -+ * Ack packets. Rather than trying to figure out how to add this -+ * functionality to the normal driver code, we just hijack the -+ * hardware, using these two function to drive the hardware -+ * directly. -+ */ -+ -+struct dwc_otg_core_global_regs *global_regs; -+struct dwc_otg_host_global_regs *hc_global_regs; -+struct dwc_otg_hc_regs *hc_regs; -+uint32_t *data_fifo; -+ -+static void do_setup(void) -+{ -+ union gintsts_data gintsts; -+ union hctsiz_data hctsiz; -+ union hcchar_data hcchar; -+ union haint_data haint; -+ union hcint_data hcint; -+ -+ /* Enable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); -+ -+ /* Enable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* -+ * Send Setup packet (Get Device Descriptor) -+ */ -+ -+ /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chdis = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ mdelay(1000); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ } -+ -+ /* Set HCTSIZ */ -+ hctsiz.d32 = 0; -+ hctsiz.b.xfersize = 8; -+ hctsiz.b.pktcnt = 1; -+ hctsiz.b.pid = DWC_OTG_HC_PID_SETUP; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.epdir = 0; -+ hcchar.b.epnum = 0; -+ hcchar.b.mps = 8; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ /* Fill FIFO with Setup data for Get Device Descriptor */ -+ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); -+ dwc_write_reg32(data_fifo++, 0x01000680); -+ dwc_write_reg32(data_fifo++, 0x00080000); -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for host channel interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.hcintr == 0); -+ -+ -+ /* Disable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); -+ -+ /* Disable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+} -+ -+static void do_in_ack(void) -+{ -+ union gintsts_data gintsts; -+ union hctsiz_data hctsiz; -+ union hcchar_data hcchar; -+ union haint_data haint; -+ union hcint_data hcint; -+ union host_grxsts_data grxsts; -+ -+ /* Enable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); -+ -+ /* Enable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* -+ * Receive Control In packet -+ */ -+ -+ /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chdis = 1; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ mdelay(1000); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ } -+ -+ /* Set HCTSIZ */ -+ hctsiz.d32 = 0; -+ hctsiz.b.xfersize = 8; -+ hctsiz.b.pktcnt = 1; -+ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.epdir = 1; -+ hcchar.b.epnum = 0; -+ hcchar.b.mps = 8; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for receive status queue interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.rxstsqlvl == 0); -+ -+ /* Read RXSTS */ -+ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ -+ /* Clear RXSTSQLVL in GINTSTS */ -+ gintsts.d32 = 0; -+ gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ switch (grxsts.b.pktsts) { -+ case DWC_GRXSTS_PKTSTS_IN: -+ /* Read the data into the host buffer */ -+ if (grxsts.b.bcnt > 0) { -+ int i; -+ int word_count = (grxsts.b.bcnt + 3) / 4; -+ -+ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); -+ -+ for (i = 0; i < word_count; i++) -+ (void)dwc_read_reg32(data_fifo++); -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for receive status queue interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.rxstsqlvl == 0); -+ -+ -+ /* Read RXSTS */ -+ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ -+ /* Clear RXSTSQLVL in GINTSTS */ -+ gintsts.d32 = 0; -+ gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ switch (grxsts.b.pktsts) { -+ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: -+ break; -+ -+ default: -+ break; -+ } -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for host channel interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.hcintr == 0); -+ -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ mdelay(1); -+ -+ /* -+ * Send handshake packet -+ */ -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chdis = 1; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ mdelay(1000); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ } -+ -+ /* Set HCTSIZ */ -+ hctsiz.d32 = 0; -+ hctsiz.b.xfersize = 0; -+ hctsiz.b.pktcnt = 1; -+ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.epdir = 0; -+ hcchar.b.epnum = 0; -+ hcchar.b.mps = 8; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for host channel interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.hcintr == 0); -+ -+ -+ /* Disable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); -+ -+ /* Disable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+} -+#endif /* DWC_HS_ELECT_TST */ -+ -+/* Handles hub class-specific requests.*/ -+int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, -+ u16 _typeReq, -+ u16 _wValue, u16 _wIndex, char *_buf, u16 _wLength) -+{ -+ int retval = 0; -+ unsigned long flags; -+ -+ struct dwc_otg_hcd *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ struct dwc_otg_core_if *core_if = hcd_to_dwc_otg_hcd(hcd)->core_if; -+ struct usb_hub_descriptor *desc; -+ union hprt0_data hprt0 = {.d32 = 0 }; -+ -+ uint32_t port_status; -+#ifdef DWC_HS_ELECT_TST -+ uint32_t t; -+ union gintmsk_data gintmsk; -+#endif -+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags); -+ -+ switch (_typeReq) { -+ case ClearHubFeature: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearHubFeature 0x%x\n", _wValue); -+ switch (_wValue) { -+ case C_HUB_LOCAL_POWER: -+ case C_HUB_OVER_CURRENT: -+ /* Nothing required here */ -+ break; -+ default: -+ retval = -EINVAL; -+ DWC_ERROR("DWC OTG HCD - " -+ "ClearHubFeature request %xh unknown\n", -+ _wValue); -+ } -+ break; -+ case ClearPortFeature: -+ if (!_wIndex || _wIndex > 1) -+ goto error; -+ -+ switch (_wValue) { -+ case USB_PORT_FEAT_ENABLE: -+ DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtena = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case USB_PORT_FEAT_SUSPEND: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ /* Clear Resume bit */ -+ mdelay(100); -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case USB_PORT_FEAT_POWER: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_POWER\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case USB_PORT_FEAT_INDICATOR: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); -+ /* Port inidicator not supported */ -+ break; -+ case USB_PORT_FEAT_C_CONNECTION: -+ /* Clears drivers internal connect status change -+ * flag */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); -+ dwc_otg_hcd->flags.b.port_connect_status_change = 0; -+ break; -+ case USB_PORT_FEAT_C_RESET: -+ /* Clears the driver's internal Port Reset Change -+ * flag */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); -+ dwc_otg_hcd->flags.b.port_reset_change = 0; -+ break; -+ case USB_PORT_FEAT_C_ENABLE: -+ /* Clears the driver's internal Port -+ * Enable/Disable Change flag */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); -+ dwc_otg_hcd->flags.b.port_enable_change = 0; -+ break; -+ case USB_PORT_FEAT_C_SUSPEND: -+ /* Clears the driver's internal Port Suspend -+ * Change flag, which is set when resume signaling on -+ * the host port is complete */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); -+ dwc_otg_hcd->flags.b.port_suspend_change = 0; -+ break; -+ case USB_PORT_FEAT_C_OVER_CURRENT: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); -+ dwc_otg_hcd->flags.b.port_over_current_change = 0; -+ break; -+ default: -+ retval = -EINVAL; -+ DWC_ERROR("DWC OTG HCD - " -+ "ClearPortFeature request %xh " -+ "unknown or unsupported\n", _wValue); -+ } -+ break; -+ case GetHubDescriptor: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetHubDescriptor\n"); -+ desc = (struct usb_hub_descriptor *)_buf; -+ desc->bDescLength = 9; -+ desc->bDescriptorType = 0x29; -+ desc->bNbrPorts = 1; -+ desc->wHubCharacteristics = 0x08; -+ desc->bPwrOn2PwrGood = 1; -+ desc->bHubContrCurrent = 0; -+ desc->bitmap[0] = 0; -+ desc->bitmap[1] = 0xff; -+ break; -+ case GetHubStatus: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetHubStatus\n"); -+ memset(_buf, 0, 4); -+ break; -+ case GetPortStatus: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetPortStatus\n"); -+ -+ if (!_wIndex || _wIndex > 1) -+ goto error; -+ -+ port_status = 0; -+ -+ if (dwc_otg_hcd->flags.b.port_connect_status_change) -+ port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); -+ -+ if (dwc_otg_hcd->flags.b.port_enable_change) -+ port_status |= (1 << USB_PORT_FEAT_C_ENABLE); -+ -+ if (dwc_otg_hcd->flags.b.port_suspend_change) -+ port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); -+ -+ if (dwc_otg_hcd->flags.b.port_reset_change) -+ port_status |= (1 << USB_PORT_FEAT_C_RESET); -+ -+ if (dwc_otg_hcd->flags.b.port_over_current_change) { -+ DWC_ERROR("Device Not Supported\n"); -+ port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT); -+ } -+ -+ if (!dwc_otg_hcd->flags.b.port_connect_status) { -+ /* -+ * The port is disconnected, which means the core is -+ * either in device mode or it soon will be. Just -+ * return 0's for the remainder of the port status -+ * since the port register can't be read if the core -+ * is in device mode. -+ */ -+ *((__le32 *) _buf) = cpu_to_le32(port_status); -+ break; -+ } -+ -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); -+ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); -+ -+ if (hprt0.b.prtconnsts) -+ port_status |= (1 << USB_PORT_FEAT_CONNECTION); -+ -+ if (hprt0.b.prtena) -+ port_status |= (1 << USB_PORT_FEAT_ENABLE); -+ -+ if (hprt0.b.prtsusp) -+ port_status |= (1 << USB_PORT_FEAT_SUSPEND); -+ -+ if (hprt0.b.prtovrcurract) -+ port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT); -+ -+ if (hprt0.b.prtrst) -+ port_status |= (1 << USB_PORT_FEAT_RESET); -+ -+ if (hprt0.b.prtpwr) -+ port_status |= (1 << USB_PORT_FEAT_POWER); -+ -+ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) -+ port_status |= (1 << USB_PORT_FEAT_HIGHSPEED); -+ else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) -+ port_status |= (1 << USB_PORT_FEAT_LOWSPEED); -+ -+ if (hprt0.b.prttstctl) -+ port_status |= (1 << USB_PORT_FEAT_TEST); -+ -+ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ -+ -+ *((__le32 *) _buf) = cpu_to_le32(port_status); -+ -+ break; -+ case SetHubFeature: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetHubFeature\n"); -+ /* No HUB features supported */ -+ break; -+ case SetPortFeature: -+ if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1)) -+ goto error; -+ -+ if (!dwc_otg_hcd->flags.b.port_connect_status) { -+ /* -+ * The port is disconnected, which means the core is -+ * either in device mode or it soon will be. Just -+ * return without doing anything since the port -+ * register can't be written if the core is in device -+ * mode. -+ */ -+ break; -+ } -+ -+ switch (_wValue) { -+ case USB_PORT_FEAT_SUSPEND: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); -+ if (hcd->self.otg_port == _wIndex && -+ hcd->self.b_hnp_enable) { -+ union gotgctl_data gotgctl = {.d32 = 0 }; -+ gotgctl.b.hstsethnpen = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> -+ gotgctl, 0, gotgctl.d32); -+ core_if->op_state = A_SUSPEND; -+ } -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ /* Suspend the Phy Clock */ -+ { -+ union pcgcctl_data pcgcctl = {.d32 = 0 }; -+ pcgcctl.b.stoppclk = 1; -+ dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32); -+ } -+ -+ /* -+ * For HNP the bus must be suspended for at -+ * least 200ms. -+ */ -+ if (hcd->self.b_hnp_enable) -+ mdelay(200); -+ break; -+ case USB_PORT_FEAT_POWER: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_POWER\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case USB_PORT_FEAT_RESET: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_RESET\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ /* When B-Host the Port reset bit is set in -+ * the Start HCD Callback function, so that -+ * the reset is started within 1ms of the HNP -+ * success interrupt. */ -+ if (!hcd->self.is_b_host) { -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ } -+ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ -+ mdelay(60); -+ hprt0.b.prtrst = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ -+#ifdef DWC_HS_ELECT_TST -+ case USB_PORT_FEAT_TEST: -+ t = (_wIndex >> 8); /* MSB wIndex USB */ -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t); -+ warn("USB_PORT_FEAT_TEST %d\n", t); -+ if (t < 6) { -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prttstctl = t; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ } else { -+ /* Setup global vars with reg -+ * addresses (quick and dirty hack, -+ * should be cleaned up) -+ */ -+ global_regs = core_if->core_global_regs; -+ hc_global_regs = -+ core_if->host_if->host_global_regs; -+ hc_regs = -+ (struct dwc_otg_hc_regs *) ((char *) -+ global_regs + -+ 0x500); -+ data_fifo = -+ (uint32_t *) ((char *)global_regs + -+ 0x1000); -+ -+ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ -+ /* Save current interrupt mask */ -+ gintmsk.d32 = -+ dwc_read_reg32(&global_regs->gintmsk); -+ -+ /* Disable all interrupts -+ * while we muck with the -+ * hardware directly -+ */ -+ dwc_write_reg32(&global_regs->gintmsk, -+ 0); -+ -+ /* 15 second delay per the test spec */ -+ mdelay(15000); -+ -+ /* Drive suspend on the root port */ -+ hprt0.d32 = -+ dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 1; -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ -+ /* 15 second delay per the test spec */ -+ mdelay(15000); -+ -+ /* Drive resume on the root port */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 0; -+ hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ mdelay(100); -+ -+ /* Clear the resume bit */ -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ -+ /* Restore interrupts */ -+ dwc_write_reg32(&global_regs->gintmsk, -+ gintmsk.d32); -+ } else if (t == 7) { -+ /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ -+ /* Save current interrupt mask */ -+ gintmsk.d32 = -+ dwc_read_reg32(&global_regs->gintmsk); -+ -+ /* -+ * Disable all interrupts -+ * while we muck with the -+ * hardware directly -+ */ -+ dwc_write_reg32(&global_regs->gintmsk, -+ 0); -+ -+ /* 15 second delay per the test spec */ -+ mdelay(15000); -+ -+ /* Send the Setup packet */ -+ do_setup(); -+ -+ /* -+ * 15 second delay so nothing -+ * else happens for awhile. -+ */ -+ mdelay(15000); -+ -+ /* Restore interrupts */ -+ dwc_write_reg32(&global_regs->gintmsk, -+ gintmsk.d32); -+ } else if (t == 8) { -+ /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ -+ /* Save current interrupt mask */ -+ gintmsk.d32 = -+ dwc_read_reg32(&global_regs->gintmsk); -+ -+ /* -+ * Disable all interrupts -+ * while we muck with the -+ * hardware directly -+ */ -+ dwc_write_reg32(&global_regs->gintmsk, -+ 0); -+ -+ /* Send the Setup packet */ -+ do_setup(); -+ -+ /* 15 second delay so nothing else happens for awhile */ -+ mdelay(15000); -+ -+ /* Send the In and Ack packets */ -+ do_in_ack(); -+ -+ /* 15 second delay so nothing else happens for awhile */ -+ mdelay(15000); -+ -+ /* Restore interrupts */ -+ dwc_write_reg32(&global_regs->gintmsk, -+ gintmsk.d32); -+ } -+ } -+ break; -+#endif /* DWC_HS_ELECT_TST */ -+ -+ case USB_PORT_FEAT_INDICATOR: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); -+ /* Not supported */ -+ break; -+ default: -+ retval = -EINVAL; -+ DWC_ERROR("DWC OTG HCD - " -+ "SetPortFeature request %xh " -+ "unknown or unsupported\n", _wValue); -+ break; -+ } -+ break; -+ default: -+error: -+ retval = -EINVAL; -+ DWC_WARN("DWC OTG HCD - Unknown hub control request type or " -+ "invalid typeReq: %xh wIndex: %xh wValue: %xh\n", -+ _typeReq, _wIndex, _wValue); -+ break; -+ } -+ -+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags); -+ -+ return retval; -+} -+ -+/** -+ * Assigns transactions from a QTD to a free host channel and initializes the -+ * host channel to perform the transactions. The host channel is removed from -+ * the free list. -+ * -+ * @hcd: The HCD state structure. -+ * @_qh: Transactions from the first QTD for this QH are selected and -+ * assigned to a free host channel. -+ */ -+static void assign_and_init_hc(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *_qh) -+{ -+ struct dwc_hc *hc; -+ struct dwc_otg_qtd *qtd; -+ struct urb *urb; -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, _qh); -+ -+ hc = list_entry(hcd->free_hc_list.next, struct dwc_hc, hc_list_entry); -+ -+ /* Remove the host channel from the free list. */ -+ list_del_init(&hc->hc_list_entry); -+ -+ qtd = list_entry(_qh->qtd_list.next, struct dwc_otg_qtd, -+ qtd_list_entry); -+ urb = qtd->urb; -+ _qh->channel = hc; -+ _qh->qtd_in_process = qtd; -+ -+ /* -+ * Use usb_pipedevice to determine device address. This address is -+ * 0 before the SET_ADDRESS command and the correct address afterward. -+ */ -+ hc->dev_addr = usb_pipedevice(urb->pipe); -+ hc->ep_num = usb_pipeendpoint(urb->pipe); -+ -+ if (urb->dev->speed == USB_SPEED_LOW) -+ hc->speed = DWC_OTG_EP_SPEED_LOW; -+ else if (urb->dev->speed == USB_SPEED_FULL) -+ hc->speed = DWC_OTG_EP_SPEED_FULL; -+ else -+ hc->speed = DWC_OTG_EP_SPEED_HIGH; -+ -+ hc->max_packet = dwc_max_packet(_qh->maxp); -+ -+ hc->xfer_started = 0; -+ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS; -+ hc->error_state = (qtd->error_count > 0); -+ hc->halt_on_queue = 0; -+ hc->halt_pending = 0; -+ hc->requests = 0; -+ -+ /* -+ * The following values may be modified in the transfer type section -+ * below. The xfer_len value may be reduced when the transfer is -+ * started to accommodate the max widths of the XferSize and PktCnt -+ * fields in the HCTSIZn register. -+ */ -+ hc->do_ping = _qh->ping_state; -+ hc->ep_is_in = (usb_pipein(urb->pipe) != 0); -+ hc->data_pid_start = _qh->data_toggle; -+ hc->multi_count = 1; -+ -+ if (hcd->core_if->dma_enable) { -+#ifdef CONFIG_CPU_CAVIUM_OCTEON -+ const uint64_t USBN_DMA0_INB_CHN0 = -+ CVMX_USBNX_DMA0_INB_CHN0(hcd->core_if->usb_num); -+#endif /* CONFIG_CPU_CAVIUM_OCTEON */ -+ hc->xfer_buff = -+ (uint8_t *) (unsigned long)urb->transfer_dma + -+ urb->actual_length; -+#ifdef CONFIG_CPU_CAVIUM_OCTEON -+ /* Octeon uses external DMA */ -+ wmb(); -+ cvmx_write_csr(USBN_DMA0_INB_CHN0 + hc->hc_num * 8, -+ (unsigned long)hc->xfer_buff); -+ cvmx_read_csr(USBN_DMA0_INB_CHN0 + hc->hc_num * 8); -+ DWC_DEBUGPL(DBG_HCDV, -+ "IN: hc->hc_num = %d, hc->xfer_buff = %p\n", -+ hc->hc_num, hc->xfer_buff); -+#endif /* CONFIG_CPU_CAVIUM_OCTEON */ -+ } else { -+ hc->xfer_buff = -+ (uint8_t *) urb->transfer_buffer + urb->actual_length; -+ } -+ hc->xfer_len = urb->transfer_buffer_length - urb->actual_length; -+ hc->xfer_count = 0; -+ -+ /* -+ * Set the split attributes -+ */ -+ hc->do_split = 0; -+ if (_qh->do_split) { -+ hc->do_split = 1; -+ hc->xact_pos = qtd->isoc_split_pos; -+ hc->complete_split = qtd->complete_split; -+ hc->hub_addr = urb->dev->tt->hub->devnum; -+ hc->port_addr = urb->dev->ttport; -+ } -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_CONTROL: -+ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL; -+ switch (qtd->control_phase) { -+ case DWC_OTG_CONTROL_SETUP: -+ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); -+ hc->do_ping = 0; -+ hc->ep_is_in = 0; -+ hc->data_pid_start = DWC_OTG_HC_PID_SETUP; -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = -+ (uint8_t *) (unsigned long)urb->setup_dma; -+ } else { -+ hc->xfer_buff = (uint8_t *) urb->setup_packet; -+ } -+ hc->xfer_len = 8; -+ break; -+ case DWC_OTG_CONTROL_DATA: -+ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n"); -+ hc->data_pid_start = qtd->data_toggle; -+ break; -+ case DWC_OTG_CONTROL_STATUS: -+ /* -+ * Direction is opposite of data direction or IN if no -+ * data. -+ */ -+ DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n"); -+ if (urb->transfer_buffer_length == 0) { -+ hc->ep_is_in = 1; -+ } else { -+ hc->ep_is_in = -+ (usb_pipein(urb->pipe) != USB_DIR_IN); -+ } -+ if (hc->ep_is_in) -+ hc->do_ping = 0; -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; -+ hc->xfer_len = 0; -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = -+ (uint8_t *) (unsigned long)hcd-> -+ status_buf_dma; -+ } else { -+ hc->xfer_buff = (uint8_t *) hcd->status_buf; -+ } -+ break; -+ } -+ break; -+ case PIPE_BULK: -+ hc->ep_type = DWC_OTG_EP_TYPE_BULK; -+ break; -+ case PIPE_INTERRUPT: -+ hc->ep_type = DWC_OTG_EP_TYPE_INTR; -+ break; -+ case PIPE_ISOCHRONOUS: -+ { -+ struct usb_iso_packet_descriptor *frame_desc; -+ frame_desc = -+ &urb->iso_frame_desc[qtd->isoc_frame_index]; -+ hc->ep_type = DWC_OTG_EP_TYPE_ISOC; -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = -+ (uint8_t *) (unsigned long)urb-> -+ transfer_dma; -+ } else { -+ hc->xfer_buff = -+ (uint8_t *) urb->transfer_buffer; -+ } -+ hc->xfer_buff += -+ frame_desc->offset + qtd->isoc_split_offset; -+ hc->xfer_len = -+ frame_desc->length - qtd->isoc_split_offset; -+ -+ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { -+ if (hc->xfer_len <= 188) { -+ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; -+ } else { -+ hc->xact_pos = -+ DWC_HCSPLIT_XACTPOS_BEGIN; -+ } -+ } -+ } -+ break; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * This value may be modified when the transfer is started to -+ * reflect the actual transfer length. -+ */ -+ hc->multi_count = dwc_hb_mult(_qh->maxp); -+ } -+ -+ dwc_otg_hc_init(hcd->core_if, hc); -+ hc->qh = _qh; -+} -+ -+/** -+ * This function selects transactions from the HCD transfer schedule and -+ * assigns them to available host channels. It is called from HCD interrupt -+ * handler functions. -+ * -+ * @hcd: The HCD state structure. -+ * -+ * Returns The types of new transactions that were assigned to host channels. -+ */ -+enum dwc_otg_transaction_type dwc_otg_hcd_select_transactions(struct dwc_otg_hcd -+ *hcd) -+{ -+ struct list_head *qh_ptr; -+ struct dwc_otg_qh *qh; -+ int num_channels; -+ enum dwc_otg_transaction_type ret_val = DWC_OTG_TRANSACTION_NONE; -+ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); -+#endif -+ -+ /* Process entries in the periodic ready list. */ -+ qh_ptr = hcd->periodic_sched_ready.next; -+ while (qh_ptr != &hcd->periodic_sched_ready && -+ !list_empty(&hcd->free_hc_list)) { -+ -+ qh = list_entry(qh_ptr, struct dwc_otg_qh, qh_list_entry); -+ assign_and_init_hc(hcd, qh); -+ -+ /* -+ * Move the QH from the periodic ready schedule to the -+ * periodic assigned schedule. -+ */ -+ qh_ptr = qh_ptr->next; -+ list_move(&qh->qh_list_entry, &hcd->periodic_sched_assigned); -+ -+ ret_val = DWC_OTG_TRANSACTION_PERIODIC; -+ } -+ -+ /* -+ * Process entries in the inactive portion of the non-periodic -+ * schedule. Some free host channels may not be used if they are -+ * reserved for periodic transfers. -+ */ -+ qh_ptr = hcd->non_periodic_sched_inactive.next; -+ num_channels = hcd->core_if->core_params->host_channels; -+ while (qh_ptr != &hcd->non_periodic_sched_inactive && -+ (hcd->non_periodic_channels < -+ num_channels - hcd->periodic_channels) && -+ !list_empty(&hcd->free_hc_list)) { -+ -+ qh = list_entry(qh_ptr, struct dwc_otg_qh, qh_list_entry); -+ assign_and_init_hc(hcd, qh); -+ -+ /* -+ * Move the QH from the non-periodic inactive schedule to the -+ * non-periodic active schedule. -+ */ -+ qh_ptr = qh_ptr->next; -+ list_move(&qh->qh_list_entry, &hcd->non_periodic_sched_active); -+ -+ if (ret_val == DWC_OTG_TRANSACTION_NONE) -+ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; -+ else -+ ret_val = DWC_OTG_TRANSACTION_ALL; -+ -+ hcd->non_periodic_channels++; -+ } -+ -+ return ret_val; -+} -+ -+/** -+ * Attempts to queue a single transaction request for a host channel -+ * associated with either a periodic or non-periodic transfer. This function -+ * assumes that there is space available in the appropriate request queue. For -+ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space -+ * is available in the appropriate Tx FIFO. -+ * -+ * @hcd: The HCD state structure. -+ * @_hc: Host channel descriptor associated with either a periodic or -+ * non-periodic transfer. -+ * @_fifo_dwords_avail: Number of DWORDs available in the periodic Tx -+ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic -+ * transfers. -+ * -+ * Returns 1 if a request is queued and more requests may be needed to -+ * complete the transfer, 0 if no more requests are required for this -+ * transfer, -1 if there is insufficient space in the Tx FIFO. -+ */ -+static int queue_transaction(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *_hc, uint16_t _fifo_dwords_avail) -+{ -+ int retval; -+ -+ if (hcd->core_if->dma_enable) { -+ if (!_hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, _hc); -+ _hc->qh->ping_state = 0; -+ } -+ retval = 0; -+ } else if (_hc->halt_pending) { -+ /* Don't queue a request if the channel has been halted. */ -+ retval = 0; -+ } else if (_hc->halt_on_queue) { -+ dwc_otg_hc_halt(hcd->core_if, _hc, _hc->halt_status); -+ retval = 0; -+ } else if (_hc->do_ping) { -+ if (!_hc->xfer_started) -+ dwc_otg_hc_start_transfer(hcd->core_if, _hc); -+ retval = 0; -+ } else if (!_hc->ep_is_in || -+ _hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { -+ if ((_fifo_dwords_avail * 4) >= _hc->max_packet) { -+ if (!_hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, _hc); -+ retval = 1; -+ } else { -+ retval = -+ dwc_otg_hc_continue_transfer(hcd->core_if, -+ _hc); -+ } -+ } else { -+ retval = -1; -+ } -+ } else { -+ if (!_hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, _hc); -+ retval = 1; -+ } else { -+ retval = -+ dwc_otg_hc_continue_transfer(hcd->core_if, _hc); -+ } -+ } -+ -+ return retval; -+} -+ -+/** -+ * Processes active non-periodic channels and queues transactions for these -+ * channels to the DWC_otg controller. After queueing transactions, the NP Tx -+ * FIFO Empty interrupt is enabled if there are more transactions to queue as -+ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx -+ * FIFO Empty interrupt is disabled. -+ */ -+static void process_non_periodic_channels(struct dwc_otg_hcd *hcd) -+{ -+ union gnptxsts_data tx_status; -+ struct list_head *orig_qh_ptr; -+ struct dwc_otg_qh *qh; -+ int status; -+ int no_queue_space = 0; -+ int no_fifo_space = 0; -+ int more_to_do = 0; -+ -+ struct dwc_otg_core_global_regs *global_regs = -+ hcd->core_if->core_global_regs; -+ -+ DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " NP Tx Req Queue Space Avail (before queue): %d\n", -+ tx_status.b.nptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", -+ tx_status.b.nptxfspcavail); -+#endif -+ /* -+ * Keep track of the starting point. Skip over the start-of-list -+ * entry. -+ */ -+ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) -+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; -+ -+ orig_qh_ptr = hcd->non_periodic_qh_ptr; -+ -+ /* -+ * Process once through the active list or until no more space is -+ * available in the request queue or the Tx FIFO. -+ */ -+ do { -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ if (!hcd->core_if->dma_enable -+ && tx_status.b.nptxqspcavail == 0) { -+ no_queue_space = 1; -+ break; -+ } -+ -+ qh = list_entry(hcd->non_periodic_qh_ptr, struct dwc_otg_qh, -+ qh_list_entry); -+ status = -+ queue_transaction(hcd, qh->channel, -+ tx_status.b.nptxfspcavail); -+ -+ if (status > 0) { -+ more_to_do = 1; -+ } else if (status < 0) { -+ no_fifo_space = 1; -+ break; -+ } -+ -+ /* Advance to next QH, skipping start-of-list entry. */ -+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; -+ if (hcd->non_periodic_qh_ptr == -+ &hcd->non_periodic_sched_active) { -+ hcd->non_periodic_qh_ptr = -+ hcd->non_periodic_qh_ptr->next; -+ } -+ -+ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); -+ -+ if (!hcd->core_if->dma_enable) { -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ intr_mask.b.nptxfempty = 1; -+ -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " NP Tx Req Queue Space Avail (after queue): %d\n", -+ tx_status.b.nptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, -+ " NP Tx FIFO Space Avail (after queue): %d\n", -+ tx_status.b.nptxfspcavail); -+#endif -+ if (no_queue_space || no_fifo_space) { -+ /* -+ * May need to queue more transactions as the request -+ * queue or Tx FIFO empties. Enable the non-periodic -+ * Tx FIFO empty interrupt. (Always use the half-empty -+ * level to ensure that new requests are loaded as -+ * soon as possible.) -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, -+ intr_mask.d32); -+ } else { -+ /* -+ * Disable the Tx FIFO empty interrupt since there are -+ * no more transactions that need to be queued right -+ * now. This function is called from interrupt -+ * handlers to queue more transactions as transfer -+ * states change. -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, -+ 0); -+ if (more_to_do) { -+ /* When not using DMA, many USB -+ * devices cause excessive loads on -+ * the serial bus simply because they -+ * continuously poll the device for -+ * status. Here we use the timer to -+ * rate limit how fast we can get the -+ * the NP TX fifo empty interrupt. We -+ * leave the interrupt disable until -+ * the timer fires and reenables it */ -+ -+ /* We'll rate limit the interrupt at -+ * 20000 per second. Making this -+ * faster improves USB performance but -+ * uses more CPU */ -+ hrtimer_start_range_ns(&hcd->poll_rate_limit, -+ ktime_set(0, 50000), -+ 5000, HRTIMER_MODE_REL); -+ } -+ } -+ } -+} -+ -+/** -+ * Processes periodic channels for the next frame and queues transactions for -+ * these channels to the DWC_otg controller. After queueing transactions, the -+ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions -+ * to queue as Periodic Tx FIFO or request queue space becomes available. -+ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. -+ */ -+static void process_periodic_channels(struct dwc_otg_hcd *hcd) -+{ -+ union hptxsts_data tx_status; -+ struct list_head *qh_ptr; -+ struct dwc_otg_qh *qh; -+ int status; -+ int no_queue_space = 0; -+ int no_fifo_space = 0; -+ -+ struct dwc_otg_host_global_regs *host_regs; -+ host_regs = hcd->core_if->host_if->host_global_regs; -+ -+ DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " P Tx Req Queue Space Avail (before queue): %d\n", -+ tx_status.b.ptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", -+ tx_status.b.ptxfspcavail); -+#endif -+ -+ qh_ptr = hcd->periodic_sched_assigned.next; -+ while (qh_ptr != &hcd->periodic_sched_assigned) { -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ if (tx_status.b.ptxqspcavail == 0) { -+ no_queue_space = 1; -+ break; -+ } -+ -+ qh = list_entry(qh_ptr, struct dwc_otg_qh, qh_list_entry); -+ -+ /* -+ * Set a flag if we're queuing high-bandwidth in slave mode. -+ * The flag prevents any halts to get into the request queue in -+ * the middle of multiple high-bandwidth packets getting queued. -+ */ -+ if ((!hcd->core_if->dma_enable) && -+ (qh->channel->multi_count > 1)) { -+ hcd->core_if->queuing_high_bandwidth = 1; -+ } -+ -+ status = -+ queue_transaction(hcd, qh->channel, -+ tx_status.b.ptxfspcavail); -+ if (status < 0) { -+ no_fifo_space = 1; -+ break; -+ } -+ -+ /* -+ * In Slave mode, stay on the current transfer until there is -+ * nothing more to do or the high-bandwidth request count is -+ * reached. In DMA mode, only need to queue one request. The -+ * controller automatically handles multiple packets for -+ * high-bandwidth transfers. -+ */ -+ if (hcd->core_if->dma_enable || -+ (status == 0 || -+ qh->channel->requests == qh->channel->multi_count)) { -+ qh_ptr = qh_ptr->next; -+ /* -+ * Move the QH from the periodic assigned schedule to -+ * the periodic queued schedule. -+ */ -+ list_move(&qh->qh_list_entry, -+ &hcd->periodic_sched_queued); -+ -+ /* done queuing high bandwidth */ -+ hcd->core_if->queuing_high_bandwidth = 0; -+ } -+ } -+ -+ if (!hcd->core_if->dma_enable) { -+ struct dwc_otg_core_global_regs *global_regs; -+ union gintmsk_data intr_mask = {.d32 = 0 }; -+ -+ global_regs = hcd->core_if->core_global_regs; -+ intr_mask.b.ptxfempty = 1; -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " P Tx Req Queue Space Avail (after queue): %d\n", -+ tx_status.b.ptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, -+ " P Tx FIFO Space Avail (after queue): %d\n", -+ tx_status.b.ptxfspcavail); -+#endif -+ if (!(list_empty(&hcd->periodic_sched_assigned)) || -+ no_queue_space || no_fifo_space) { -+ /* -+ * May need to queue more transactions as the request -+ * queue or Tx FIFO empties. Enable the periodic Tx -+ * FIFO empty interrupt. (Always use the half-empty -+ * level to ensure that new requests are loaded as -+ * soon as possible.) -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, -+ intr_mask.d32); -+ } else { -+ /* -+ * Disable the Tx FIFO empty interrupt since there are -+ * no more transactions that need to be queued right -+ * now. This function is called from interrupt -+ * handlers to queue more transactions as transfer -+ * states change. -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, -+ 0); -+ } -+ } -+} -+ -+/** -+ * This function processes the currently active host channels and queues -+ * transactions for these channels to the DWC_otg controller. It is called -+ * from HCD interrupt handler functions. -+ * -+ * @hcd: The HCD state structure. -+ * @_tr_type: The type(s) of transactions to queue (non-periodic, -+ * periodic, or both). -+ */ -+void dwc_otg_hcd_queue_transactions(struct dwc_otg_hcd *hcd, -+ enum dwc_otg_transaction_type _tr_type) -+{ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); -+#endif -+ /* Process host channels associated with periodic transfers. */ -+ if ((_tr_type == DWC_OTG_TRANSACTION_PERIODIC || -+ _tr_type == DWC_OTG_TRANSACTION_ALL) && -+ !list_empty(&hcd->periodic_sched_assigned)) { -+ -+ process_periodic_channels(hcd); -+ } -+ -+ /* Process host channels associated with non-periodic transfers. */ -+ if ((_tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || -+ _tr_type == DWC_OTG_TRANSACTION_ALL)) { -+ if (!list_empty(&hcd->non_periodic_sched_active)) { -+ process_non_periodic_channels(hcd); -+ } else { -+ /* -+ * Ensure NP Tx FIFO empty interrupt is disabled when -+ * there are no non-periodic transfers to process. -+ */ -+ union gintmsk_data gintmsk = {.d32 = 0 }; -+ gintmsk.b.nptxfempty = 1; -+ dwc_modify_reg32(&hcd->core_if->core_global_regs-> -+ gintmsk, gintmsk.d32, 0); -+ } -+ } -+} -+ -+/** -+ * Sets the final status of an URB and returns it to the device driver. Any -+ * required cleanup of the URB is performed. -+ */ -+void dwc_otg_hcd_complete_urb(struct dwc_otg_hcd *hcd, struct urb *urb, -+ int status) -+{ -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ DWC_PRINT("%s: urb %p, device %d, ep %d %s, status=%d\n", -+ __func__, urb, usb_pipedevice(urb->pipe), -+ usb_pipeendpoint(urb->pipe), -+ usb_pipein(urb->pipe) ? "IN" : "OUT", status); -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ int i; -+ for (i = 0; i < urb->number_of_packets; i++) { -+ DWC_PRINT(" ISO Desc %d status: %d\n", -+ i, urb->iso_frame_desc[i].status); -+ } -+ } -+ } -+#endif -+ -+ urb->status = status; -+ urb->hcpriv = NULL; -+ -+ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); -+} -+ -+/* -+ * Returns the Queue Head for an URB. -+ */ -+struct dwc_otg_qh *dwc_urb_to_qh(struct urb *urb) -+{ -+ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); -+ return ep->hcpriv; -+} -+ -+#ifdef DEBUG -+void dwc_print_setup_data(uint8_t *setup) -+{ -+ int i; -+ if (CHK_DEBUG_LEVEL(DBG_HCD)) { -+ DWC_PRINT("Setup Data = MSB "); -+ for (i = 7; i >= 0; i--) -+ DWC_PRINT("%02x ", setup[i]); -+ DWC_PRINT("\n"); -+ DWC_PRINT(" bmRequestType Tranfer = %s\n", -+ (setup[0] & 0x80) ? "Device-to-Host" : -+ "Host-to-Device"); -+ DWC_PRINT(" bmRequestType Type = "); -+ switch ((setup[0] & 0x60) >> 5) { -+ case 0: -+ DWC_PRINT("Standard\n"); -+ break; -+ case 1: -+ DWC_PRINT("Class\n"); -+ break; -+ case 2: -+ DWC_PRINT("Vendor\n"); -+ break; -+ case 3: -+ DWC_PRINT("Reserved\n"); -+ break; -+ } -+ DWC_PRINT(" bmRequestType Recipient = "); -+ switch (setup[0] & 0x1f) { -+ case 0: -+ DWC_PRINT("Device\n"); -+ break; -+ case 1: -+ DWC_PRINT("Interface\n"); -+ break; -+ case 2: -+ DWC_PRINT("Endpoint\n"); -+ break; -+ case 3: -+ DWC_PRINT("Other\n"); -+ break; -+ default: -+ DWC_PRINT("Reserved\n"); -+ break; -+ } -+ DWC_PRINT(" bRequest = 0x%0x\n", setup[1]); -+ DWC_PRINT(" wValue = 0x%0x\n", *((uint16_t *) &setup[2])); -+ DWC_PRINT(" wIndex = 0x%0x\n", *((uint16_t *) &setup[4])); -+ DWC_PRINT(" wLength = 0x%0x\n\n", *((uint16_t *) &setup[6])); -+ } -+} -+#endif -+ -+void dwc_otg_hcd_dump_frrem(struct dwc_otg_hcd *hcd) -+{ -+#ifdef DEBUG -+ DWC_PRINT("Frame remaining at SOF:\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->frrem_samples, hcd->frrem_accum, -+ (hcd->frrem_samples > 0) ? -+ hcd->frrem_accum / hcd->frrem_samples : 0); -+ -+ DWC_PRINT("\n"); -+ DWC_PRINT("Frame remaining at start_transfer (uframe 7):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->core_if->hfnum_7_samples, -+ hcd->core_if->hfnum_7_frrem_accum, -+ (hcd->core_if->hfnum_7_samples > -+ 0) ? hcd->core_if->hfnum_7_frrem_accum / -+ hcd->core_if->hfnum_7_samples : 0); -+ DWC_PRINT("Frame remaining at start_transfer (uframe 0):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->core_if->hfnum_0_samples, -+ hcd->core_if->hfnum_0_frrem_accum, -+ (hcd->core_if->hfnum_0_samples > -+ 0) ? hcd->core_if->hfnum_0_frrem_accum / -+ hcd->core_if->hfnum_0_samples : 0); -+ DWC_PRINT("Frame remaining at start_transfer (uframe 1-6):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->core_if->hfnum_other_samples, -+ hcd->core_if->hfnum_other_frrem_accum, -+ (hcd->core_if->hfnum_other_samples > -+ 0) ? hcd->core_if->hfnum_other_frrem_accum / -+ hcd->core_if->hfnum_other_samples : 0); -+ -+ DWC_PRINT("\n"); -+ DWC_PRINT("Frame remaining at sample point A (uframe 7):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, -+ (hcd->hfnum_7_samples_a > 0) ? -+ hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0); -+ DWC_PRINT("Frame remaining at sample point A (uframe 0):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, -+ (hcd->hfnum_0_samples_a > 0) ? -+ hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0); -+ DWC_PRINT("Frame remaining at sample point A (uframe 1-6):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, -+ (hcd->hfnum_other_samples_a > 0) ? -+ hcd->hfnum_other_frrem_accum_a / -+ hcd->hfnum_other_samples_a : 0); -+ -+ DWC_PRINT("\n"); -+ DWC_PRINT("Frame remaining at sample point B (uframe 7):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, -+ (hcd->hfnum_7_samples_b > 0) ? -+ hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0); -+ DWC_PRINT("Frame remaining at sample point B (uframe 0):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, -+ (hcd->hfnum_0_samples_b > 0) ? -+ hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0); -+ DWC_PRINT("Frame remaining at sample point B (uframe 1-6):\n"); -+ DWC_PRINT(" samples %u, accum %lu, avg %lu\n", -+ hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, -+ (hcd->hfnum_other_samples_b > 0) ? -+ hcd->hfnum_other_frrem_accum_b / -+ hcd->hfnum_other_samples_b : 0); -+#endif -+} -+ -+void dwc_otg_hcd_dump_state(struct dwc_otg_hcd *hcd) -+{ -+#ifdef DEBUG -+ int num_channels; -+ int i; -+ union gnptxsts_data np_tx_status; -+ union hptxsts_data p_tx_status; -+ -+ num_channels = hcd->core_if->core_params->host_channels; -+ DWC_PRINT("\n"); -+ DWC_PRINT -+ ("************************************************************\n"); -+ DWC_PRINT("HCD State:\n"); -+ DWC_PRINT(" Num channels: %d\n", num_channels); -+ for (i = 0; i < num_channels; i++) { -+ struct dwc_hc *hc = hcd->hc_ptr_array[i]; -+ DWC_PRINT(" Channel %d:\n", i); -+ DWC_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", -+ hc->dev_addr, hc->ep_num, hc->ep_is_in); -+ DWC_PRINT(" speed: %d\n", hc->speed); -+ DWC_PRINT(" ep_type: %d\n", hc->ep_type); -+ DWC_PRINT(" max_packet: %d\n", hc->max_packet); -+ DWC_PRINT(" data_pid_start: %d\n", hc->data_pid_start); -+ DWC_PRINT(" multi_count: %d\n", hc->multi_count); -+ DWC_PRINT(" xfer_started: %d\n", hc->xfer_started); -+ DWC_PRINT(" xfer_buff: %p\n", hc->xfer_buff); -+ DWC_PRINT(" xfer_len: %d\n", hc->xfer_len); -+ DWC_PRINT(" xfer_count: %d\n", hc->xfer_count); -+ DWC_PRINT(" halt_on_queue: %d\n", hc->halt_on_queue); -+ DWC_PRINT(" halt_pending: %d\n", hc->halt_pending); -+ DWC_PRINT(" halt_status: %d\n", hc->halt_status); -+ DWC_PRINT(" do_split: %d\n", hc->do_split); -+ DWC_PRINT(" complete_split: %d\n", hc->complete_split); -+ DWC_PRINT(" hub_addr: %d\n", hc->hub_addr); -+ DWC_PRINT(" port_addr: %d\n", hc->port_addr); -+ DWC_PRINT(" xact_pos: %d\n", hc->xact_pos); -+ DWC_PRINT(" requests: %d\n", hc->requests); -+ DWC_PRINT(" qh: %p\n", hc->qh); -+ if (hc->xfer_started) { -+ union hfnum_data hfnum; -+ union hcchar_data hcchar; -+ union hctsiz_data hctsiz; -+ union hcint_data hcint; -+ union hcintmsk_data hcintmsk; -+ hfnum.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if-> -+ host_global_regs->hfnum); -+ hcchar.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hcchar); -+ hctsiz.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hctsiz); -+ hcint.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hcint); -+ hcintmsk.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hcintmsk); -+ DWC_PRINT(" hfnum: 0x%08x\n", hfnum.d32); -+ DWC_PRINT(" hcchar: 0x%08x\n", hcchar.d32); -+ DWC_PRINT(" hctsiz: 0x%08x\n", hctsiz.d32); -+ DWC_PRINT(" hcint: 0x%08x\n", hcint.d32); -+ DWC_PRINT(" hcintmsk: 0x%08x\n", hcintmsk.d32); -+ } -+ if (hc->xfer_started && (hc->qh != NULL) -+ && (hc->qh->qtd_in_process != NULL)) { -+ struct dwc_otg_qtd *qtd; -+ struct urb *urb; -+ qtd = hc->qh->qtd_in_process; -+ urb = qtd->urb; -+ DWC_PRINT(" URB Info:\n"); -+ DWC_PRINT(" qtd: %p, urb: %p\n", qtd, urb); -+ if (urb != NULL) { -+ DWC_PRINT(" Dev: %d, EP: %d %s\n", -+ usb_pipedevice(urb->pipe), -+ usb_pipeendpoint(urb->pipe), -+ usb_pipein(urb->pipe) ? "IN" : "OUT"); -+ DWC_PRINT(" Max packet size: %d\n", -+ usb_maxpacket(urb->dev, urb->pipe, -+ usb_pipeout(urb-> -+ pipe))); -+ DWC_PRINT(" transfer_buffer: %p\n", -+ urb->transfer_buffer); -+ DWC_PRINT(" transfer_dma: %p\n", -+ (void *)urb->transfer_dma); -+ DWC_PRINT(" transfer_buffer_length: %d\n", -+ urb->transfer_buffer_length); -+ DWC_PRINT(" actual_length: %d\n", -+ urb->actual_length); -+ } -+ } -+ } -+ DWC_PRINT(" non_periodic_channels: %d\n", hcd->non_periodic_channels); -+ DWC_PRINT(" periodic_channels: %d\n", hcd->periodic_channels); -+ DWC_PRINT(" periodic_usecs: %d\n", hcd->periodic_usecs); -+ np_tx_status.d32 = -+ dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts); -+ DWC_PRINT(" NP Tx Req Queue Space Avail: %d\n", -+ np_tx_status.b.nptxqspcavail); -+ DWC_PRINT(" NP Tx FIFO Space Avail: %d\n", -+ np_tx_status.b.nptxfspcavail); -+ p_tx_status.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts); -+ DWC_PRINT(" P Tx Req Queue Space Avail: %d\n", -+ p_tx_status.b.ptxqspcavail); -+ DWC_PRINT(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); -+ dwc_otg_hcd_dump_frrem(hcd); -+ dwc_otg_dump_global_registers(hcd->core_if); -+ dwc_otg_dump_host_registers(hcd->core_if); -+ DWC_PRINT -+ ("************************************************************\n"); -+ DWC_PRINT("\n"); -+#endif -+} -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -new file mode 100644 -index 0000000..6dcf1f5 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -0,0 +1,661 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+#ifndef DWC_DEVICE_ONLY -+#if !defined(__DWC_HCD_H__) -+#define __DWC_HCD_H__ -+ -+#include -+#include -+#include -+ -+#include <../drivers/usb/core/hcd.h> -+ -+struct dwc_otg_device; -+ -+#include "dwc_otg_cil.h" -+ -+/** -+ * -+ * This file contains the structures, constants, and interfaces for -+ * the Host Contoller Driver (HCD). -+ * -+ * The Host Controller Driver (HCD) is responsible for translating requests -+ * from the USB Driver into the appropriate actions on the DWC_otg controller. -+ * It isolates the USBD from the specifics of the controller by providing an -+ * API to the USBD. -+ */ -+ -+/** -+ * Phases for control transfers. -+ */ -+enum dwc_otg_control_phase { -+ DWC_OTG_CONTROL_SETUP, -+ DWC_OTG_CONTROL_DATA, -+ DWC_OTG_CONTROL_STATUS -+}; -+ -+/** Transaction types. */ -+enum dwc_otg_transaction_type { -+ DWC_OTG_TRANSACTION_NONE, -+ DWC_OTG_TRANSACTION_PERIODIC, -+ DWC_OTG_TRANSACTION_NON_PERIODIC, -+ DWC_OTG_TRANSACTION_ALL -+}; -+ -+struct dwc_otg_qh; -+ -+/* -+ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, -+ * interrupt, or isochronous transfer. A single QTD is created for each URB -+ * (of one of these types) submitted to the HCD. The transfer associated with -+ * a QTD may require one or multiple transactions. -+ * -+ * A QTD is linked to a Queue Head, which is entered in either the -+ * non-periodic or periodic schedule for execution. When a QTD is chosen for -+ * execution, some or all of its transactions may be executed. After -+ * execution, the state of the QTD is updated. The QTD may be retired if all -+ * its transactions are complete or if an error occurred. Otherwise, it -+ * remains in the schedule so more transactions can be executed later. -+ */ -+struct dwc_otg_qtd { -+ /* -+ * Determines the PID of the next data packet for the data phase of -+ * control transfers. Ignored for other transfer types.
-+ * One of the following values: -+ * - DWC_OTG_HC_PID_DATA0 -+ * - DWC_OTG_HC_PID_DATA1 -+ */ -+ uint8_t data_toggle; -+ -+ /** Current phase for control transfers (Setup, Data, or Status). */ -+ enum dwc_otg_control_phase control_phase; -+ -+ /** Keep track of the current split type -+ * for FS/LS endpoints on a HS Hub */ -+ uint8_t complete_split; -+ -+ /** How many bytes transferred during SSPLIT OUT */ -+ uint32_t ssplit_out_xfer_count; -+ -+ /** -+ * Holds the number of bus errors that have occurred for a transaction -+ * within this transfer. -+ */ -+ uint8_t error_count; -+ -+ /** -+ * Index of the next frame descriptor for an isochronous transfer. A -+ * frame descriptor describes the buffer position and length of the -+ * data to be transferred in the next scheduled (micro)frame of an -+ * isochronous transfer. It also holds status for that transaction. -+ * The frame index starts at 0. -+ */ -+ int isoc_frame_index; -+ -+ /** Position of the ISOC split on full/low speed */ -+ uint8_t isoc_split_pos; -+ -+ /** Position of the ISOC split in the buffer for the current frame */ -+ uint16_t isoc_split_offset; -+ -+ /** URB for this transfer */ -+ struct urb *urb; -+ -+ /* The queue head for this transfer. */ -+ struct dwc_otg_qh *qh; -+ -+ /** This list of QTDs */ -+ struct list_head qtd_list_entry; -+ -+}; -+ -+/** -+ * A Queue Head (QH) holds the static characteristics of an endpoint and -+ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may -+ * be entered in either the non-periodic or periodic schedule. -+ */ -+struct dwc_otg_qh { -+ /** -+ * Endpoint type. -+ * One of the following values: -+ * - USB_ENDPOINT_XFER_CONTROL -+ * - USB_ENDPOINT_XFER_ISOC -+ * - USB_ENDPOINT_XFER_BULK -+ * - USB_ENDPOINT_XFER_INT -+ */ -+ uint8_t ep_type; -+ uint8_t ep_is_in; -+ -+ /** wMaxPacketSize Field of Endpoint Descriptor. */ -+ uint16_t maxp; -+ -+ /** -+ * Determines the PID of the next data packet for non-control -+ * transfers. Ignored for control transfers.
-+ * One of the following values: -+ * - DWC_OTG_HC_PID_DATA0 -+ * - DWC_OTG_HC_PID_DATA1 -+ */ -+ uint8_t data_toggle; -+ -+ /** Ping state if 1. */ -+ uint8_t ping_state; -+ -+ /** -+ * List of QTDs for this QH. -+ */ -+ struct list_head qtd_list; -+ -+ /** Host channel currently processing transfers for this QH. */ -+ struct dwc_hc *channel; -+ -+ /** QTD currently assigned to a host channel for this QH. */ -+ struct dwc_otg_qtd *qtd_in_process; -+ -+ /** Full/low speed endpoint on high-speed hub requires split. */ -+ uint8_t do_split; -+ -+ /** @name Periodic schedule information */ -+ /** @{ */ -+ -+ /** Bandwidth in microseconds per (micro)frame. */ -+ uint8_t usecs; -+ -+ /** Interval between transfers in (micro)frames. */ -+ uint16_t interval; -+ -+ /** -+ * (micro)frame to initialize a periodic transfer. The transfer -+ * executes in the following (micro)frame. -+ */ -+ uint16_t sched_frame; -+ -+ /** (micro)frame at which last start split was initialized. */ -+ uint16_t start_split_frame; -+ -+ /** @} */ -+ -+ /** Entry for QH in either the periodic or non-periodic schedule. */ -+ struct list_head qh_list_entry; -+}; -+ -+/** -+ * This structure holds the state of the HCD, including the non-periodic and -+ * periodic schedules. -+ */ -+struct dwc_otg_hcd { -+ -+ /** DWC OTG Core Interface Layer */ -+ struct dwc_otg_core_if *core_if; -+ -+ /** Internal DWC HCD Flags */ -+ union dwc_otg_hcd_internal_flags { -+ uint32_t d32; -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:26; -+ unsigned port_over_current_change:1; -+ unsigned port_suspend_change:1; -+ unsigned port_enable_change:1; -+ unsigned port_reset_change:1; -+ unsigned port_connect_status:1; -+ unsigned port_connect_status_change:1; -+#else -+ unsigned port_connect_status_change:1; -+ unsigned port_connect_status:1; -+ unsigned port_reset_change:1; -+ unsigned port_enable_change:1; -+ unsigned port_suspend_change:1; -+ unsigned port_over_current_change:1; -+ unsigned reserved:26; -+#endif -+ } b; -+ } flags; -+ -+ /** -+ * Inactive items in the non-periodic schedule. This is a list of -+ * Queue Heads. Transfers associated with these Queue Heads are not -+ * currently assigned to a host channel. -+ */ -+ struct list_head non_periodic_sched_inactive; -+ -+ /** -+ * Active items in the non-periodic schedule. This is a list of -+ * Queue Heads. Transfers associated with these Queue Heads are -+ * currently assigned to a host channel. -+ */ -+ struct list_head non_periodic_sched_active; -+ -+ /** -+ * Pointer to the next Queue Head to process in the active -+ * non-periodic schedule. -+ */ -+ struct list_head *non_periodic_qh_ptr; -+ -+ /** -+ * Inactive items in the periodic schedule. This is a list of QHs for -+ * periodic transfers that are _not_ scheduled for the next frame. -+ * Each QH in the list has an interval counter that determines when it -+ * needs to be scheduled for execution. This scheduling mechanism -+ * allows only a simple calculation for periodic bandwidth used (i.e. -+ * must assume that all periodic transfers may need to execute in the -+ * same frame). However, it greatly simplifies scheduling and should -+ * be sufficient for the vast majority of OTG hosts, which need to -+ * connect to a small number of peripherals at one time. -+ * -+ * Items move from this list to periodic_sched_ready when the QH -+ * interval counter is 0 at SOF. -+ */ -+ struct list_head periodic_sched_inactive; -+ -+ /** -+ * List of periodic QHs that are ready for execution in the next -+ * frame, but have not yet been assigned to host channels. -+ * -+ * Items move from this list to periodic_sched_assigned as host -+ * channels become available during the current frame. -+ */ -+ struct list_head periodic_sched_ready; -+ -+ /** -+ * List of periodic QHs to be executed in the next frame that are -+ * assigned to host channels. -+ * -+ * Items move from this list to periodic_sched_queued as the -+ * transactions for the QH are queued to the DWC_otg controller. -+ */ -+ struct list_head periodic_sched_assigned; -+ -+ /** -+ * List of periodic QHs that have been queued for execution. -+ * -+ * Items move from this list to either periodic_sched_inactive or -+ * periodic_sched_ready when the channel associated with the transfer -+ * is released. If the interval for the QH is 1, the item moves to -+ * periodic_sched_ready because it must be rescheduled for the next -+ * frame. Otherwise, the item moves to periodic_sched_inactive. -+ */ -+ struct list_head periodic_sched_queued; -+ -+ /** -+ * Total bandwidth claimed so far for periodic transfers. This value -+ * is in microseconds per (micro)frame. The assumption is that all -+ * periodic transfers may occur in the same (micro)frame. -+ */ -+ uint16_t periodic_usecs; -+ -+ /** -+ * Frame number read from the core at SOF. The value ranges from 0 to -+ * DWC_HFNUM_MAX_FRNUM. -+ */ -+ uint16_t frame_number; -+ -+ /** -+ * Free host channels in the controller. This is a list of -+ * struct dwc_hc items. -+ */ -+ struct list_head free_hc_list; -+ -+ /** -+ * Number of host channels assigned to periodic transfers. Currently -+ * assuming that there is a dedicated host channel for each periodic -+ * transaction and at least one host channel available for -+ * non-periodic transactions. -+ */ -+ int periodic_channels; -+ -+ /** -+ * Number of host channels assigned to non-periodic transfers. -+ */ -+ int non_periodic_channels; -+ -+ /** -+ * Array of pointers to the host channel descriptors. Allows accessing -+ * a host channel descriptor given the host channel number. This is -+ * useful in interrupt handlers. -+ */ -+ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; -+ -+ /** -+ * Buffer to use for any data received during the status phase of a -+ * control transfer. Normally no data is transferred during the status -+ * phase. This buffer is used as a bit bucket. -+ */ -+ uint8_t *status_buf; -+ -+ /** -+ * DMA address for status_buf. -+ */ -+ dma_addr_t status_buf_dma; -+#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 -+ -+ /** -+ * Structure to allow starting the HCD in a non-interrupt context -+ * during an OTG role change. -+ */ -+ struct work_struct start_work; -+ -+ /** -+ * Connection timer. An OTG host must display a message if the device -+ * does not connect. Started when the VBus power is turned on via -+ * sysfs attribute "buspower". -+ */ -+ struct timer_list conn_timer; -+ -+ /* Tasket to do a reset */ -+ struct tasklet_struct *reset_tasklet; -+ -+ struct hrtimer poll_rate_limit; -+ -+ spinlock_t global_lock; -+ -+#ifdef DEBUG -+ uint32_t frrem_samples; -+ uint64_t frrem_accum; -+ -+ uint32_t hfnum_7_samples_a; -+ uint64_t hfnum_7_frrem_accum_a; -+ uint32_t hfnum_0_samples_a; -+ uint64_t hfnum_0_frrem_accum_a; -+ uint32_t hfnum_other_samples_a; -+ uint64_t hfnum_other_frrem_accum_a; -+ -+ uint32_t hfnum_7_samples_b; -+ uint64_t hfnum_7_frrem_accum_b; -+ uint32_t hfnum_0_samples_b; -+ uint64_t hfnum_0_frrem_accum_b; -+ uint32_t hfnum_other_samples_b; -+ uint64_t hfnum_other_frrem_accum_b; -+#endif -+ -+}; -+ -+/** Gets the dwc_otg_hcd from a struct usb_hcd */ -+static inline struct dwc_otg_hcd *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd) -+{ -+ return (struct dwc_otg_hcd *)(hcd->hcd_priv); -+} -+ -+/** Gets the struct usb_hcd that contains a struct dwc_otg_hcd. */ -+static inline struct usb_hcd *dwc_otg_hcd_to_hcd(struct dwc_otg_hcd -+ *dwc_otg_hcd) -+{ -+ return container_of((void *)dwc_otg_hcd, struct usb_hcd, hcd_priv); -+} -+ -+/** @name HCD Create/Destroy Functions */ -+/** @{ */ -+extern int __init dwc_otg_hcd_init(struct device *_dev); -+extern void dwc_otg_hcd_remove(struct device *_dev); -+/** @} */ -+ -+/** @name Linux HC Driver API Functions */ -+ -+extern int dwc_otg_hcd_start(struct usb_hcd *hcd); -+extern void dwc_otg_hcd_stop(struct usb_hcd *hcd); -+extern int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd); -+extern void dwc_otg_hcd_free(struct usb_hcd *hcd); -+extern int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, -+ struct urb *urb, unsigned mem_flags); -+extern int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, -+ struct urb *urb, int status); -+extern void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd, -+ struct usb_host_endpoint *ep); -+extern irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); -+extern int dwc_otg_hcd_hub_status_data(struct usb_hcd *hcd, char *buf); -+extern int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, -+ u16 typeReq, -+ u16 wValue, -+ u16 wIndex, char *buf, u16 wLength); -+ -+ -+/** @name Transaction Execution Functions */ -+extern enum dwc_otg_transaction_type dwc_otg_hcd_select_transactions(struct -+ dwc_otg_hcd -+ *hcd); -+extern void dwc_otg_hcd_queue_transactions(struct dwc_otg_hcd *hcd, -+ enum dwc_otg_transaction_type tr_type); -+extern void dwc_otg_hcd_complete_urb(struct dwc_otg_hcd *hcd, struct urb *urb, -+ int status); -+ -+/** @name Interrupt Handler Functions */ -+extern int32_t dwc_otg_hcd_handle_intr(struct dwc_otg_hcd *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_sof_intr(struct dwc_otg_hcd *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_port_intr(struct dwc_otg_hcd *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_disconnect_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_hc_intr(struct dwc_otg_hcd *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_hc_n_intr(struct dwc_otg_hcd *dwc_otg_hcd, -+ uint32_t num); -+extern int32_t dwc_otg_hcd_handle_session_req_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(struct dwc_otg_hcd -+ *dwc_otg_hcd); -+ -+/** @name Schedule Queue Functions */ -+ -+/* Implemented in dwc_otg_hcd_queue.c */ -+extern struct dwc_otg_qh *dwc_otg_hcd_qh_create(struct dwc_otg_hcd *hcd, -+ struct urb *urb); -+extern void dwc_otg_hcd_qh_init(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh, -+ struct urb *urb); -+extern void dwc_otg_hcd_qh_free(struct dwc_otg_qh *qh); -+extern int dwc_otg_hcd_qh_add(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh); -+extern void dwc_otg_hcd_qh_remove(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh); -+extern void dwc_otg_hcd_qh_deactivate(struct dwc_otg_hcd *hcd, -+ struct dwc_otg_qh *qh, int sched_csplit); -+ -+/** Remove and free a QH */ -+static inline void dwc_otg_hcd_qh_remove_and_free(struct dwc_otg_hcd *hcd, -+ struct dwc_otg_qh *qh) -+{ -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ dwc_otg_hcd_qh_free(qh); -+} -+ -+/** Allocates memory for a QH structure. -+ * Returns Returns the memory allocate or NULL on error. */ -+static inline struct dwc_otg_qh *dwc_otg_hcd_qh_alloc(void) -+{ -+ return kmalloc(sizeof(struct dwc_otg_qh), GFP_ATOMIC); -+} -+ -+extern struct dwc_otg_qtd *dwc_otg_hcd_qtd_create(struct urb *urb); -+extern void dwc_otg_hcd_qtd_init(struct dwc_otg_qtd *qtd, struct urb *urb); -+extern int dwc_otg_hcd_qtd_add(struct dwc_otg_qtd *qtd, -+ struct dwc_otg_hcd *dwc_otg_hcd); -+ -+/** Allocates memory for a QTD structure. -+ * Returns Returns the memory allocate or NULL on error. */ -+static inline struct dwc_otg_qtd *dwc_otg_hcd_qtd_alloc(void) -+{ -+ return kmalloc(sizeof(struct dwc_otg_qtd), GFP_ATOMIC); -+} -+ -+/** -+ * Frees the memory for a QTD structure. QTD should already be removed from -+ * list. -+ * @qtd: QTD to free. -+ */ -+static inline void dwc_otg_hcd_qtd_free(struct dwc_otg_qtd *qtd) -+{ -+ kfree(qtd); -+} -+ -+/** -+ * Removes a QTD from list. -+ * @qtd: QTD to remove from list. -+ */ -+static inline void dwc_otg_hcd_qtd_remove(struct dwc_otg_qtd *qtd) -+{ -+ list_del(&qtd->qtd_list_entry); -+} -+ -+/** Remove and free a QTD */ -+static inline void dwc_otg_hcd_qtd_remove_and_free(struct dwc_otg_qtd *qtd) -+{ -+ dwc_otg_hcd_qtd_remove(qtd); -+ dwc_otg_hcd_qtd_free(qtd); -+} -+ -+/** @name Internal Functions */ -+struct dwc_otg_qh *dwc_urb_to_qh(struct urb *urb); -+void dwc_otg_hcd_dump_frrem(struct dwc_otg_hcd *hcd); -+void dwc_otg_hcd_dump_state(struct dwc_otg_hcd *hcd); -+ -+/** Gets the usb_host_endpoint associated with an URB. */ -+static inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) -+{ -+ struct usb_device *dev = urb->dev; -+ int ep_num = usb_pipeendpoint(urb->pipe); -+ -+ if (usb_pipein(urb->pipe)) -+ return dev->ep_in[ep_num]; -+ else -+ return dev->ep_out[ep_num]; -+} -+ -+/* -+ * Gets the endpoint number from a bEndpointAddress argument. The endpoint is -+ * qualified with its direction (possible 32 endpoints per device). -+ */ -+#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) \ -+ ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ -+ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) -+ -+/** Gets the QH that contains the list_head */ -+#define dwc_list_to_qh(_list_head_ptr_) \ -+ (container_of(_list_head_ptr_, struct dwc_otg_qh, qh_list_entry)) -+ -+/** Gets the QTD that contains the list_head */ -+#define dwc_list_to_qtd(_list_head_ptr_) \ -+ (container_of(_list_head_ptr_, struct dwc_otg_qtd, qtd_list_entry)) -+ -+/** Check if QH is non-periodic */ -+#define dwc_qh_is_non_per(_qh_ptr_) \ -+ ((_qh_ptr_->ep_type == USB_ENDPOINT_XFER_BULK) || \ -+ (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL)) -+ -+/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ -+#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -+ -+/** Packet size for any kind of endpoint descriptor */ -+#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) -+ -+/** -+ * Returns true if frame1 is less than or equal to frame2. The comparison is -+ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the -+ * frame number when the max frame number is reached. -+ */ -+static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) -+{ -+ return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= -+ (DWC_HFNUM_MAX_FRNUM >> 1); -+} -+ -+/** -+ * Returns true if frame1 is greater than frame2. The comparison is done -+ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame -+ * number when the max frame number is reached. -+ */ -+static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) -+{ -+ return (frame1 != frame2) && -+ (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < -+ (DWC_HFNUM_MAX_FRNUM >> 1)); -+} -+ -+/** -+ * Increments frame by the amount specified by inc. The addition is done -+ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. -+ */ -+static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) -+{ -+ return (frame + inc) & DWC_HFNUM_MAX_FRNUM; -+} -+ -+static inline uint16_t dwc_full_frame_num(uint16_t frame) -+{ -+ return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; -+} -+ -+static inline uint16_t dwc_micro_frame_num(uint16_t frame) -+{ -+ return frame & 0x7; -+} -+ -+#ifdef DEBUG -+/** -+ * Macro to sample the remaining PHY clocks left in the current frame. This -+ * may be used during debugging to determine the average time it takes to -+ * execute sections of code. There are two possible sample points, "a" and -+ * "b", so the letter argument must be one of these values. -+ * -+ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For -+ * example, "cat /sys/devices/lm0/hcd_frrem". -+ */ -+#define dwc_sample_frrem(_hcd, _qh, _letter) \ -+{ \ -+ union hfnum_data hfnum; \ -+ struct dwc_otg_qtd *qtd; \ -+ qtd = list_entry(_qh->qtd_list.next, struct dwc_otg_qtd, qtd_list_entry); \ -+ if (usb_pipeint(qtd->urb->pipe) && qh->start_split_frame != 0 && !qtd->complete_split) { \ -+ hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ -+ switch (hfnum.b.frnum & 0x7) { \ -+ case 7: \ -+ _hcd->hfnum_7_samples_##_letter++; \ -+ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ -+ break; \ -+ case 0: \ -+ _hcd->hfnum_0_samples_##_letter++; \ -+ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ -+ break; \ -+ default: \ -+ _hcd->hfnum_other_samples_##_letter++; \ -+ _hcd->hfnum_other_frrem_accum_##_letter += \ -+ hfnum.b.frrem; \ -+ break; \ -+ } \ -+ } \ -+} -+#else -+#define dwc_sample_frrem(hcd, qh, letter) -+#endif -+#endif -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -new file mode 100644 -index 0000000..2c4266f ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -0,0 +1,1890 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+#ifndef DWC_DEVICE_ONLY -+ -+#include "dwc_otg_driver.h" -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+/* -+ * This file contains the implementation of the HCD Interrupt handlers. -+ */ -+ -+/* This function handles interrupts for the HCD. */ -+int32_t dwc_otg_hcd_handle_intr(struct dwc_otg_hcd *dwc_otg_hcd) -+{ -+ int retval = 0; -+ -+ struct dwc_otg_core_if *core_if = dwc_otg_hcd->core_if; -+ union gintsts_data gintsts; -+#ifdef DEBUG -+ struct dwc_otg_core_global_regs *global_regs = -+ core_if->core_global_regs; -+#endif -+ -+ /* Check if HOST Mode */ -+ if (dwc_otg_is_host_mode(core_if)) { -+ gintsts.d32 = dwc_otg_read_core_intr(core_if); -+ if (!gintsts.d32) -+ return 0; -+#ifdef DEBUG -+ /* Don't print debug message in the interrupt handler on SOF */ -+# ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+# endif -+ DWC_DEBUGPL(DBG_HCD, "\n"); -+#endif -+ -+#ifdef DEBUG -+# ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+# endif -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Interrupt Detected " -+ "gintsts&gintmsk=0x%08x\n", -+ gintsts.d32); -+#endif -+ -+ if (gintsts.b.sofintr) -+ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); -+ -+ if (gintsts.b.rxstsqlvl) -+ retval |= -+ dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd); -+ -+ if (gintsts.b.nptxfempty) -+ retval |= -+ dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd); -+ -+ if (gintsts.b.i2cintr) -+ ;/** @todo Implement i2cintr handler. */ -+ -+ if (gintsts.b.portintr) -+ retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); -+ -+ if (gintsts.b.hcintr) -+ retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); -+ -+ if (gintsts.b.ptxfempty) { -+ retval |= -+ dwc_otg_hcd_handle_perio_tx_fifo_empty_intr -+ (dwc_otg_hcd); -+ } -+#ifdef DEBUG -+# ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+# endif -+ { -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD Finished Servicing Interrupts\n"); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", -+ dwc_read_reg32(&global_regs->gintsts)); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", -+ dwc_read_reg32(&global_regs->gintmsk)); -+ } -+#endif -+ -+#ifdef DEBUG -+# ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+# endif -+ DWC_DEBUGPL(DBG_HCD, "\n"); -+#endif -+ -+ } -+ -+ return retval; -+} -+ -+#ifdef DWC_TRACK_MISSED_SOFS -+#warning Compiling code to track missed SOFs -+#define FRAME_NUM_ARRAY_SIZE 1000 -+/** -+ * This function is for debug only. -+ */ -+static inline void track_missed_sofs(uint16_t _curr_frame_number) -+{ -+ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; -+ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; -+ static int frame_num_idx; -+ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; -+ static int dumped_frame_num_array; -+ -+ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { -+ if ((((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != -+ _curr_frame_number)) { -+ frame_num_array[frame_num_idx] = _curr_frame_number; -+ last_frame_num_array[frame_num_idx++] = last_frame_num; -+ } -+ } else if (!dumped_frame_num_array) { -+ int i; -+ printk(KERN_EMERG USB_DWC "Frame Last Frame\n"); -+ printk(KERN_EMERG USB_DWC "----- ----------\n"); -+ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { -+ printk(KERN_EMERG USB_DWC "0x%04x 0x%04x\n", -+ frame_num_array[i], last_frame_num_array[i]); -+ } -+ dumped_frame_num_array = 1; -+ } -+ last_frame_num = _curr_frame_number; -+} -+#endif -+ -+/** -+ * Handles the start-of-frame interrupt in host mode. Non-periodic -+ * transactions may be queued to the DWC_otg controller for the current -+ * (micro)frame. Periodic transactions may be queued to the controller for the -+ * next (micro)frame. -+ */ -+int32_t dwc_otg_hcd_handle_sof_intr(struct dwc_otg_hcd *hcd) -+{ -+ union hfnum_data hfnum; -+ struct list_head *qh_entry; -+ struct dwc_otg_qh *qh; -+ enum dwc_otg_transaction_type tr_type; -+ union gintsts_data gintsts = {.d32 = 0 }; -+ -+ hfnum.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); -+ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); -+#endif -+ -+ hcd->frame_number = hfnum.b.frnum; -+ -+#ifdef DEBUG -+ hcd->frrem_accum += hfnum.b.frrem; -+ hcd->frrem_samples++; -+#endif -+ -+#ifdef DWC_TRACK_MISSED_SOFS -+ track_missed_sofs(hcd->frame_number); -+#endif -+ -+ /* Determine whether any periodic QHs should be executed. */ -+ qh_entry = hcd->periodic_sched_inactive.next; -+ while (qh_entry != &hcd->periodic_sched_inactive) { -+ qh = list_entry(qh_entry, struct dwc_otg_qh, qh_list_entry); -+ qh_entry = qh_entry->next; -+ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { -+ /* -+ * Move QH to the ready list to be executed next -+ * (micro)frame. -+ */ -+ list_move(&qh->qh_list_entry, -+ &hcd->periodic_sched_ready); -+ } -+ } -+ -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE) { -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } else if (list_empty(&hcd->periodic_sched_inactive) && -+ list_empty(&hcd->periodic_sched_ready) && -+ list_empty(&hcd->periodic_sched_assigned) && -+ list_empty(&hcd->periodic_sched_queued)) { -+ /* -+ * We don't have USB data to send. Unfortunately the -+ * Synopsis block continues to generate interrupts at -+ * about 8k/sec. In order not waste time on these -+ * useless interrupts, we're going to disable the SOF -+ * interrupt. It will be re-enabled when a new packet -+ * is enqueued in dwc_otg_hcd_urb_enqueue() -+ */ -+ dwc_modify_reg32(&hcd->core_if->core_global_regs->gintmsk, -+ DWC_SOF_INTR_MASK, 0); -+ } -+ -+ /* Clear interrupt */ -+ gintsts.b.sofintr = 1; -+ dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/* Handles the Rx Status Queue Level Interrupt, which indicates that -+ * there is at least one packet in the Rx FIFO. The packets are moved -+ * from the FIFO to memory if the DWC_otg controller is operating in -+ * Slave mode. */ -+int32_t -+dwc_otg_hcd_handle_rx_status_q_level_intr(struct dwc_otg_hcd *dwc_otg_hcd) -+{ -+ union host_grxsts_data grxsts; -+ struct dwc_hc *hc = NULL; -+ -+ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); -+ -+ grxsts.d32 = -+ dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); -+ -+ hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; -+ -+ /* Packet Status */ -+ DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); -+ DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); -+ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, -+ hc->data_pid_start); -+ DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); -+ -+ switch (grxsts.b.pktsts) { -+ case DWC_GRXSTS_PKTSTS_IN: -+ /* Read the data into the host buffer. */ -+ if (grxsts.b.bcnt > 0) { -+ dwc_otg_read_packet(dwc_otg_hcd->core_if, -+ hc->xfer_buff, grxsts.b.bcnt); -+ -+ /* Update the HC fields for the next packet received. */ -+ hc->xfer_count += grxsts.b.bcnt; -+ hc->xfer_buff += grxsts.b.bcnt; -+ } -+ -+ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: -+ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: -+ case DWC_GRXSTS_PKTSTS_CH_HALTED: -+ /* Handled in interrupt, just ignore data */ -+ break; -+ default: -+ DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", -+ grxsts.b.pktsts); -+ break; -+ } -+ -+ return 1; -+} -+ -+/* This interrupt occurs when the non-periodic Tx FIFO is -+ * half-empty. More data packets may be written to the FIFO for OUT -+ * transfers. More requests may be written to the non-periodic request -+ * queue for IN transfers. This interrupt is enabled only in Slave -+ * mode. */ -+int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(struct dwc_otg_hcd * -+ dwc_otg_hcd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); -+ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, -+ DWC_OTG_TRANSACTION_NON_PERIODIC); -+ return 1; -+} -+ -+/* This interrupt occurs when the periodic Tx FIFO is half-empty. More -+ * data packets may be written to the FIFO for OUT transfers. More -+ * requests may be written to the periodic request queue for IN -+ * transfers. This interrupt is enabled only in Slave mode. */ -+int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(struct dwc_otg_hcd * -+ dwc_otg_hcd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); -+ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, -+ DWC_OTG_TRANSACTION_PERIODIC); -+ return 1; -+} -+ -+/* There are multiple conditions that can cause a port interrupt. This -+ * function determines which interrupt conditions have occurred and -+ * handles them appropriately. */ -+int32_t dwc_otg_hcd_handle_port_intr(struct dwc_otg_hcd *dwc_otg_hcd) -+{ -+ int retval = 0; -+ union hprt0_data hprt0; -+ union hprt0_data hprt0_modify; -+ -+ hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); -+ hprt0_modify.d32 = -+ dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); -+ -+ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in -+ * GINTSTS */ -+ -+ hprt0_modify.b.prtena = 0; -+ hprt0_modify.b.prtconndet = 0; -+ hprt0_modify.b.prtenchng = 0; -+ hprt0_modify.b.prtovrcurrchng = 0; -+ -+ /* Port Connect Detected -+ * Set flag and clear if detected */ -+ if (hprt0.b.prtconndet) { -+ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " -+ "Port Connect Detected--\n", hprt0.d32); -+ dwc_otg_hcd->flags.b.port_connect_status_change = 1; -+ dwc_otg_hcd->flags.b.port_connect_status = 1; -+ hprt0_modify.b.prtconndet = 1; -+ -+ /* B-Device has connected, Delete the connection timer. */ -+ del_timer(&dwc_otg_hcd->conn_timer); -+ -+ /* The Hub driver asserts a reset when it sees port connect -+ * status change flag */ -+ retval |= 1; -+ } -+ -+ /* Port Enable Changed -+ * Clear if detected - Set internal flag if disabled */ -+ if (hprt0.b.prtenchng) { -+ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " -+ "Port Enable Changed--\n", hprt0.d32); -+ hprt0_modify.b.prtenchng = 1; -+ if (hprt0.b.prtena == 1) { -+ int do_reset = 0; -+ struct dwc_otg_core_params *params = -+ dwc_otg_hcd->core_if->core_params; -+ struct dwc_otg_core_global_regs *global_regs = -+ dwc_otg_hcd->core_if->core_global_regs; -+ struct dwc_otg_host_if *host_if = -+ dwc_otg_hcd->core_if->host_if; -+ -+ /* Check if we need to adjust the PHY clock speed for -+ * low power and adjust it */ -+ if (params->host_support_fs_ls_low_power) { -+ union gusbcfg_data usbcfg; -+ -+ usbcfg.d32 = -+ dwc_read_reg32(&global_regs->gusbcfg); -+ -+ if ((hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) -+ || (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED)) { -+ /* -+ * Low power -+ */ -+ union hcfg_data hcfg; -+ if (usbcfg.b.phylpwrclksel == 0) { -+ /* Set PHY low power clock select for FS/LS devices */ -+ usbcfg.b.phylpwrclksel = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, -+ usbcfg.d32); -+ do_reset = 1; -+ } -+ -+ hcfg.d32 = -+ dwc_read_reg32(&host_if->host_global_regs->hcfg); -+ -+ if ((hprt0.b.prtspd == -+ DWC_HPRT0_PRTSPD_LOW_SPEED) -+ && (params-> -+ host_ls_low_power_phy_clk == -+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) { -+ /* 6 MHZ */ -+ DWC_DEBUGPL(DBG_CIL, -+ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); -+ if (hcfg.b.fslspclksel != -+ DWC_HCFG_6_MHZ) { -+ hcfg.b.fslspclksel = -+ DWC_HCFG_6_MHZ; -+ dwc_write_reg32(&host_if->host_global_regs->hcfg, -+ hcfg.d32); -+ do_reset = 1; -+ } -+ } else { -+ /* 48 MHZ */ -+ DWC_DEBUGPL(DBG_CIL, -+ "FS_PHY programming HCFG to 48 MHz ()\n"); -+ if (hcfg.b.fslspclksel != -+ DWC_HCFG_48_MHZ) { -+ hcfg.b.fslspclksel = DWC_HCFG_48_MHZ; -+ dwc_write_reg32(&host_if->host_global_regs->hcfg, -+ hcfg.d32); -+ do_reset = 1; -+ } -+ } -+ } else { -+ /* -+ * Not low power -+ */ -+ if (usbcfg.b.phylpwrclksel == 1) { -+ usbcfg.b.phylpwrclksel = 0; -+ dwc_write_reg32(&global_regs->gusbcfg, -+ usbcfg.d32); -+ do_reset = 1; -+ } -+ } -+ if (do_reset) -+ tasklet_schedule(dwc_otg_hcd->reset_tasklet); -+ } -+ if (!do_reset) -+ /* -+ * Port has been enabled set the reset -+ * change flag -+ */ -+ dwc_otg_hcd->flags.b.port_reset_change = 1; -+ } else { -+ dwc_otg_hcd->flags.b.port_enable_change = 1; -+ } -+ retval |= 1; -+ } -+ -+ /** Overcurrent Change Interrupt */ -+ if (hprt0.b.prtovrcurrchng) { -+ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " -+ "Port Overcurrent Changed--\n", hprt0.d32); -+ dwc_otg_hcd->flags.b.port_over_current_change = 1; -+ hprt0_modify.b.prtovrcurrchng = 1; -+ retval |= 1; -+ } -+ -+ /* Clear Port Interrupts */ -+ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, -+ hprt0_modify.d32); -+ -+ return retval; -+} -+ -+/** This interrupt indicates that one or more host channels has a pending -+ * interrupt. There are multiple conditions that can cause each host channel -+ * interrupt. This function determines which conditions have occurred for each -+ * host channel interrupt and handles them appropriately. */ -+int32_t dwc_otg_hcd_handle_hc_intr(struct dwc_otg_hcd *dwc_otg_hcd) -+{ -+ int i; -+ int retval = 0; -+ union haint_data haint; -+ -+ /* Clear appropriate bits in HCINTn to clear the interrupt bit in -+ * GINTSTS */ -+ -+ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); -+ -+ for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { -+ if (haint.b2.chint & (1 << i)) -+ retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); -+ } -+ -+ return retval; -+} -+ -+/* Macro used to clear one channel interrupt */ -+#define clear_hc_int(_hc_regs_, _intr_) \ -+do { \ -+ union hcint_data hcint_clear = {.d32 = 0}; \ -+ hcint_clear.b._intr_ = 1; \ -+ dwc_write_reg32(&((_hc_regs_)->hcint), hcint_clear.d32); \ -+} while (0) -+ -+/* -+ * Macro used to disable one channel interrupt. Channel interrupts are -+ * disabled when the channel is halted or released by the interrupt handler. -+ * There is no need to handle further interrupts of that type until the -+ * channel is re-assigned. In fact, subsequent handling may cause crashes -+ * because the channel structures are cleaned up when the channel is released. -+ */ -+#define disable_hc_int(_hc_regs_, _intr_) \ -+ do { \ -+ union hcintmsk_data hcintmsk = {.d32 = 0}; \ -+ hcintmsk.b._intr_ = 1; \ -+ dwc_modify_reg32(&((_hc_regs_)->hcintmsk), hcintmsk.d32, 0); \ -+ } while (0) -+ -+/** -+ * Gets the actual length of a transfer after the transfer halts. _halt_status -+ * holds the reason for the halt. -+ * -+ * For IN transfers where _halt_status is DWC_OTG_HC_XFER_COMPLETE, -+ * *_short_read is set to 1 upon return if less than the requested -+ * number of bytes were transferred. Otherwise, *_short_read is set to 0 upon -+ * return. _short_read may also be NULL on entry, in which case it remains -+ * unchanged. -+ */ -+static uint32_t get_actual_xfer_length(struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status _halt_status, -+ int *_short_read) -+{ -+ union hctsiz_data hctsiz; -+ uint32_t length; -+ -+ if (_short_read != NULL) -+ *_short_read = 0; -+ -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ -+ if (_halt_status == DWC_OTG_HC_XFER_COMPLETE) { -+ if (hc->ep_is_in) { -+ length = hc->xfer_len - hctsiz.b.xfersize; -+ if (_short_read != NULL) -+ *_short_read = (hctsiz.b.xfersize != 0); -+ } else if (hc->qh->do_split) { -+ length = qtd->ssplit_out_xfer_count; -+ } else { -+ length = hc->xfer_len; -+ } -+ } else { -+ /* -+ * Must use the hctsiz.pktcnt field to determine how much data -+ * has been transferred. This field reflects the number of -+ * packets that have been transferred via the USB. This is -+ * always an integral number of packets if the transfer was -+ * halted before its normal completion. (Can't use the -+ * hctsiz.xfersize field because that reflects the number of -+ * bytes transferred via the AHB, not the USB). -+ */ -+ length = -+ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; -+ } -+ -+ return length; -+} -+ -+/** -+ * Updates the state of the URB after a Transfer Complete interrupt on the -+ * host channel. Updates the actual_length field of the URB based on the -+ * number of bytes transferred via the host channel. Sets the URB status -+ * if the data transfer is finished. -+ * -+ * Returns 1 if the data transfer specified by the URB is completely finished, -+ * 0 otherwise. -+ */ -+static int update_urb_state_xfer_comp(struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct urb *urb, struct dwc_otg_qtd *qtd) -+{ -+ int xfer_done = 0; -+ int short_read = 0; -+ -+ urb->actual_length += get_actual_xfer_length(hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE, -+ &short_read); -+ -+ if (short_read || (urb->actual_length == urb->transfer_buffer_length)) { -+ xfer_done = 1; -+ if (short_read && (urb->transfer_flags & URB_SHORT_NOT_OK)) -+ urb->status = -EREMOTEIO; -+ else -+ urb->status = 0; -+ } -+#ifdef DEBUG -+ { -+ union hctsiz_data hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", -+ __func__, (hc->ep_is_in ? "IN" : "OUT"), -+ hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); -+ DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", -+ hctsiz.b.xfersize); -+ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", -+ urb->transfer_buffer_length); -+ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", -+ urb->actual_length); -+ DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", -+ short_read, xfer_done); -+ } -+#endif -+ -+ return xfer_done; -+} -+ -+/* -+ * Save the starting data toggle for the next transfer. The data toggle is -+ * saved in the QH for non-control transfers and it's saved in the QTD for -+ * control transfers. -+ */ -+static void save_data_toggle(struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ union hctsiz_data hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ -+ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { -+ struct dwc_otg_qh *qh = hc->qh; -+ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ else -+ qh->data_toggle = DWC_OTG_HC_PID_DATA1; -+ } else { -+ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) -+ qtd->data_toggle = DWC_OTG_HC_PID_DATA0; -+ else -+ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; -+ } -+} -+ -+/** -+ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic -+ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are -+ * still linked to the QH, the QH is added to the end of the inactive -+ * non-periodic schedule. For periodic QHs, removes the QH from the periodic -+ * schedule if no more QTDs are linked to the QH. -+ */ -+static void deactivate_qh(struct dwc_otg_hcd *hcd, -+ struct dwc_otg_qh *qh, int free_qtd) -+{ -+ int continue_split = 0; -+ struct dwc_otg_qtd *qtd; -+ -+ DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); -+ -+ qtd = list_entry(qh->qtd_list.next, struct dwc_otg_qtd, qtd_list_entry); -+ -+ if (qtd->complete_split) { -+ continue_split = 1; -+ } else if ((qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID) || -+ (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END)) { -+ continue_split = 1; -+ } -+ -+ if (free_qtd) { -+ dwc_otg_hcd_qtd_remove_and_free(qtd); -+ continue_split = 0; -+ } -+ -+ qh->channel = NULL; -+ qh->qtd_in_process = NULL; -+ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); -+} -+ -+/** -+ * Updates the state of an Isochronous URB when the transfer is stopped for -+ * any reason. The fields of the current entry in the frame descriptor array -+ * are set based on the transfer state and the input _halt_status. Completes -+ * the Isochronous URB if all the URB frames have been completed. -+ * -+ * Returns DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be -+ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE. -+ */ -+static enum dwc_otg_halt_status -+update_isoc_urb_state(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status halt_status) -+{ -+ struct urb *urb = qtd->urb; -+ enum dwc_otg_halt_status ret_val = halt_status; -+ struct usb_iso_packet_descriptor *frame_desc; -+ -+ frame_desc = &urb->iso_frame_desc[qtd->isoc_frame_index]; -+ switch (halt_status) { -+ case DWC_OTG_HC_XFER_COMPLETE: -+ frame_desc->status = 0; -+ frame_desc->actual_length = -+ get_actual_xfer_length(hc, hc_regs, qtd, -+ halt_status, NULL); -+ break; -+ case DWC_OTG_HC_XFER_FRAME_OVERRUN: -+ urb->error_count++; -+ if (hc->ep_is_in) -+ frame_desc->status = -ENOSR; -+ else -+ frame_desc->status = -ECOMM; -+ frame_desc->actual_length = 0; -+ break; -+ case DWC_OTG_HC_XFER_BABBLE_ERR: -+ urb->error_count++; -+ frame_desc->status = -EOVERFLOW; -+ /* Don't need to update actual_length in this case. */ -+ break; -+ case DWC_OTG_HC_XFER_XACT_ERR: -+ urb->error_count++; -+ frame_desc->status = -EPROTO; -+ frame_desc->actual_length = -+ get_actual_xfer_length(hc, hc_regs, qtd, -+ halt_status, NULL); -+ break; -+ default: -+ DWC_ERROR("%s: Unhandled halt_status (%d)\n", __func__, -+ halt_status); -+ BUG(); -+ break; -+ } -+ -+ if (++qtd->isoc_frame_index == urb->number_of_packets) { -+ /* -+ * urb->status is not used for isoc transfers. -+ * The individual frame_desc statuses are used instead. -+ */ -+ dwc_otg_hcd_complete_urb(hcd, urb, 0); -+ qtd->urb = NULL; -+ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; -+ } else { -+ ret_val = DWC_OTG_HC_XFER_COMPLETE; -+ } -+ -+ return ret_val; -+} -+ -+/** -+ * Releases a host channel for use by other transfers. Attempts to select and -+ * queue more transactions since at least one host channel is available. -+ * -+ * @hcd: The HCD state structure. -+ * @hc: The host channel to release. -+ * @qtd: The QTD associated with the host channel. This QTD may be freed -+ * if the transfer is complete or an error has occurred. -+ * @_halt_status: Reason the channel is being released. This status -+ * determines the actions taken by this function. -+ */ -+static void release_channel(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status halt_status) -+{ -+ enum dwc_otg_transaction_type tr_type; -+ int free_qtd; -+ -+ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n", -+ __func__, hc->hc_num, halt_status); -+ -+ switch (halt_status) { -+ case DWC_OTG_HC_XFER_URB_COMPLETE: -+ free_qtd = 1; -+ break; -+ case DWC_OTG_HC_XFER_AHB_ERR: -+ case DWC_OTG_HC_XFER_STALL: -+ case DWC_OTG_HC_XFER_BABBLE_ERR: -+ free_qtd = 1; -+ break; -+ case DWC_OTG_HC_XFER_XACT_ERR: -+ if (qtd->error_count >= 3) { -+ DWC_DEBUGPL(DBG_HCDV, -+ " Complete URB with transaction error\n"); -+ free_qtd = 1; -+ qtd->urb->status = -EPROTO; -+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPROTO); -+ qtd->urb = NULL; -+ } else { -+ free_qtd = 0; -+ } -+ break; -+ case DWC_OTG_HC_XFER_URB_DEQUEUE: -+ /* -+ * The QTD has already been removed and the QH has been -+ * deactivated. Don't want to do anything except release the -+ * host channel and try to queue more transfers. -+ */ -+ goto cleanup; -+ case DWC_OTG_HC_XFER_NO_HALT_STATUS: -+ DWC_ERROR("%s: No halt_status, channel %d\n", __func__, -+ hc->hc_num); -+ free_qtd = 0; -+ break; -+ default: -+ free_qtd = 0; -+ break; -+ } -+ -+ deactivate_qh(hcd, hc->qh, free_qtd); -+ -+cleanup: -+ /* -+ * Release the host channel for use by other transfers. The cleanup -+ * function clears the channel interrupt enables and conditions, so -+ * there's no need to clear the Channel Halted interrupt separately. -+ */ -+ dwc_otg_hc_cleanup(hcd->core_if, hc); -+ list_add_tail(&hc->hc_list_entry, &hcd->free_hc_list); -+ -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ hcd->non_periodic_channels--; -+ break; -+ -+ default: -+ /* -+ * Don't release reservations for periodic channels here. -+ * That's done when a periodic transfer is descheduled (i.e. -+ * when the QH is removed from the periodic schedule). -+ */ -+ break; -+ } -+ -+ /* Try to queue more transfers now that there's a free channel. */ -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE) -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+} -+ -+/** -+ * Halts a host channel. If the channel cannot be halted immediately because -+ * the request queue is full, this function ensures that the FIFO empty -+ * interrupt for the appropriate queue is enabled so that the halt request can -+ * be queued when there is space in the request queue. -+ * -+ * This function may also be called in DMA mode. In that case, the channel is -+ * simply released since the core always halts the channel automatically in -+ * DMA mode. -+ */ -+static void halt_channel(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status halt_status) -+{ -+ if (hcd->core_if->dma_enable) { -+ release_channel(hcd, hc, qtd, halt_status); -+ return; -+ } -+ -+ /* Slave mode processing... */ -+ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); -+ -+ if (hc->halt_on_queue) { -+ union gintmsk_data gintmsk = {.d32 = 0 }; -+ struct dwc_otg_core_global_regs *global_regs; -+ global_regs = hcd->core_if->core_global_regs; -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || -+ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { -+ /* -+ * Make sure the Non-periodic Tx FIFO empty interrupt -+ * is enabled so that the non-periodic schedule will -+ * be processed. -+ */ -+ gintmsk.b.nptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); -+ } else { -+ /* -+ * Move the QH from the periodic queued schedule to -+ * the periodic assigned schedule. This allows the -+ * halt to be queued when the periodic schedule is -+ * processed. -+ */ -+ list_move(&hc->qh->qh_list_entry, -+ &hcd->periodic_sched_assigned); -+ -+ /* -+ * Make sure the Periodic Tx FIFO Empty interrupt is -+ * enabled so that the periodic schedule will be -+ * processed. -+ */ -+ gintmsk.b.ptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); -+ } -+ } -+} -+ -+/** -+ * Performs common cleanup for non-periodic transfers after a Transfer -+ * Complete interrupt. This function should be called after any endpoint type -+ * specific handling is finished to release the host channel. -+ */ -+static void complete_non_periodic_xfer(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status halt_status) -+{ -+ union hcint_data hcint; -+ -+ qtd->error_count = 0; -+ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ if (hcint.b.nyet) { -+ /* -+ * Got a NYET on the last transaction of the transfer. This -+ * means that the endpoint should be in the PING state at the -+ * beginning of the next transfer. -+ */ -+ hc->qh->ping_state = 1; -+ clear_hc_int(hc_regs, nyet); -+ } -+ -+ /* -+ * Always halt and release the host channel to make it available for -+ * more transfers. There may still be more phases for a control -+ * transfer or more data packets for a bulk transfer at this point, -+ * but the host channel is still halted. A channel will be reassigned -+ * to the transfer when the non-periodic schedule is processed after -+ * the channel is released. This allows transactions to be queued -+ * properly via dwc_otg_hcd_queue_transactions, which also enables the -+ * Tx FIFO Empty interrupt if necessary. -+ */ -+ if (hc->ep_is_in) { -+ /* -+ * IN transfers in Slave mode require an explicit disable to -+ * halt the channel. (In DMA mode, this call simply releases -+ * the channel.) -+ */ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } else { -+ /* -+ * The channel is automatically disabled by the core for OUT -+ * transfers in Slave mode. -+ */ -+ release_channel(hcd, hc, qtd, halt_status); -+ } -+} -+ -+/** -+ * Performs common cleanup for periodic transfers after a Transfer Complete -+ * interrupt. This function should be called after any endpoint type specific -+ * handling is finished to release the host channel. -+ */ -+static void complete_periodic_xfer(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status halt_status) -+{ -+ union hctsiz_data hctsiz; -+ qtd->error_count = 0; -+ -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { -+ /* Core halts channel in these cases. */ -+ release_channel(hcd, hc, qtd, halt_status); -+ } else { -+ /* Flush any outstanding requests from the Tx queue. */ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+} -+ -+/** -+ * Handles a host channel Transfer Complete interrupt. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_xfercomp_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ int urb_xfer_done; -+ enum dwc_otg_halt_status halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ struct urb *urb = qtd->urb; -+ int pipe_type = usb_pipetype(urb->pipe); -+ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Transfer Complete--\n", hc->hc_num); -+ -+ /* -+ * Handle xfer complete on CSPLIT. -+ */ -+ if (hc->qh->do_split) -+ qtd->complete_split = 0; -+ -+ /* Update the QTD and URB states. */ -+ switch (pipe_type) { -+ case PIPE_CONTROL: -+ switch (qtd->control_phase) { -+ case DWC_OTG_CONTROL_SETUP: -+ if (urb->transfer_buffer_length > 0) -+ qtd->control_phase = DWC_OTG_CONTROL_DATA; -+ else -+ qtd->control_phase = DWC_OTG_CONTROL_STATUS; -+ DWC_DEBUGPL(DBG_HCDV, -+ " Control setup transaction done\n"); -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ break; -+ case DWC_OTG_CONTROL_DATA:{ -+ urb_xfer_done = -+ update_urb_state_xfer_comp(hc, hc_regs, -+ urb, qtd); -+ if (urb_xfer_done) { -+ qtd->control_phase = -+ DWC_OTG_CONTROL_STATUS; -+ DWC_DEBUGPL(DBG_HCDV, -+ " Control data transfer done\n"); -+ } else { -+ save_data_toggle(hc, hc_regs, qtd); -+ } -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ break; -+ } -+ case DWC_OTG_CONTROL_STATUS: -+ DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); -+ if (urb->status == -EINPROGRESS) -+ urb->status = 0; -+ dwc_otg_hcd_complete_urb(hcd, urb, urb->status); -+ qtd->urb = NULL; -+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; -+ break; -+ } -+ -+ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, -+ halt_status); -+ break; -+ case PIPE_BULK: -+ DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); -+ urb_xfer_done = -+ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); -+ if (urb_xfer_done) { -+ dwc_otg_hcd_complete_urb(hcd, urb, urb->status); -+ qtd->urb = NULL; -+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; -+ } else { -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ } -+ -+ save_data_toggle(hc, hc_regs, qtd); -+ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, -+ halt_status); -+ break; -+ case PIPE_INTERRUPT: -+ DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); -+ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); -+ -+ /* -+ * Interrupt URB is done on the first transfer complete -+ * interrupt. -+ */ -+ dwc_otg_hcd_complete_urb(hcd, urb, urb->status); -+ qtd->urb = NULL; -+ save_data_toggle(hc, hc_regs, qtd); -+ complete_periodic_xfer(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_URB_COMPLETE); -+ break; -+ case PIPE_ISOCHRONOUS: -+ DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); -+ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { -+ halt_status = -+ update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE); -+ } -+ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); -+ break; -+ } -+ -+ disable_hc_int(hc_regs, xfercompl); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel STALL interrupt. This handler may be called in -+ * either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_stall_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ struct urb *urb = qtd->urb; -+ int pipe_type = usb_pipetype(urb->pipe); -+ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "STALL Received--\n", hc->hc_num); -+ -+ if (pipe_type == PIPE_CONTROL) { -+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPIPE); -+ qtd->urb = NULL; -+ } -+ -+ if (pipe_type == PIPE_BULK || pipe_type == PIPE_INTERRUPT) { -+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPIPE); -+ qtd->urb = NULL; -+ /* -+ * USB protocol requires resetting the data toggle for bulk -+ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) -+ * setup command is issued to the endpoint. Anticipate the -+ * CLEAR_FEATURE command since a STALL has occurred and reset -+ * the data toggle now. -+ */ -+ hc->qh->data_toggle = 0; -+ } -+ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); -+ -+ disable_hc_int(hc_regs, stall); -+ -+ return 1; -+} -+ -+/* -+ * Updates the state of the URB when a transfer has been stopped due to an -+ * abnormal condition before the transfer completes. Modifies the -+ * actual_length field of the URB to reflect the number of bytes that have -+ * actually been transferred via the host channel. -+ */ -+static void update_urb_state_xfer_intr(struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct urb *urb, -+ struct dwc_otg_qtd *qtd, -+ enum dwc_otg_halt_status halt_status) -+{ -+ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, -+ halt_status, NULL); -+ urb->actual_length += bytes_transferred; -+ -+#ifdef DEBUG -+ { -+ union hctsiz_data hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", -+ __func__, (hc->ep_is_in ? "IN" : "OUT"), -+ hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", -+ hc->start_pkt_count); -+ DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); -+ DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", -+ hc->max_packet); -+ DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", -+ bytes_transferred); -+ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", -+ urb->actual_length); -+ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", -+ urb->transfer_buffer_length); -+ } -+#endif -+} -+ -+/** -+ * Handles a host channel NAK interrupt. This handler may be called in either -+ * DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_nak_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "NAK Received--\n", hc->hc_num); -+ -+ /* -+ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and -+ * interrupt. Re-start the SSPLIT transfer. -+ */ -+ if (hc->do_split) { -+ if (hc->complete_split) -+ qtd->error_count = 0; -+ qtd->complete_split = 0; -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ goto handle_nak_done; -+ } -+ -+ switch (usb_pipetype(qtd->urb->pipe)) { -+ case PIPE_CONTROL: -+ case PIPE_BULK: -+ if (hcd->core_if->dma_enable && hc->ep_is_in) { -+ /* -+ * NAK interrupts are enabled on bulk/control IN -+ * transfers in DMA mode for the sole purpose of -+ * resetting the error count after a transaction error -+ * occurs. The core will continue transferring data. -+ */ -+ qtd->error_count = 0; -+ goto handle_nak_done; -+ } -+ -+ /* -+ * NAK interrupts normally occur during OUT transfers in DMA -+ * or Slave mode. For IN transfers, more requests will be -+ * queued as request queue space is available. -+ */ -+ qtd->error_count = 0; -+ -+ if (!hc->qh->ping_state) { -+ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, -+ qtd, DWC_OTG_HC_XFER_NAK); -+ save_data_toggle(hc, hc_regs, qtd); -+ if (qtd->urb->dev->speed == USB_SPEED_HIGH) -+ hc->qh->ping_state = 1; -+ } -+ -+ /* -+ * Halt the channel so the transfer can be re-started from -+ * the appropriate point or the PING protocol will -+ * start/continue. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ break; -+ case PIPE_INTERRUPT: -+ qtd->error_count = 0; -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ break; -+ case PIPE_ISOCHRONOUS: -+ /* Should never get called for isochronous transfers. */ -+ BUG(); -+ break; -+ } -+ -+handle_nak_done: -+ disable_hc_int(hc_regs, nak); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel ACK interrupt. This interrupt is enabled when -+ * performing the PING protocol in Slave mode, when errors occur during -+ * either Slave mode or DMA mode, and during Start Split transactions. -+ */ -+static int32_t handle_hc_ack_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "ACK Received--\n", hc->hc_num); -+ -+ if (hc->do_split) { -+ /* -+ * Handle ACK on SSPLIT. -+ * ACK should not occur in CSPLIT. -+ */ -+ if ((!hc->ep_is_in) -+ && (hc->data_pid_start != DWC_OTG_HC_PID_SETUP)) { -+ qtd->ssplit_out_xfer_count = hc->xfer_len; -+ } -+ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { -+ /* Don't need complete for isochronous out transfers. */ -+ qtd->complete_split = 1; -+ } -+ -+ /* ISOC OUT */ -+ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && !hc->ep_is_in) { -+ switch (hc->xact_pos) { -+ case DWC_HCSPLIT_XACTPOS_ALL: -+ break; -+ case DWC_HCSPLIT_XACTPOS_END: -+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; -+ qtd->isoc_split_offset = 0; -+ break; -+ case DWC_HCSPLIT_XACTPOS_BEGIN: -+ case DWC_HCSPLIT_XACTPOS_MID: -+ /* -+ * For BEGIN or MID, calculate the length for -+ * the next microframe to determine the correct -+ * SSPLIT token, either MID or END. -+ */ -+ do { -+ struct usb_iso_packet_descriptor -+ *frame_desc; -+ -+ frame_desc = -+ &qtd->urb->iso_frame_desc[qtd->isoc_frame_index]; -+ qtd->isoc_split_offset += 188; -+ -+ if ((frame_desc->length - -+ qtd->isoc_split_offset) <= 188) { -+ qtd->isoc_split_pos = -+ DWC_HCSPLIT_XACTPOS_END; -+ } else { -+ qtd->isoc_split_pos = -+ DWC_HCSPLIT_XACTPOS_MID; -+ } -+ -+ } while (0); -+ break; -+ } -+ } else { -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); -+ } -+ } else { -+ qtd->error_count = 0; -+ -+ if (hc->qh->ping_state) { -+ hc->qh->ping_state = 0; -+ /* -+ * Halt the channel so the transfer can be re-started -+ * from the appropriate point. This only happens in -+ * Slave mode. In DMA mode, the ping_state is cleared -+ * when the transfer is started because the core -+ * automatically executes the PING, then the transfer. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); -+ } -+ } -+ -+ /* -+ * If the ACK occurred when _not_ in the PING state, let the channel -+ * continue transferring data after clearing the error count. -+ */ -+ -+ disable_hc_int(hc_regs, ack); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel NYET interrupt. This interrupt should only occur on -+ * Bulk and Control OUT endpoints and for complete split transactions. If a -+ * NYET occurs at the same time as a Transfer Complete interrupt, it is -+ * handled in the xfercomp interrupt handler, not here. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_nyet_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "NYET Received--\n", hc->hc_num); -+ -+ /* -+ * NYET on CSPLIT -+ * re-do the CSPLIT immediately on non-periodic -+ */ -+ if ((hc->do_split) && (hc->complete_split)) { -+ if ((hc->ep_type == DWC_OTG_EP_TYPE_INTR) || -+ (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { -+ int frnum = -+ dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd -+ (hcd)); -+ -+ if (dwc_full_frame_num(frnum) != -+ dwc_full_frame_num(hc->qh->sched_frame)) { -+ /* -+ * No longer in the same full speed frame. -+ * Treat this as a transaction error. -+ */ -+#if 0 -+ /** @todo Fix system performance so this can -+ * be treated as an error. Right now complete -+ * splits cannot be scheduled precisely enough -+ * due to other system activity, so this error -+ * occurs regularly in Slave mode. -+ */ -+ qtd->error_count++; -+#endif -+ qtd->complete_split = 0; -+ halt_channel(hcd, hc, qtd, -+ DWC_OTG_HC_XFER_XACT_ERR); -+ /** @todo add support for isoc release */ -+ goto handle_nyet_done; -+ } -+ } -+ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); -+ goto handle_nyet_done; -+ } -+ -+ hc->qh->ping_state = 1; -+ qtd->error_count = 0; -+ -+ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, -+ DWC_OTG_HC_XFER_NYET); -+ save_data_toggle(hc, hc_regs, qtd); -+ -+ /* -+ * Halt the channel and re-start the transfer so the PING -+ * protocol will start. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); -+ -+handle_nyet_done: -+ disable_hc_int(hc_regs, nyet); -+ return 1; -+} -+ -+/** -+ * Handles a host channel babble interrupt. This handler may be called in -+ * either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_babble_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Babble Error--\n", hc->hc_num); -+ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { -+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EOVERFLOW); -+ qtd->urb = NULL; -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); -+ } else { -+ enum dwc_otg_halt_status halt_status; -+ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_BABBLE_ERR); -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+ disable_hc_int(hc_regs, bblerr); -+ return 1; -+} -+ -+/** -+ * Handles a host channel AHB error interrupt. This handler is only called in -+ * DMA mode. -+ */ -+static int32_t handle_hc_ahberr_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ union hcchar_data hcchar; -+ union hcsplt_data hcsplt; -+ union hctsiz_data hctsiz; -+ uint32_t hcdma; -+ struct urb *urb = qtd->urb; -+ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "AHB Error--\n", hc->hc_num); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcdma = dwc_read_reg32(&hc_regs->hcdma); -+ -+ DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); -+ DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); -+ DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); -+ DWC_ERROR(" Device address: %d\n", usb_pipedevice(urb->pipe)); -+ DWC_ERROR(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), -+ (usb_pipein(urb->pipe) ? "IN" : "OUT")); -+ DWC_ERROR(" Endpoint type: %s\n", -+ ({ -+ char *pipetype; -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_CONTROL: -+ pipetype = "CONTROL"; -+ break; -+ case PIPE_BULK: -+ pipetype = "BULK"; -+ break; -+ case PIPE_INTERRUPT: -+ pipetype = "INTERRUPT"; -+ break; -+ case PIPE_ISOCHRONOUS: -+ pipetype = "ISOCHRONOUS"; -+ break; -+ default: -+ pipetype = "UNKNOWN"; -+ break; -+ } -+ pipetype; -+ })); -+ DWC_ERROR(" Speed: %s\n", -+ ({ -+ char *speed; -+ switch (urb->dev->speed) { -+ case USB_SPEED_HIGH: -+ speed = "HIGH"; -+ break; -+ case USB_SPEED_FULL: -+ speed = "FULL"; -+ break; -+ case USB_SPEED_LOW: -+ speed = "LOW"; -+ break; -+ default: -+ speed = "UNKNOWN"; -+ break; -+ } -+ speed; -+ })); -+ DWC_ERROR(" Max packet size: %d\n", -+ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); -+ DWC_ERROR(" Data buffer length: %d\n", urb->transfer_buffer_length); -+ DWC_ERROR(" Transfer buffer: %p, Transfer DMA: 0x%llx\n", -+ urb->transfer_buffer, (unsigned long long)urb->transfer_dma); -+ DWC_ERROR(" Setup buffer: %p, Setup DMA: 0x%llx\n", -+ urb->setup_packet, (unsigned long long)urb->setup_dma); -+ DWC_ERROR(" Interval: %d\n", urb->interval); -+ -+ dwc_otg_hcd_complete_urb(hcd, urb, -EIO); -+ qtd->urb = NULL; -+ -+ /* -+ * Force a channel halt. Don't call halt_channel because that won't -+ * write to the HCCHARn register in DMA mode to force the halt. -+ */ -+ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); -+ -+ disable_hc_int(hc_regs, ahberr); -+ return 1; -+} -+ -+/** -+ * Handles a host channel transaction error interrupt. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_xacterr_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Transaction Error--\n", hc->hc_num); -+ -+ switch (usb_pipetype(qtd->urb->pipe)) { -+ case PIPE_CONTROL: -+ case PIPE_BULK: -+ qtd->error_count++; -+ if (!hc->qh->ping_state) { -+ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, -+ qtd, -+ DWC_OTG_HC_XFER_XACT_ERR); -+ save_data_toggle(hc, hc_regs, qtd); -+ if (!hc->ep_is_in -+ && qtd->urb->dev->speed == USB_SPEED_HIGH) { -+ hc->qh->ping_state = 1; -+ } -+ } -+ -+ /* -+ * Halt the channel so the transfer can be re-started from -+ * the appropriate point or the PING protocol will start. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); -+ break; -+ case PIPE_INTERRUPT: -+ qtd->error_count++; -+ if ((hc->do_split) && (hc->complete_split)) -+ qtd->complete_split = 0; -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); -+ break; -+ case PIPE_ISOCHRONOUS: -+ { -+ enum dwc_otg_halt_status halt_status; -+ halt_status = -+ update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_XACT_ERR); -+ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+ break; -+ } -+ -+ disable_hc_int(hc_regs, xacterr); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel frame overrun interrupt. This handler may be called -+ * in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_frmovrun_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ enum dwc_otg_halt_status halt_status; -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Frame Overrun--\n", hc->hc_num); -+ -+ switch (usb_pipetype(qtd->urb->pipe)) { -+ case PIPE_CONTROL: -+ case PIPE_BULK: -+ break; -+ case PIPE_INTERRUPT: -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); -+ break; -+ case PIPE_ISOCHRONOUS: -+ halt_status = -+ update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_FRAME_OVERRUN); -+ halt_channel(hcd, hc, qtd, halt_status); -+ break; -+ } -+ -+ disable_hc_int(hc_regs, frmovrun); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel data toggle error interrupt. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_datatglerr_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Data Toggle Error--\n", hc->hc_num); -+ -+ if (hc->ep_is_in) { -+ qtd->error_count = 0; -+ } else { -+ DWC_ERROR("Data Toggle Error on OUT transfer," -+ "channel %d\n", hc->hc_num); -+ } -+ -+ disable_hc_int(hc_regs, datatglerr); -+ -+ return 1; -+} -+ -+#ifdef DEBUG -+/** -+ * This function is for debug only. It checks that a valid halt status is set -+ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is -+ * taken and a warning is issued. -+ * Returns 1 if halt status is ok, 0 otherwise. -+ */ -+static inline int halt_status_ok(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ union hcchar_data hcchar; -+ union hctsiz_data hctsiz; -+ union hcint_data hcint; -+ union hcintmsk_data hcintmsk; -+ union hcsplt_data hcsplt; -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { -+ /* -+ * This code is here only as a check. This condition should -+ * never happen. Ignore the halt if it does occur. -+ */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ DWC_WARN -+ ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " -+ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " -+ "hcint 0x%08x, hcintmsk 0x%08x, " -+ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, -+ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, -+ hcintmsk.d32, hcsplt.d32, qtd->complete_split); -+ -+ DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", -+ __func__, hc->hc_num); -+ DWC_WARN("\n"); -+ clear_hc_int(hc_regs, chhltd); -+ return 0; -+ } -+ -+ /* -+ * This code is here only as a check. hcchar.chdis should -+ * never be set when the halt interrupt occurs. Halt the -+ * channel again if it does occur. -+ */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chdis) { -+ DWC_WARN("%s: hcchar.chdis set unexpectedly, " -+ "hcchar 0x%08x, trying to halt again\n", -+ __func__, hcchar.d32); -+ clear_hc_int(hc_regs, chhltd); -+ hc->halt_pending = 0; -+ halt_channel(hcd, hc, qtd, hc->halt_status); -+ return 0; -+ } -+ -+ return 1; -+} -+#endif -+ -+/** -+ * Handles a host Channel Halted interrupt in DMA mode. This handler -+ * determines the reason the channel halted and proceeds accordingly. -+ */ -+static void handle_hc_chhltd_intr_dma(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ union hcint_data hcint; -+ union hcintmsk_data hcintmsk; -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || -+ hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR) { -+ /* -+ * Just release the channel. A dequeue can happen on a -+ * transfer timeout. In the case of an AHB Error, the channel -+ * was forced to halt because there's no way to gracefully -+ * recover. -+ */ -+ release_channel(hcd, hc, qtd, hc->halt_status); -+ return; -+ } -+ -+ /* Read the HCINTn register to determine the cause for the halt. */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ -+ if (hcint.b.xfercomp) { -+ /* -+ * @todo This is here because of a possible hardware -+ * bug. Spec says that on SPLIT-ISOC OUT transfers in -+ * DMA mode that a HALT interrupt w/ACK bit set should -+ * occur, but I only see the XFERCOMP bit, even with -+ * it masked out. This is a workaround for that -+ * behavior. Should fix this when hardware is fixed. -+ */ -+ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && (!hc->ep_is_in)) -+ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); -+ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.stall) { -+ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.xacterr) { -+ /* -+ * Must handle xacterr before nak or ack. Could get a xacterr -+ * at the same time as either of these on a BULK/CONTROL OUT -+ * that started with a PING. The xacterr takes precedence. -+ */ -+ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.nyet) { -+ /* -+ * Must handle nyet before nak or ack. Could get a nyet at the -+ * same time as either of those on a BULK/CONTROL OUT that -+ * started with a PING. The nyet takes precedence. -+ */ -+ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.bblerr) { -+ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.frmovrun) { -+ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.nak && !hcintmsk.b.nak) { -+ /* -+ * If nak is not masked, it's because a non-split IN transfer -+ * is in an error state. In that case, the nak is handled by -+ * the nak interrupt handler, not here. Handle nak here for -+ * BULK/CONTROL OUT transfers, which halt on a NAK to allow -+ * rewinding the buffer pointer. -+ */ -+ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.ack && !hcintmsk.b.ack) { -+ /* -+ * If ack is not masked, it's because a non-split IN transfer -+ * is in an error state. In that case, the ack is handled by -+ * the ack interrupt handler, not here. Handle ack here for -+ * split transfers. Start splits halt on ACK. -+ */ -+ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); -+ } else { -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * A periodic transfer halted with no other channel -+ * interrupts set. Assume it was halted by the core -+ * because it could not be completed in its scheduled -+ * (micro)frame. -+ */ -+#ifdef DEBUG -+ DWC_PRINT("%s: Halt channel %d (assume incomplete " -+ "periodic transfer)\n", -+ __func__, hc->hc_num); -+#endif -+ halt_channel(hcd, hc, qtd, -+ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); -+ } else { -+ DWC_ERROR("%s: Channel %d, DMA Mode -- ChHltd set, " -+ "but reason for halting is unknown, hcint " -+ "0x%08x, intsts 0x%08x\n", -+ __func__, hc->hc_num, hcint.d32, -+ dwc_read_reg32(&hcd->core_if->core_global_regs-> -+ gintsts)); -+ } -+ } -+} -+ -+/** -+ * Handles a host channel Channel Halted interrupt. -+ * -+ * In slave mode, this handler is called only when the driver specifically -+ * requests a halt. This occurs during handling other host channel interrupts -+ * (e.g. nak, xacterr, stall, nyet, etc.). -+ * -+ * In DMA mode, this is the interrupt that occurs when the core has finished -+ * processing a transfer on a channel. Other host channel interrupts (except -+ * ahberr) are disabled in DMA mode. -+ */ -+static int32_t handle_hc_chhltd_intr(struct dwc_otg_hcd *hcd, -+ struct dwc_hc *hc, -+ struct dwc_otg_hc_regs *hc_regs, -+ struct dwc_otg_qtd *qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Channel Halted--\n", hc->hc_num); -+ -+ if (hcd->core_if->dma_enable) { -+ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); -+ } else { -+#ifdef DEBUG -+ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) -+ return 1; -+#endif -+ release_channel(hcd, hc, qtd, hc->halt_status); -+ } -+ -+ return 1; -+} -+ -+/** Handles interrupt for a specific Host Channel */ -+int32_t dwc_otg_hcd_handle_hc_n_intr(struct dwc_otg_hcd *dwc_otg_hcd, -+ uint32_t _num) -+{ -+ int retval = 0; -+ union hcint_data hcint; -+ union hcintmsk_data hcintmsk; -+ struct dwc_hc *hc; -+ struct dwc_otg_hc_regs *hc_regs; -+ struct dwc_otg_qtd *qtd; -+ -+ DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", _num); -+ -+ hc = dwc_otg_hcd->hc_ptr_array[_num]; -+ hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[_num]; -+ qtd = list_entry(hc->qh->qtd_list.next, struct dwc_otg_qtd, -+ qtd_list_entry); -+ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ DWC_DEBUGPL(DBG_HCDV, -+ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", -+ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); -+ hcint.d32 = hcint.d32 & hcintmsk.d32; -+ -+ if (!dwc_otg_hcd->core_if->dma_enable) { -+ if ((hcint.b.chhltd) && (hcint.d32 != 0x2)) -+ hcint.b.chhltd = 0; -+ } -+ -+ if (hcint.b.xfercomp) { -+ retval |= -+ handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ /* -+ * If NYET occurred at same time as Xfer Complete, the NYET is -+ * handled by the Xfer Complete interrupt handler. Don't want -+ * to call the NYET interrupt handler in this case. -+ */ -+ hcint.b.nyet = 0; -+ } -+ if (hcint.b.chhltd) -+ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.ahberr) -+ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.stall) -+ retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.nak) -+ retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.ack) -+ retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.nyet) -+ retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.xacterr) -+ retval |= -+ handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.bblerr) -+ retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.frmovrun) -+ retval |= -+ handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ if (hcint.b.datatglerr) -+ retval |= -+ handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ -+ return retval; -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -new file mode 100644 -index 0000000..e4c96f2 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -0,0 +1,695 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+#ifndef DWC_DEVICE_ONLY -+ -+/* -+ * -+ * This file contains the functions to manage Queue Heads and Queue -+ * Transfer Descriptors. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dwc_otg_driver.h" -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+/** -+ * This function allocates and initializes a QH. -+ * -+ * @hcd: The HCD state structure for the DWC OTG controller. -+ * @urb: Holds the information about the device/endpoint that we need -+ * to initialize the QH. -+ * -+ * Returns Returns pointer to the newly allocated QH, or NULL on error. */ -+struct dwc_otg_qh *dwc_otg_hcd_qh_create(struct dwc_otg_hcd *hcd, -+ struct urb *urb) -+{ -+ struct dwc_otg_qh *qh; -+ -+ /* Allocate memory */ -+ /** @todo add memflags argument */ -+ qh = dwc_otg_hcd_qh_alloc(); -+ if (qh == NULL) -+ return NULL; -+ -+ dwc_otg_hcd_qh_init(hcd, qh, urb); -+ return qh; -+} -+ -+/** Free each QTD in the QH's QTD-list then free the QH. QH should already be -+ * removed from a list. QTD list should already be empty if called from URB -+ * Dequeue. -+ * -+ * @qh: The QH to free. -+ */ -+void dwc_otg_hcd_qh_free(struct dwc_otg_qh *qh) -+{ -+ struct dwc_otg_qtd *qtd; -+ struct list_head *pos; -+ -+ /* Free each QTD in the QTD list */ -+ for (pos = qh->qtd_list.next; -+ pos != &qh->qtd_list; pos = qh->qtd_list.next) { -+ list_del(pos); -+ qtd = dwc_list_to_qtd(pos); -+ dwc_otg_hcd_qtd_free(qtd); -+ } -+ -+ kfree(qh); -+ return; -+} -+ -+/** Initializes a QH structure. -+ * -+ * @hcd: The HCD state structure for the DWC OTG controller. -+ * @qh: The QH to init. -+ * @urb: Holds the information about the device/endpoint that we need -+ * to initialize the QH. */ -+#define SCHEDULE_SLOP 10 -+void dwc_otg_hcd_qh_init(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh, -+ struct urb *urb) -+{ -+ memset(qh, 0, sizeof(struct dwc_otg_qh)); -+ -+ /* Initialize QH */ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_CONTROL: -+ qh->ep_type = USB_ENDPOINT_XFER_CONTROL; -+ break; -+ case PIPE_BULK: -+ qh->ep_type = USB_ENDPOINT_XFER_BULK; -+ break; -+ case PIPE_ISOCHRONOUS: -+ qh->ep_type = USB_ENDPOINT_XFER_ISOC; -+ break; -+ case PIPE_INTERRUPT: -+ qh->ep_type = USB_ENDPOINT_XFER_INT; -+ break; -+ } -+ -+ qh->ep_is_in = usb_pipein(urb->pipe) ? 1 : 0; -+ -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ qh->maxp = -+ usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe))); -+ INIT_LIST_HEAD(&qh->qtd_list); -+ INIT_LIST_HEAD(&qh->qh_list_entry); -+ qh->channel = NULL; -+ -+ /* FS/LS Enpoint on HS Hub -+ * NOT virtual root hub */ -+ qh->do_split = 0; -+ if (((urb->dev->speed == USB_SPEED_LOW) || -+ (urb->dev->speed == USB_SPEED_FULL)) && -+ (urb->dev->tt) && (urb->dev->tt->hub->devnum != 1)) { -+ DWC_DEBUGPL(DBG_HCD, -+ "QH init: EP %d: TT found at hub addr %d, for " -+ "port %d\n", -+ usb_pipeendpoint(urb->pipe), -+ urb->dev->tt->hub->devnum, urb->dev->ttport); -+ qh->do_split = 1; -+ } -+ -+ if (qh->ep_type == USB_ENDPOINT_XFER_INT || -+ qh->ep_type == USB_ENDPOINT_XFER_ISOC) { -+ /* Compute scheduling parameters once and save them. */ -+ union hprt0_data hprt; -+ -+ /* todo Account for split transfers in the bus time. */ -+ int bytecount = -+ dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); -+ /* -+ * The results from usb_calc_bus_time are in nanosecs, -+ * so divide the result by 1000 to convert to -+ * microsecs expected by this driver -+ */ -+ qh->usecs = usb_calc_bus_time(urb->dev->speed, -+ usb_pipein(urb->pipe), -+ (qh->ep_type == -+ USB_ENDPOINT_XFER_ISOC), -+ bytecount) / 1000; -+ -+ /* Start in a slightly future (micro)frame. */ -+ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, -+ SCHEDULE_SLOP); -+ qh->interval = urb->interval; -+#if 0 -+ /* Increase interrupt polling rate for debugging. */ -+ if (qh->ep_type == USB_ENDPOINT_XFER_INT) -+ qh->interval = 8; -+#endif -+ hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0); -+ if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && -+ ((urb->dev->speed == USB_SPEED_LOW) || -+ (urb->dev->speed == USB_SPEED_FULL))) { -+ qh->interval *= 8; -+ qh->sched_frame |= 0x7; -+ qh->start_split_frame = qh->sched_frame; -+ } -+ -+ } -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", -+ urb->dev->devnum); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", -+ usb_pipeendpoint(urb->pipe), -+ usb_pipein(urb->pipe) == USB_DIR_IN ? "IN" : "OUT"); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", -+ ({ -+ char *speed; -+ switch (urb->dev->speed) { -+ case USB_SPEED_LOW: -+ speed = "low"; -+ break; -+ case USB_SPEED_FULL: -+ speed = "full"; -+ break; -+ case USB_SPEED_HIGH: -+ speed = "high"; -+ break; -+ default: -+ speed = "?"; -+ break; -+ } -+ speed; -+ })); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", -+ ({ -+ char *type; -+ switch (qh->ep_type) { -+ case USB_ENDPOINT_XFER_ISOC: -+ type = "isochronous"; -+ break; -+ case USB_ENDPOINT_XFER_INT: -+ type = "interrupt"; -+ break; -+ case USB_ENDPOINT_XFER_CONTROL: -+ type = "control"; -+ break; -+ case USB_ENDPOINT_XFER_BULK: -+ type = "bulk"; -+ break; -+ default: -+ type = "?"; -+ break; -+ } -+ type; -+ })); -+#ifdef DEBUG -+ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", -+ qh->usecs); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", -+ qh->interval); -+ } -+#endif -+ -+ return; -+} -+ -+/** -+ * Checks that a channel is available for a periodic transfer. -+ * -+ * Returns 0 if successful, negative error code otherise. -+ */ -+static int periodic_channel_available(struct dwc_otg_hcd *hcd) -+{ -+ /* -+ * Currently assuming that there is a dedicated host channnel for each -+ * periodic transaction plus at least one host channel for -+ * non-periodic transactions. -+ */ -+ int status; -+ int num_channels; -+ -+ num_channels = hcd->core_if->core_params->host_channels; -+ if ((hcd->periodic_channels + hcd->non_periodic_channels < -+ num_channels) && (hcd->periodic_channels < num_channels - 1)) { -+ status = 0; -+ } else { -+ DWC_NOTICE -+ ("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", -+ __func__, num_channels, hcd->periodic_channels, -+ hcd->non_periodic_channels); -+ status = -ENOSPC; -+ } -+ -+ return status; -+} -+ -+/** -+ * Checks that there is sufficient bandwidth for the specified QH in the -+ * periodic schedule. For simplicity, this calculation assumes that all the -+ * transfers in the periodic schedule may occur in the same (micro)frame. -+ * -+ * @hcd: The HCD state structure for the DWC OTG controller. -+ * @qh: QH containing periodic bandwidth required. -+ * -+ * Returns 0 if successful, negative error code otherwise. -+ */ -+static int check_periodic_bandwidth(struct dwc_otg_hcd *hcd, -+ struct dwc_otg_qh *qh) -+{ -+ int status; -+ uint16_t max_claimed_usecs; -+ -+ status = 0; -+ -+ if (hcd->core_if->core_params->speed == DWC_SPEED_PARAM_HIGH) { -+ /* -+ * High speed mode. -+ * Max periodic usecs is 80% x 125 usec = 100 usec. -+ */ -+ max_claimed_usecs = 100 - qh->usecs; -+ } else { -+ /* -+ * Full speed mode. -+ * Max periodic usecs is 90% x 1000 usec = 900 usec. -+ */ -+ max_claimed_usecs = 900 - qh->usecs; -+ } -+ -+ if (hcd->periodic_usecs > max_claimed_usecs) { -+ DWC_NOTICE("%s: already claimed usecs %d, required usecs %d\n", -+ __func__, hcd->periodic_usecs, qh->usecs); -+ status = -ENOSPC; -+ } -+ -+ return status; -+} -+ -+/** -+ * Checks that the max transfer size allowed in a host channel is large enough -+ * to handle the maximum data transfer in a single (micro)frame for a periodic -+ * transfer. -+ * -+ * @hcd: The HCD state structure for the DWC OTG controller. -+ * @qh: QH for a periodic endpoint. -+ * -+ * Returns 0 if successful, negative error code otherwise. -+ */ -+static int check_max_xfer_size(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) -+{ -+ int status; -+ uint32_t max_xfer_size; -+ uint32_t max_channel_xfer_size; -+ -+ status = 0; -+ -+ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); -+ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; -+ -+ if (max_xfer_size > max_channel_xfer_size) { -+ DWC_NOTICE("%s: Periodic xfer length %d > " -+ "max xfer length for channel %d\n", -+ __func__, max_xfer_size, max_channel_xfer_size); -+ status = -ENOSPC; -+ } -+ -+ return status; -+} -+ -+/** -+ * Schedules an interrupt or isochronous transfer in the periodic schedule. -+ * -+ * @hcd: The HCD state structure for the DWC OTG controller. -+ * @qh: QH for the periodic transfer. The QH should already contain the -+ * scheduling information. -+ * -+ * Returns 0 if successful, negative error code otherwise. -+ */ -+static int schedule_periodic(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) -+{ -+ int status = 0; -+ -+ status = periodic_channel_available(hcd); -+ if (status) { -+ DWC_NOTICE("%s: No host channel available for periodic " -+ "transfer.\n", __func__); -+ return status; -+ } -+ -+ status = check_periodic_bandwidth(hcd, qh); -+ if (status) { -+ DWC_NOTICE("%s: Insufficient periodic bandwidth for " -+ "periodic transfer.\n", __func__); -+ return status; -+ } -+ -+ status = check_max_xfer_size(hcd, qh); -+ if (status) { -+ DWC_NOTICE("%s: Channel max transfer size too small " -+ "for periodic transfer.\n", __func__); -+ return status; -+ } -+ -+ /* Always start in the inactive schedule. */ -+ list_add_tail(&qh->qh_list_entry, &hcd->periodic_sched_inactive); -+ -+ /* Reserve the periodic channel. */ -+ hcd->periodic_channels++; -+ -+ /* Update claimed usecs per (micro)frame. */ -+ hcd->periodic_usecs += qh->usecs; -+ -+ /* -+ * Update average periodic bandwidth claimed and # periodic -+ * reqs for usbfs. -+ */ -+ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated += -+ qh->usecs / qh->interval; -+ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { -+ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs++; -+ DWC_DEBUGPL(DBG_HCD, -+ "Scheduled intr: qh %p, usecs %d, period %d\n", qh, -+ qh->usecs, qh->interval); -+ } else { -+ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs++; -+ DWC_DEBUGPL(DBG_HCD, -+ "Scheduled isoc: qh %p, usecs %d, period %d\n", qh, -+ qh->usecs, qh->interval); -+ } -+ -+ return status; -+} -+ -+/** -+ * This function adds a QH to either the non periodic or periodic schedule if -+ * it is not already in the schedule. If the QH is already in the schedule, no -+ * action is taken. -+ * -+ * Returns 0 if successful, negative error code otherwise. -+ */ -+int dwc_otg_hcd_qh_add(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) -+{ -+ int status = 0; -+ -+ if (!spin_is_locked(&hcd->global_lock)) { -+ pr_err("%s don't have hcd->global_lock", __func__); -+ BUG(); -+ } -+ -+ if (!list_empty(&qh->qh_list_entry)) { -+ /* QH already in a schedule. */ -+ goto done; -+ } -+ -+ /* Add the new QH to the appropriate schedule */ -+ if (dwc_qh_is_non_per(qh)) { -+ /* Always start in the inactive schedule. */ -+ list_add_tail(&qh->qh_list_entry, -+ &hcd->non_periodic_sched_inactive); -+ } else { -+ status = schedule_periodic(hcd, qh); -+ } -+ -+done: -+ return status; -+} -+ -+/** -+ * Removes an interrupt or isochronous transfer from the periodic schedule. -+ * -+ * @hcd: The HCD state structure for the DWC OTG controller. -+ * @qh: QH for the periodic transfer. -+ */ -+static void deschedule_periodic(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) -+{ -+ list_del_init(&qh->qh_list_entry); -+ -+ /* Release the periodic channel reservation. */ -+ hcd->periodic_channels--; -+ -+ /* Update claimed usecs per (micro)frame. */ -+ hcd->periodic_usecs -= qh->usecs; -+ -+ /* -+ * Update average periodic bandwidth claimed and # periodic -+ * reqs for usbfs. -+ */ -+ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_allocated -= -+ qh->usecs / qh->interval; -+ -+ if (qh->ep_type == USB_ENDPOINT_XFER_INT) { -+ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_int_reqs--; -+ DWC_DEBUGPL(DBG_HCD, -+ "Descheduled intr: qh %p, usecs %d, period %d\n", -+ qh, qh->usecs, qh->interval); -+ } else { -+ hcd_to_bus(dwc_otg_hcd_to_hcd(hcd))->bandwidth_isoc_reqs--; -+ DWC_DEBUGPL(DBG_HCD, -+ "Descheduled isoc: qh %p, usecs %d, period %d\n", -+ qh, qh->usecs, qh->interval); -+ } -+} -+ -+/** -+ * Removes a QH from either the non-periodic or periodic schedule. Memory is -+ * not freed. -+ * -+ * @hcd: The HCD state structure. -+ * @qh: QH to remove from schedule. */ -+void dwc_otg_hcd_qh_remove(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh) -+{ -+ if (!spin_is_locked(&hcd->global_lock)) { -+ pr_err("%s don't have hcd->global_lock", __func__); -+ BUG(); -+ } -+ -+ if (list_empty(&qh->qh_list_entry)) { -+ /* QH is not in a schedule. */ -+ goto done; -+ } -+ -+ if (dwc_qh_is_non_per(qh)) { -+ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { -+ hcd->non_periodic_qh_ptr = -+ hcd->non_periodic_qh_ptr->next; -+ } -+ list_del_init(&qh->qh_list_entry); -+ } else { -+ deschedule_periodic(hcd, qh); -+ } -+ -+done: -+ ; -+} -+ -+/** -+ * Deactivates a QH. For non-periodic QHs, removes the QH from the active -+ * non-periodic schedule. The QH is added to the inactive non-periodic -+ * schedule if any QTDs are still attached to the QH. -+ * -+ * For periodic QHs, the QH is removed from the periodic queued schedule. If -+ * there are any QTDs still attached to the QH, the QH is added to either the -+ * periodic inactive schedule or the periodic ready schedule and its next -+ * scheduled frame is calculated. The QH is placed in the ready schedule if -+ * the scheduled frame has been reached already. Otherwise it's placed in the -+ * inactive schedule. If there are no QTDs attached to the QH, the QH is -+ * completely removed from the periodic schedule. -+ */ -+void dwc_otg_hcd_qh_deactivate(struct dwc_otg_hcd *hcd, struct dwc_otg_qh *qh, -+ int sched_next_periodic_split) -+{ -+ uint16_t frame_number; -+ -+ if (!spin_is_locked(&hcd->global_lock)) { -+ pr_err("%s don't have hcd->global_lock", __func__); -+ BUG(); -+ } -+ -+ if (dwc_qh_is_non_per(qh)) { -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ if (!list_empty(&qh->qtd_list)) -+ /* Add back to inactive non-periodic schedule. */ -+ dwc_otg_hcd_qh_add(hcd, qh); -+ return; -+ } -+ -+ frame_number = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd)); -+ -+ if (qh->do_split) { -+ /* Schedule the next continuing periodic split transfer */ -+ if (sched_next_periodic_split) { -+ -+ qh->sched_frame = frame_number; -+ if (dwc_frame_num_le(frame_number, -+ dwc_frame_num_inc(qh->start_split_frame, -+ 1))) { -+ /* -+ * Allow one frame to elapse after -+ * start split microframe before -+ * scheduling complete split, but DONT -+ * if we are doing the next start -+ * split in the same frame for an ISOC -+ * out. -+ */ -+ if ((qh->ep_type != USB_ENDPOINT_XFER_ISOC) -+ || (qh->ep_is_in != 0)) { -+ qh->sched_frame = -+ dwc_frame_num_inc(qh->sched_frame, -+ 1); -+ } -+ } -+ } else { -+ qh->sched_frame = -+ dwc_frame_num_inc(qh->start_split_frame, -+ qh->interval); -+ if (dwc_frame_num_le(qh->sched_frame, frame_number)) -+ qh->sched_frame = frame_number; -+ -+ qh->sched_frame |= 0x7; -+ qh->start_split_frame = qh->sched_frame; -+ } -+ } else { -+ qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, -+ qh->interval); -+ if (dwc_frame_num_le(qh->sched_frame, frame_number)) -+ qh->sched_frame = frame_number; -+ } -+ -+ if (list_empty(&qh->qtd_list)) { -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ } else { -+ /* -+ * Remove from periodic_sched_queued and move to -+ * appropriate queue. -+ */ -+ if (qh->sched_frame == frame_number) { -+ list_move(&qh->qh_list_entry, -+ &hcd->periodic_sched_ready); -+ } else { -+ list_move(&qh->qh_list_entry, -+ &hcd->periodic_sched_inactive); -+ } -+ } -+} -+ -+/** -+ * This function allocates and initializes a QTD. -+ * -+ * @urb: The URB to create a QTD from. Each URB-QTD pair will end up -+ * pointing to each other so each pair should have a unique correlation. -+ * -+ * Returns Returns pointer to the newly allocated QTD, or NULL on error. */ -+struct dwc_otg_qtd *dwc_otg_hcd_qtd_create(struct urb *urb) -+{ -+ struct dwc_otg_qtd *qtd; -+ -+ qtd = dwc_otg_hcd_qtd_alloc(); -+ if (qtd == NULL) -+ return NULL; -+ -+ dwc_otg_hcd_qtd_init(qtd, urb); -+ return qtd; -+} -+ -+/** -+ * Initializes a QTD structure. -+ * -+ * @qtd: The QTD to initialize. -+ * @urb: The URB to use for initialization. -+ */ -+void dwc_otg_hcd_qtd_init(struct dwc_otg_qtd *qtd, struct urb *urb) -+{ -+ memset(qtd, 0, sizeof(struct dwc_otg_qtd)); -+ qtd->urb = urb; -+ if (usb_pipecontrol(urb->pipe)) { -+ /* -+ * The only time the QTD data toggle is used is on the data -+ * phase of control transfers. This phase always starts with -+ * DATA1. -+ */ -+ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; -+ qtd->control_phase = DWC_OTG_CONTROL_SETUP; -+ } -+ -+ /* start split */ -+ qtd->complete_split = 0; -+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; -+ qtd->isoc_split_offset = 0; -+ -+ /* Store the qtd ptr in the urb to reference what QTD. */ -+ urb->hcpriv = qtd; -+ return; -+} -+ -+/** -+ * This function adds a QTD to the QTD-list of a QH. It will find the correct -+ * QH to place the QTD into. If it does not find a QH, then it will create a -+ * new QH. If the QH to which the QTD is added is not currently scheduled, it -+ * is placed into the proper schedule based on its EP type. -+ * -+ * @qtd: The QTD to add -+ * @dwc_otg_hcd: The DWC HCD structure -+ * -+ * Returns 0 if successful, negative error code otherwise. -+ */ -+int dwc_otg_hcd_qtd_add(struct dwc_otg_qtd *qtd, -+ struct dwc_otg_hcd *dwc_otg_hcd) -+{ -+ struct usb_host_endpoint *ep; -+ struct dwc_otg_qh *qh; -+ int retval = 0; -+ -+ struct urb *urb = qtd->urb; -+ -+ /* -+ * Get the QH which holds the QTD-list to insert to. Create QH if it -+ * doesn't exist. -+ */ -+ ep = dwc_urb_to_endpoint(urb); -+ qh = ep->hcpriv; -+ if (qh == NULL) { -+ qh = dwc_otg_hcd_qh_create(dwc_otg_hcd, urb); -+ if (qh == NULL) { -+ retval = -ENOMEM; -+ goto done; -+ } -+ ep->hcpriv = qh; -+ } -+ qtd->qh = qh; -+ retval = dwc_otg_hcd_qh_add(dwc_otg_hcd, qh); -+ if (retval == 0) -+ list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list); -+done: -+ return retval; -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_octeon.c b/drivers/usb/host/dwc_otg/dwc_otg_octeon.c -new file mode 100644 -index 0000000..5e92b3c ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_octeon.c -@@ -0,0 +1,1078 @@ -+/* ========================================================================== -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* permission constants */ -+#include -+#include -+ -+#include "dwc_otg_plat.h" -+#include "dwc_otg_attr.h" -+#include "dwc_otg_driver.h" -+#include "dwc_otg_cil.h" -+#ifndef DWC_HOST_ONLY -+#include "dwc_otg_pcd.h" -+#endif -+#include "dwc_otg_hcd.h" -+ -+#define DWC_DRIVER_VERSION "2.40a 10-APR-2006" -+#define DWC_DRIVER_DESC "HS OTG USB Controller driver" -+ -+static const char dwc_driver_name[] = "dwc_otg"; -+int dwc_errata_write_count; /* See dwc_otg_plat.h, dwc_write_reg32 */ -+ -+/*-------------------------------------------------------------------------*/ -+/* Encapsulate the module parameter settings */ -+ -+static struct dwc_otg_core_params dwc_otg_module_params = { -+ .opt = -1, -+ .otg_cap = -1, -+ .dma_enable = -1, -+ .dma_burst_size = -1, -+ .speed = -1, -+ .host_support_fs_ls_low_power = -1, -+ .host_ls_low_power_phy_clk = -1, -+ .enable_dynamic_fifo = -1, -+ .data_fifo_size = -1, -+ .dev_rx_fifo_size = -1, -+ .dev_nperio_tx_fifo_size = -1, -+ .dev_perio_tx_fifo_size = {-1, /* dev_perio_tx_fifo_size_1 */ -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1}, /* 15 */ -+ .host_rx_fifo_size = -1, -+ .host_nperio_tx_fifo_size = -1, -+ .host_perio_tx_fifo_size = -1, -+ .max_transfer_size = -1, -+ .max_packet_count = -1, -+ .host_channels = -1, -+ .dev_endpoints = -1, -+ .phy_type = -1, -+ .phy_utmi_width = -1, -+ .phy_ulpi_ddr = -1, -+ .phy_ulpi_ext_vbus = -1, -+ .i2c_enable = -1, -+ .ulpi_fs_ls = -1, -+ .ts_dline = -1, -+}; -+ -+/** -+ * Global Debug Level Mask. -+ */ -+uint32_t g_dbg_lvl; /* 0 -> OFF */ -+ -+/** -+ * This function shows the Driver Version. -+ */ -+static ssize_t version_show(struct device_driver *dev, char *buf) -+{ -+ return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n", -+ DWC_DRIVER_VERSION); -+} -+ -+static DRIVER_ATTR(version, S_IRUGO, version_show, NULL); -+ -+/** -+ * This function is called during module intialization to verify that -+ * the module parameters are in a valid state. -+ */ -+static int check_parameters(struct dwc_otg_core_if *core_if) -+{ -+ int i; -+ int retval = 0; -+ -+/* Checks if the parameter is outside of its valid range of values */ -+#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \ -+ ((dwc_otg_module_params._param_ < (_low_)) || \ -+ (dwc_otg_module_params._param_ > (_high_))) -+ -+/* If the parameter has been set by the user, check that the parameter value is -+ * within the value range of values. If not, report a module error. */ -+#define DWC_OTG_PARAM_ERR(_param_, _low_, _high_, _string_) \ -+ do { \ -+ if (dwc_otg_module_params._param_ != -1) { \ -+ if (DWC_OTG_PARAM_TEST(_param_, (_low_), (_high_))) { \ -+ DWC_ERROR("`%d' invalid for parameter `%s'\n", \ -+ dwc_otg_module_params._param_, _string_); \ -+ dwc_otg_module_params._param_ = dwc_param_##_param_##_default; \ -+ retval++; \ -+ } \ -+ } \ -+ } while (0) -+ -+ DWC_OTG_PARAM_ERR(opt, 0, 1, "opt"); -+ DWC_OTG_PARAM_ERR(otg_cap, 0, 2, "otg_cap"); -+ DWC_OTG_PARAM_ERR(dma_enable, 0, 1, "dma_enable"); -+ DWC_OTG_PARAM_ERR(speed, 0, 1, "speed"); -+ DWC_OTG_PARAM_ERR(host_support_fs_ls_low_power, 0, 1, -+ "host_support_fs_ls_low_power"); -+ DWC_OTG_PARAM_ERR(host_ls_low_power_phy_clk, 0, 1, -+ "host_ls_low_power_phy_clk"); -+ DWC_OTG_PARAM_ERR(enable_dynamic_fifo, 0, 1, "enable_dynamic_fifo"); -+ DWC_OTG_PARAM_ERR(data_fifo_size, 32, 32768, "data_fifo_size"); -+ DWC_OTG_PARAM_ERR(dev_rx_fifo_size, 16, 32768, "dev_rx_fifo_size"); -+ DWC_OTG_PARAM_ERR(dev_nperio_tx_fifo_size, 16, 32768, -+ "dev_nperio_tx_fifo_size"); -+ DWC_OTG_PARAM_ERR(host_rx_fifo_size, 16, 32768, "host_rx_fifo_size"); -+ DWC_OTG_PARAM_ERR(host_nperio_tx_fifo_size, 16, 32768, -+ "host_nperio_tx_fifo_size"); -+ DWC_OTG_PARAM_ERR(host_perio_tx_fifo_size, 16, 32768, -+ "host_perio_tx_fifo_size"); -+ DWC_OTG_PARAM_ERR(max_transfer_size, 2047, 524288, "max_transfer_size"); -+ DWC_OTG_PARAM_ERR(max_packet_count, 15, 511, "max_packet_count"); -+ DWC_OTG_PARAM_ERR(host_channels, 1, 16, "host_channels"); -+ DWC_OTG_PARAM_ERR(dev_endpoints, 1, 15, "dev_endpoints"); -+ DWC_OTG_PARAM_ERR(phy_type, 0, 2, "phy_type"); -+ DWC_OTG_PARAM_ERR(phy_ulpi_ddr, 0, 1, "phy_ulpi_ddr"); -+ DWC_OTG_PARAM_ERR(phy_ulpi_ext_vbus, 0, 1, "phy_ulpi_ext_vbus"); -+ DWC_OTG_PARAM_ERR(i2c_enable, 0, 1, "i2c_enable"); -+ DWC_OTG_PARAM_ERR(ulpi_fs_ls, 0, 1, "ulpi_fs_ls"); -+ DWC_OTG_PARAM_ERR(ts_dline, 0, 1, "ts_dline"); -+ -+ if (dwc_otg_module_params.dma_burst_size != -1) { -+ if (DWC_OTG_PARAM_TEST(dma_burst_size, 1, 1) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 4, 4) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 8, 8) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 16, 16) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 32, 32) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 64, 64) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 128, 128) && -+ DWC_OTG_PARAM_TEST(dma_burst_size, 256, 256)) { -+ DWC_ERROR -+ ("`%d' invalid for parameter `dma_burst_size'\n", -+ dwc_otg_module_params.dma_burst_size); -+ dwc_otg_module_params.dma_burst_size = 32; -+ retval++; -+ } -+ } -+ -+ if (dwc_otg_module_params.phy_utmi_width != -1) { -+ if (DWC_OTG_PARAM_TEST(phy_utmi_width, 8, 8) && -+ DWC_OTG_PARAM_TEST(phy_utmi_width, 16, 16)) { -+ DWC_ERROR -+ ("`%d' invalid for parameter `phy_utmi_width'\n", -+ dwc_otg_module_params.phy_utmi_width); -+ dwc_otg_module_params.phy_utmi_width = 16; -+ retval++; -+ } -+ } -+ -+ for (i = 0; i < 15; i++) { -+ /* @todo should be like above */ -+ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -+ (unsigned)-1) { -+ if (DWC_OTG_PARAM_TEST -+ (dev_perio_tx_fifo_size[i], 4, 768)) { -+ DWC_ERROR -+ ("`%d' invalid for parameter `%s_%d'\n", -+ dwc_otg_module_params. -+ dev_perio_tx_fifo_size[i], -+ "dev_perio_tx_fifo_size", i); -+ dwc_otg_module_params. -+ dev_perio_tx_fifo_size[i] = -+ dwc_param_dev_perio_tx_fifo_size_default; -+ retval++; -+ } -+ } -+ } -+ -+ /* At this point, all module parameters that have been set by the user -+ * are valid, and those that have not are left unset. Now set their -+ * default values and/or check the parameters against the hardware -+ * configurations of the OTG core. */ -+ -+/* This sets the parameter to the default value if it has not been set by the -+ * user */ -+#define PARAM_SET_DEFAULT(_param_) \ -+ ({ \ -+ int changed = 1; \ -+ if (dwc_otg_module_params._param_ == -1) { \ -+ changed = 0; \ -+ dwc_otg_module_params._param_ = dwc_param_##_param_##_default; \ -+ } \ -+ changed; \ -+ }) -+ -+/* This checks the macro agains the hardware configuration to see if it is -+ * valid. It is possible that the default value could be invalid. In this -+ * case, it will report a module error if the user touched the parameter. -+ * Otherwise it will adjust the value without any error. */ -+#define PARAM_CHECK_VALID(_param_, _str_, _is_valid_, _set_valid_) \ -+ ({ \ -+ int changed = PARAM_SET_DEFAULT(_param_); \ -+ int error = 0; \ -+ if (!(_is_valid_)) { \ -+ if (changed) { \ -+ DWC_ERROR("`%d' invalid for parameter `%s'. Check HW configuration.\n", dwc_otg_module_params._param_, _str_); \ -+ error = 1; \ -+ } \ -+ dwc_otg_module_params._param_ = (_set_valid_); \ -+ } \ -+ error; \ -+ }) -+ -+ /* OTG Cap */ -+ retval += PARAM_CHECK_VALID(otg_cap, "otg_cap", -+ ({ -+ int valid; -+ valid = 1; -+ switch (dwc_otg_module_params.otg_cap) { -+ case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE: -+ if (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) -+ valid = 0; -+ break; -+ case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: -+ if ((core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) -+ && (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) -+ && (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) -+ && (core_if->hwcfg2.b.op_mode != DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) -+ valid = 0; -+ break; -+ case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: -+ /* always valid */ -+ break; -+ } -+ valid; -+ }), -+ (((core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) -+ || (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) -+ || (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) -+ || (core_if->hwcfg2.b.op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) -+ ? -+ DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)); -+ -+ retval += PARAM_CHECK_VALID(dma_enable, "dma_enable", -+ ((dwc_otg_module_params. -+ dma_enable == 1) -+ && (core_if->hwcfg2.b. -+ architecture == 0)) ? 0 : 1, -+ 0); -+ -+ retval += PARAM_CHECK_VALID(opt, "opt", 1, 0); -+ -+ PARAM_SET_DEFAULT(dma_burst_size); -+ -+ retval += PARAM_CHECK_VALID(host_support_fs_ls_low_power, -+ "host_support_fs_ls_low_power", -+ 1, 0); -+ -+ retval += PARAM_CHECK_VALID(enable_dynamic_fifo, -+ "enable_dynamic_fifo", -+ ((dwc_otg_module_params.enable_dynamic_fifo == 0) -+ || (core_if->hwcfg2.b.dynamic_fifo == 1)), 0); -+ -+ retval += PARAM_CHECK_VALID(data_fifo_size, -+ "data_fifo_size", -+ dwc_otg_module_params.data_fifo_size <= core_if->hwcfg3.b.dfifo_depth, -+ core_if->hwcfg3.b.dfifo_depth); -+ -+ retval += PARAM_CHECK_VALID(dev_rx_fifo_size, -+ "dev_rx_fifo_size", -+ (dwc_otg_module_params.dev_rx_fifo_size <= -+ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)), -+ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)); -+ -+ retval += PARAM_CHECK_VALID(dev_nperio_tx_fifo_size, -+ "dev_nperio_tx_fifo_size", -+ dwc_otg_module_params.dev_nperio_tx_fifo_size <= -+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16), -+ dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16); -+ -+ retval += PARAM_CHECK_VALID(host_rx_fifo_size, -+ "host_rx_fifo_size", -+ dwc_otg_module_params.host_rx_fifo_size <= -+ dwc_read_reg32(&core_if->core_global_regs->grxfsiz), -+ dwc_read_reg32(&core_if->core_global_regs->grxfsiz)); -+ -+ retval += PARAM_CHECK_VALID(host_nperio_tx_fifo_size, -+ "host_nperio_tx_fifo_size", -+ dwc_otg_module_params.host_nperio_tx_fifo_size <= -+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16), -+ dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16); -+ -+ retval += PARAM_CHECK_VALID(host_perio_tx_fifo_size, -+ "host_perio_tx_fifo_size", -+ dwc_otg_module_params.host_perio_tx_fifo_size <= -+ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16), -+ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16)); -+ -+ retval += PARAM_CHECK_VALID(max_transfer_size, -+ "max_transfer_size", -+ dwc_otg_module_params.max_transfer_size < -+ (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11)), -+ (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11)) - 1); -+ -+ retval += PARAM_CHECK_VALID(max_packet_count, -+ "max_packet_count", -+ dwc_otg_module_params.max_packet_count < -+ (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)), -+ (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1); -+ -+ retval += PARAM_CHECK_VALID(host_channels, -+ "host_channels", -+ dwc_otg_module_params.host_channels <= (core_if->hwcfg2.b.num_host_chan + 1), -+ core_if->hwcfg2.b.num_host_chan + 1); -+ -+ retval += PARAM_CHECK_VALID(dev_endpoints, -+ "dev_endpoints", -+ dwc_otg_module_params.dev_endpoints <= core_if->hwcfg2.b.num_dev_ep, -+ core_if->hwcfg2.b.num_dev_ep); -+ -+/* -+ * Define the following to disable the FS PHY Hardware checking. This is for -+ * internal testing only. -+ * -+ * #define NO_FS_PHY_HW_CHECKS -+ */ -+ -+#ifdef NO_FS_PHY_HW_CHECKS -+ retval += PARAM_CHECK_VALID(phy_type, "phy_type", 1, 0); -+#else -+ retval += PARAM_CHECK_VALID(phy_type, "phy_type", -+ ({ -+ int valid = 0; -+ if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_UTMI) && ((core_if->hwcfg2.b.hs_phy_type == 1) || (core_if->hwcfg2.b.hs_phy_type == 3))) -+ valid = 1; -+ else if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_ULPI) && ((core_if->hwcfg2.b.hs_phy_type == 2) || (core_if->hwcfg2.b.hs_phy_type == 3))) -+ valid = 1; -+ else if ((dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) && (core_if->hwcfg2.b.fs_phy_type == 1)) -+ valid = 1; -+ valid; -+ }), -+ ({ -+ int set = DWC_PHY_TYPE_PARAM_FS; -+ if (core_if->hwcfg2.b.hs_phy_type) { -+ if ((core_if->hwcfg2.b.hs_phy_type == 3) -+ || (core_if->hwcfg2.b.hs_phy_type == 1)) -+ set = DWC_PHY_TYPE_PARAM_UTMI; -+ else -+ set = DWC_PHY_TYPE_PARAM_ULPI; -+ } -+ set; -+ })); -+#endif -+ -+ retval += PARAM_CHECK_VALID(speed, "speed", -+ dwc_otg_module_params.speed == 0 -+ && (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? 0 : 1, -+ dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS ? 1 : 0); -+ -+ retval += PARAM_CHECK_VALID(host_ls_low_power_phy_clk, -+ "host_ls_low_power_phy_clk", -+ dwc_otg_module_params.host_ls_low_power_phy_clk == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ -+ && (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? 0 : 1, -+ (dwc_otg_module_params.phy_type == DWC_PHY_TYPE_PARAM_FS) ? -+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ : DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ); -+ -+ PARAM_SET_DEFAULT(phy_ulpi_ddr); -+ PARAM_SET_DEFAULT(phy_ulpi_ext_vbus); -+ PARAM_SET_DEFAULT(phy_utmi_width); -+ PARAM_SET_DEFAULT(ulpi_fs_ls); -+ PARAM_SET_DEFAULT(ts_dline); -+ -+#ifdef NO_FS_PHY_HW_CHECKS -+ retval += PARAM_CHECK_VALID(i2c_enable, "i2c_enable", 1, 0); -+#else -+ retval += PARAM_CHECK_VALID(i2c_enable, "i2c_enable", -+ dwc_otg_module_params.i2c_enable == 1 -+ && (core_if->hwcfg3.b.i2c == 0) ? 0 : 1, 0); -+#endif -+ -+ for (i = 0; i < 15; i++) { -+ -+ int changed = 1; -+ int error = 0; -+ -+ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] == -1) { -+ changed = 0; -+ dwc_otg_module_params.dev_perio_tx_fifo_size[i] = -+ dwc_param_dev_perio_tx_fifo_size_default; -+ } -+ if (! -+ (dwc_otg_module_params.dev_perio_tx_fifo_size[i] <= -+ (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz[i])))) { -+ if (changed) { -+ DWC_ERROR("`%d' invalid for parameter " -+ "`dev_perio_fifo_size_%d'. " -+ "Check HW configuration.\n", -+ dwc_otg_module_params. -+ dev_perio_tx_fifo_size[i], i); -+ error = 1; -+ } -+ dwc_otg_module_params.dev_perio_tx_fifo_size[i] = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ dptxfsiz[i]); -+ } -+ retval += error; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function is the top level interrupt handler for the Common -+ * (Device and host modes) interrupts. -+ */ -+static irqreturn_t dwc_otg_common_irq(int _irq, void *_dev) -+{ -+ struct dwc_otg_device *otg_dev = _dev; -+ int32_t retval = IRQ_NONE; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&otg_dev->hcd->global_lock, flags); -+ -+ retval = dwc_otg_handle_common_intr(otg_dev->core_if); -+ -+ spin_unlock_irqrestore(&otg_dev->hcd->global_lock, flags); -+ -+ return IRQ_RETVAL(retval); -+} -+ -+/** -+ * This function is called when a device is unregistered with the -+ * dwc_otg_driver. This happens, for example, when the rmmod command is -+ * executed. The device may or may not be electrically present. If it is -+ * present, the driver stops device processing. Any resources used on behalf -+ * of this device are freed. -+ * -+ * @dev: -+ */ -+static int dwc_otg_driver_remove(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct dwc_otg_device *otg_dev = dev->platform_data; -+ DWC_DEBUGPL(DBG_ANY, "%s(%p)\n", __func__, dev); -+ -+ if (otg_dev == NULL) -+ /* Memory allocation for the dwc_otg_device failed. */ -+ return -ENOMEM; -+ -+ /* -+ * Free the IRQ -+ */ -+ if (otg_dev->common_irq_installed) -+ free_irq(platform_get_irq(to_platform_device(dev), 0), otg_dev); -+ -+#ifndef DWC_DEVICE_ONLY -+ if (otg_dev->hcd != NULL) -+ dwc_otg_hcd_remove(dev); -+#endif -+ -+#ifndef DWC_HOST_ONLY -+ if (otg_dev->pcd != NULL) -+ dwc_otg_pcd_remove(dev); -+#endif -+ if (otg_dev->core_if != NULL) -+ dwc_otg_cil_remove(otg_dev->core_if); -+ -+ /* -+ * Remove the device attributes -+ */ -+ dwc_otg_attr_remove(dev); -+ -+ /* -+ * Clear the platform_data pointer. -+ */ -+ dev->platform_data = 0; -+ return 0; -+} -+ -+/** -+ * This function is called when an device is bound to a -+ * dwc_otg_driver. It creates the driver components required to -+ * control the device (CIL, HCD, and PCD) and it initializes the -+ * device. The driver components are stored in a dwc_otg_device -+ * structure. A reference to the dwc_otg_device is saved in the -+ * device. This allows the driver to access the dwc_otg_device -+ * structure on subsequent calls to driver methods for this device. -+ * -+ * @dev: device definition -+ */ -+static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) -+{ -+ struct resource *res_base; -+ struct device *dev = &pdev->dev; -+ struct dwc_otg_device *dwc_otg_device; -+ int32_t snpsid; -+ unsigned long flags; -+ int irq; -+ int retval; -+ -+ dev_dbg(dev, "dwc_otg_driver_probe(%p)\n", dev); -+ -+ dwc_otg_device = devm_kzalloc(&pdev->dev, -+ sizeof(struct dwc_otg_device), -+ GFP_KERNEL); -+ if (!dwc_otg_device) { -+ dev_err(dev, "kmalloc of dwc_otg_device failed\n"); -+ return -ENOMEM; -+ } -+ dwc_otg_device->reg_offset = 0xFFFFFFFF; -+ -+ /* -+ * Map the DWC_otg Core memory into virtual address space. -+ */ -+ res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res_base) -+ goto err_ports; -+ -+ dwc_otg_device->base = -+ devm_ioremap_nocache(&pdev->dev, -+ res_base->start, -+ res_base->end - res_base->start); -+ -+ if (!dwc_otg_device->base) -+ goto err_ports; -+ -+ dev_dbg(dev, "base=%p\n", dwc_otg_device->base); -+ -+ /* -+ * Attempt to ensure this device is really a DWC_otg Controller. -+ * Read and verify the SNPSID register contents. The value should be -+ * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX". -+ */ -+ snpsid = -+ dwc_read_reg32((uint32_t *) ((uint8_t *) dwc_otg_device->base + -+ 0x40)); -+ if ((snpsid & 0xFFFFF000) != 0x4F542000) { -+ dev_err(dev, "Bad value for SNPSID: 0x%08x\n", snpsid); -+ goto err_ports; -+ } -+ -+ /* -+ * Initialize driver data to point to the global DWC_otg -+ * Device structure. -+ */ -+ dev->platform_data = dwc_otg_device; -+ dev_dbg(dev, "dwc_otg_device=0x%p\n", dwc_otg_device); -+ -+ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base, -+ &dwc_otg_module_params); -+ if (dwc_otg_device->core_if == 0) { -+ dev_err(dev, "CIL initialization failed!\n"); -+ goto err_ports; -+ } -+ dwc_otg_device->core_if->usb_num = to_platform_device(dev)->id; -+ -+ /* -+ * Validate parameter values. -+ */ -+ if (check_parameters(dwc_otg_device->core_if) != 0) -+ goto err_ports; -+ -+ /* -+ * Create Device Attributes in sysfs -+ */ -+ dwc_otg_attr_create(dev); -+ -+ /* -+ * Disable the global interrupt until all the interrupt -+ * handlers are installed. -+ */ -+ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); -+ /* -+ * Install the interrupt handler for the common interrupts before -+ * enabling common interrupts in core_init below. -+ */ -+ irq = platform_get_irq(to_platform_device(dev), 0); -+ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", irq); -+ retval = request_irq(irq, dwc_otg_common_irq, -+ IRQF_SHARED, "dwc_otg", dwc_otg_device); -+ if (retval != 0) { -+ DWC_ERROR("request of irq%d failed\n", irq); -+ goto err_ports; -+ } else { -+ dwc_otg_device->common_irq_installed = 1; -+ } -+ -+ /* -+ * Initialize the DWC_otg core. -+ */ -+ dwc_otg_core_init(dwc_otg_device->core_if); -+ -+#ifndef DWC_HOST_ONLY -+ /* -+ * Initialize the PCD -+ */ -+ retval = dwc_otg_pcd_init(dev); -+ if (retval != 0) { -+ DWC_ERROR("dwc_otg_pcd_init failed\n"); -+ dwc_otg_device->pcd = NULL; -+ goto err_ports; -+ } -+#endif -+#ifndef DWC_DEVICE_ONLY -+ /* -+ * Initialize the HCD -+ */ -+ retval = dwc_otg_hcd_init(dev); -+ if (retval != 0) { -+ DWC_ERROR("dwc_otg_hcd_init failed\n"); -+ dwc_otg_device->hcd = NULL; -+ goto err_ports; -+ } -+#endif -+ -+ /* -+ * Enable the global interrupt after all the interrupt -+ * handlers are installed. -+ */ -+ local_irq_save(flags); -+ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); -+ local_irq_restore(flags); -+ -+ return 0; -+ -+err_ports: -+ devm_kfree(&pdev->dev, dwc_otg_device); -+ return -ENOENT; -+} -+ -+/** -+ * This structure defines the methods to be called by a bus driver -+ * during the lifecycle of a device on that bus. Both drivers and -+ * devices are registered with a bus driver. The bus driver matches -+ * devices to drivers based on information in the device and driver -+ * structures. -+ * -+ * The probe function is called when the bus driver matches a device -+ * to this driver. The remove function is called when a device is -+ * unregistered with the bus driver. -+ */ -+static struct platform_driver dwc_otg_driver = { -+ .probe = dwc_otg_driver_probe, -+ .remove = dwc_otg_driver_remove, -+ .driver = { -+ .name = dwc_driver_name, -+ .owner = THIS_MODULE}, -+}; -+ -+/** -+ * This function is called when the dwc_otg_driver is installed with the -+ * insmod command. It registers the dwc_otg_driver structure with the -+ * appropriate bus driver. This will cause the dwc_otg_driver_probe function -+ * to be called. In addition, the bus driver will automatically expose -+ * attributes defined for the device and driver in the special sysfs file -+ * system. -+ * -+ * Returns -+ */ -+static int __init dwc_otg_driver_init(void) -+{ -+ int retval; -+ -+ pr_info("%s: version %s\n", dwc_driver_name, DWC_DRIVER_VERSION); -+ -+ /* Though core was configured for external dma override that with slave -+ mode only for CN31XX. DMA is broken in this chip */ -+ if (OCTEON_IS_MODEL(OCTEON_CN31XX)) -+ dwc_otg_module_params.dma_enable = 0; -+ -+ retval = platform_driver_register(&dwc_otg_driver); -+ -+ if (retval < 0) { -+ pr_err("%s retval=%d\n", __func__, retval); -+ return retval; -+ } -+ if (driver_create_file(&dwc_otg_driver.driver, &driver_attr_version)) -+ pr_warning("DWC_OTG: Failed to create driver version file\n"); -+ -+ return retval; -+} -+module_init(dwc_otg_driver_init); -+ -+/** -+ * This function is called when the driver is removed from the kernel -+ * with the rmmod command. The driver unregisters itself with its bus -+ * driver. -+ * -+ */ -+static void __exit dwc_otg_driver_cleanup(void) -+{ -+ printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n"); -+ -+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); -+ -+ platform_driver_unregister(&dwc_otg_driver); -+ -+ printk(KERN_INFO "%s module removed\n", dwc_driver_name); -+} -+module_exit(dwc_otg_driver_cleanup); -+ -+MODULE_DESCRIPTION(DWC_DRIVER_DESC); -+MODULE_AUTHOR("Synopsys Inc."); -+MODULE_LICENSE("GPL"); -+ -+module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444); -+MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None"); -+module_param_named(opt, dwc_otg_module_params.opt, int, 0444); -+MODULE_PARM_DESC(opt, "OPT Mode"); -+module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444); -+MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled"); -+module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int, -+ 0444); -+MODULE_PARM_DESC(dma_burst_size, -+ "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256"); -+module_param_named(speed, dwc_otg_module_params.speed, int, 0444); -+MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed"); -+module_param_named(host_support_fs_ls_low_power, -+ dwc_otg_module_params.host_support_fs_ls_low_power, int, -+ 0444); -+MODULE_PARM_DESC(host_support_fs_ls_low_power, -+ "Support Low Power w/FS or LS 0=Support 1=Don't Support"); -+module_param_named(host_ls_low_power_phy_clk, -+ dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444); -+MODULE_PARM_DESC(host_ls_low_power_phy_clk, -+ "Low Speed Low Power Clock 0=48Mhz 1=6Mhz"); -+module_param_named(enable_dynamic_fifo, -+ dwc_otg_module_params.enable_dynamic_fifo, int, 0444); -+MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing"); -+module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int, -+ 0444); -+MODULE_PARM_DESC(data_fifo_size, -+ "Total number of words in the data FIFO memory 32-32768"); -+module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size, -+ int, 0444); -+MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); -+module_param_named(dev_nperio_tx_fifo_size, -+ dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444); -+MODULE_PARM_DESC(dev_nperio_tx_fifo_size, -+ "Number of words in the non-periodic Tx FIFO 16-32768"); -+module_param_named(dev_perio_tx_fifo_size_1, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_1, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_2, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_2, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_3, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_3, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_4, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_4, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_5, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_5, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_6, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_6, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_7, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_7, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_8, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_8, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_9, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_9, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_10, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_10, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_11, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_11, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_12, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_12, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_13, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_13, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_14, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_14, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_15, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_15, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size, -+ int, 0444); -+MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); -+module_param_named(host_nperio_tx_fifo_size, -+ dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444); -+MODULE_PARM_DESC(host_nperio_tx_fifo_size, -+ "Number of words in the non-periodic Tx FIFO 16-32768"); -+module_param_named(host_perio_tx_fifo_size, -+ dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444); -+MODULE_PARM_DESC(host_perio_tx_fifo_size, -+ "Number of words in the host periodic Tx FIFO 16-32768"); -+module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size, -+ int, 0444); -+/** @todo Set the max to 512K, modify checks */ -+MODULE_PARM_DESC(max_transfer_size, -+ "The maximum transfer size supported in bytes 2047-65535"); -+module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count, -+ int, 0444); -+MODULE_PARM_DESC(max_packet_count, -+ "The maximum number of packets in a transfer 15-511"); -+module_param_named(host_channels, dwc_otg_module_params.host_channels, int, -+ 0444); -+MODULE_PARM_DESC(host_channels, -+ "The number of host channel registers to use 1-16"); -+module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int, -+ 0444); -+MODULE_PARM_DESC(dev_endpoints, -+ "The number of endpoints in addition to EP0 available " -+ "for device mode 1-15"); -+module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444); -+MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI"); -+module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int, -+ 0444); -+MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits"); -+module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444); -+MODULE_PARM_DESC(phy_ulpi_ddr, -+ "ULPI at double or single data rate 0=Single 1=Double"); -+module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus, -+ int, 0444); -+MODULE_PARM_DESC(phy_ulpi_ext_vbus, -+ "ULPI PHY using internal or external vbus 0=Internal"); -+module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444); -+MODULE_PARM_DESC(i2c_enable, "FS PHY Interface"); -+module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444); -+MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only"); -+module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444); -+MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs"); -+module_param_named(debug, g_dbg_lvl, int, 0644); -+MODULE_PARM_DESC(debug, ""); -+ -+/** @page "Module Parameters" -+ * -+ * The following parameters may be specified when starting the module. -+ * These parameters define how the DWC_otg controller should be -+ * configured. Parameter values are passed to the CIL initialization -+ * function dwc_otg_cil_init -+ * -+ * Example: modprobe dwc_otg speed=1 otg_cap=1 -+ * -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+*/ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_plat.h b/drivers/usb/host/dwc_otg/dwc_otg_plat.h -new file mode 100644 -index 0000000..93ef282 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_plat.h -@@ -0,0 +1,236 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_OTG_PLAT_H__) -+#define __DWC_OTG_PLAT_H__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define SZ_256K 0x00040000 -+#ifndef CONFIG_64BIT -+#define OCTEON_USB_BASE_ADDRESS 0x80016F0010000000ull -+#endif -+ -+/** -+ * @file -+ * -+ * This file contains the Platform Specific constants, interfaces -+ * (functions and macros) for Linux. -+ * -+ */ -+ -+/** -+ * Reads the content of a register. -+ * -+ * @_reg: address of register to read. -+ * Returns contents of the register. -+ * -+ -+ * Usage:
-+ * uint32_t dev_ctl = dwc_read_reg32(&dev_regs->dctl); -+ */ -+static inline uint32_t dwc_read_reg32(uint32_t *_reg) -+{ -+ uint32_t result; -+ /* USB device registers on Octeon are 32bit address swapped */ -+#ifdef CONFIG_64BIT -+ uint64_t address = (unsigned long)_reg ^ 4; -+#else -+ uint64_t address = OCTEON_USB_BASE_ADDRESS | ((unsigned long)_reg ^ 4); -+#endif -+ result = cvmx_read64_uint32(address); -+ return result; -+}; -+ -+/** -+ * Writes a register with a 32 bit value. -+ * -+ * @_reg: address of register to read. -+ * @_value: to write to _reg. -+ * -+ * Usage:
-+ * dwc_write_reg32(&dev_regs->dctl, 0); -+ */ -+static inline void dwc_write_reg32(uint32_t *_reg, -+ const uint32_t _value) -+{ -+ /* USB device registers on Octeon are 32bit address swapped */ -+#ifdef CONFIG_64BIT -+ uint64_t address = (unsigned long)_reg ^ 4; -+#else -+ uint64_t address = OCTEON_USB_BASE_ADDRESS | ((unsigned long)_reg ^ 4); -+#endif -+ wmb(); -+ cvmx_write64_uint32(address, _value); -+ -+#ifdef CONFIG_CPU_CAVIUM_OCTEON -+ /* O2P/O1P pass 1 bug workaround: A read must occur for at least -+ every 3rd write to insure that the writes do not overrun the -+ USBN. */ -+ if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)) { -+ extern int dwc_errata_write_count; -+ if (++dwc_errata_write_count > 2) { -+ cvmx_read_csr(CVMX_USBNX_DMA0_INB_CHN0(0)); -+ dwc_errata_write_count = 0; -+ } -+ } -+#endif -+}; -+ -+/** -+ * This function modifies bit values in a register. Using the -+ * algorithm: (reg_contents & ~clear_mask) | set_mask. -+ * -+ * @_reg: address of register to read. -+ * @_clear_mask: bit mask to be cleared. -+ * @_set_mask: bit mask to be set. -+ * -+ * Usage:
-+ * // Clear the SOF Interrupt Mask bit and
-+ * // set the OTG Interrupt mask bit, leaving all others as they were. -+ * dwc_modify_reg32(&dev_regs->gintmsk, DWC_SOF_INT, DWC_OTG_INT);
-+ */ -+static inline void dwc_modify_reg32(uint32_t *_reg, -+ const uint32_t _clear_mask, -+ const uint32_t _set_mask) -+{ -+ uint32_t value = dwc_read_reg32(_reg); -+ value &= ~_clear_mask; -+ value |= _set_mask; -+ dwc_write_reg32(_reg, value); -+}; -+ -+/* -+ * Debugging support vanishes in non-debug builds. -+ */ -+ -+/** -+ * The Debug Level bit-mask variable. -+ */ -+extern uint32_t g_dbg_lvl; -+/** -+ * Set the Debug Level variable. -+ */ -+static inline uint32_t SET_DEBUG_LEVEL(const uint32_t _new) -+{ -+ uint32_t old = g_dbg_lvl; -+ g_dbg_lvl = _new; -+ return old; -+} -+ -+/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ -+#define DBG_CIL (0x2) -+/** When debug level has the DBG_CILV bit set, display CIL Verbose debug -+ * messages */ -+#define DBG_CILV (0x20) -+/** When debug level has the DBG_PCD bit set, display PCD (Device) debug -+ * messages */ -+#define DBG_PCD (0x4) -+/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug -+ * messages */ -+#define DBG_PCDV (0x40) -+/** When debug level has the DBG_HCD bit set, display Host debug messages */ -+#define DBG_HCD (0x8) -+/** When debug level has the DBG_HCDV bit set, display Verbose Host debug -+ * messages */ -+#define DBG_HCDV (0x80) -+/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host -+ * mode. */ -+#define DBG_HCD_URB (0x800) -+ -+/** When debug level has any bit set, display debug messages */ -+#define DBG_ANY (0xFF) -+ -+/** All debug messages off */ -+#define DBG_OFF 0 -+ -+/** Prefix string for DWC_DEBUG print macros. */ -+#define USB_DWC "DWC_otg: " -+ -+/** -+ * Print a debug message when the Global debug level variable contains -+ * the bit defined in lvl. -+ * -+ * @lvl: - Debug level, use one of the DBG_ constants above. -+ * @x: - like printf -+ * -+ * Example:

-+ * -+ * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); -+ * -+ *
-+ * results in:
-+ * -+ * usb-DWC_otg: dwc_otg_cil_init(ca867000) -+ * -+ */ -+#ifdef DEBUG -+ -+# define DWC_DEBUGPL(lvl, x...) \ -+ do { \ -+ if ((lvl)&g_dbg_lvl) \ -+ printk(KERN_DEBUG USB_DWC x); \ -+ } while (0) -+# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x) -+ -+# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) -+ -+#else -+ -+# define DWC_DEBUGPL(lvl, x...) do { } while (0) -+# define DWC_DEBUGP(x...) -+ -+# define CHK_DEBUG_LEVEL(level) (0) -+ -+#endif /*DEBUG*/ -+/* -+ * Print an Error message. -+ */ -+#define DWC_ERROR(x...) printk(KERN_ERR USB_DWC x) -+/* -+ * Print a Warning message. -+ */ -+#define DWC_WARN(x...) printk(KERN_WARNING USB_DWC x) -+/* -+ * Print a notice (normal but significant message). -+ */ -+#define DWC_NOTICE(x...) printk(KERN_NOTICE USB_DWC x) -+/* -+ * Basic message printing. -+ */ -+#define DWC_PRINT(x...) printk(KERN_INFO USB_DWC x) -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -new file mode 100644 -index 0000000..34cc4f7 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -@@ -0,0 +1,2355 @@ -+/* ========================================================================== -+ * -+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, -+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -+ * otherwise expressly agreed to in writing between Synopsys and you. -+ * -+ * The Software IS NOT an item of Licensed Software or Licensed Product under -+ * any End User Software License Agreement or Agreement for Licensed Product -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+ -+#ifndef __DWC_OTG_REGS_H__ -+#define __DWC_OTG_REGS_H__ -+ -+/* -+ * -+ * This file contains the data structures for accessing the DWC_otg -+ * core registers. -+ * -+ * The application interfaces with the HS OTG core by reading from and -+ * writing to the Control and Status Register (CSR) space through the -+ * AHB Slave interface. These registers are 32 bits wide, and the -+ * addresses are 32-bit-block aligned. -+ * CSRs are classified as follows: -+ * - Core Global Registers -+ * - Device Mode Registers -+ * - Device Global Registers -+ * - Device Endpoint Specific Registers -+ * - Host Mode Registers -+ * - Host Global Registers -+ * - Host Port CSRs -+ * - Host Channel Specific Registers -+ * -+ * Only the Core Global registers can be accessed in both Device and -+ * Host modes. When the HS OTG core is operating in one mode, either -+ * Device or Host, the application must not access registers from the -+ * other mode. When the core switches from one mode to another, the -+ * registers in the new mode of operation must be reprogrammed as they -+ * would be after a power-on reset. -+ */ -+ -+/****************************************************************************/ -+/* DWC_otg Core registers . -+ * The dwc_otg_core_global_regs structure defines the size -+ * and relative field offsets for the Core Global registers. -+ */ -+struct dwc_otg_core_global_regs { -+ /* OTG Control and Status Register. Offset: 000h */ -+ uint32_t gotgctl; -+ /* OTG Interrupt Register. Offset: 004h */ -+ uint32_t gotgint; -+ /* Core AHB Configuration Register. Offset: 008h */ -+ uint32_t gahbcfg; -+#define DWC_GLBINTRMASK 0x0001 -+#define DWC_DMAENABLE 0x0020 -+#define DWC_NPTXEMPTYLVL_EMPTY 0x0080 -+#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000 -+#define DWC_PTXEMPTYLVL_EMPTY 0x0100 -+#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000 -+ -+ /* Core USB Configuration Register. Offset: 00Ch */ -+ uint32_t gusbcfg; -+ /* Core Reset Register. Offset: 010h */ -+ uint32_t grstctl; -+ /* Core Interrupt Register. Offset: 014h */ -+ uint32_t gintsts; -+ /* Core Interrupt Mask Register. Offset: 018h */ -+ uint32_t gintmsk; -+ /* Receive Status Queue Read Register (Read Only). Offset: 01Ch */ -+ uint32_t grxstsr; -+ /* Receive Status Queue Read & POP Register (Read Only). Offset: 020h*/ -+ uint32_t grxstsp; -+ /* Receive FIFO Size Register. Offset: 024h */ -+ uint32_t grxfsiz; -+ /* Non Periodic Transmit FIFO Size Register. Offset: 028h */ -+ uint32_t gnptxfsiz; -+ /* -+ *Non Periodic Transmit FIFO/Queue Status Register (Read -+ * Only). Offset: 02Ch -+ */ -+ uint32_t gnptxsts; -+ /* I2C Access Register. Offset: 030h */ -+ uint32_t gi2cctl; -+ /* PHY Vendor Control Register. Offset: 034h */ -+ uint32_t gpvndctl; -+ /* General Purpose Input/Output Register. Offset: 038h */ -+ uint32_t ggpio; -+ /* User ID Register. Offset: 03Ch */ -+ uint32_t guid; -+ /* Synopsys ID Register (Read Only). Offset: 040h */ -+ uint32_t gsnpsid; -+ /* User HW Config1 Register (Read Only). Offset: 044h */ -+ uint32_t ghwcfg1; -+ /* User HW Config2 Register (Read Only). Offset: 048h */ -+ uint32_t ghwcfg2; -+#define DWC_SLAVE_ONLY_ARCH 0 -+#define DWC_EXT_DMA_ARCH 1 -+#define DWC_INT_DMA_ARCH 2 -+ -+#define DWC_MODE_HNP_SRP_CAPABLE 0 -+#define DWC_MODE_SRP_ONLY_CAPABLE 1 -+#define DWC_MODE_NO_HNP_SRP_CAPABLE 2 -+#define DWC_MODE_SRP_CAPABLE_DEVICE 3 -+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4 -+#define DWC_MODE_SRP_CAPABLE_HOST 5 -+#define DWC_MODE_NO_SRP_CAPABLE_HOST 6 -+ -+ /* User HW Config3 Register (Read Only). Offset: 04Ch */ -+ uint32_t ghwcfg3; -+ /* User HW Config4 Register (Read Only). Offset: 050h*/ -+ uint32_t ghwcfg4; -+ /* Reserved Offset: 054h-0FFh */ -+ uint32_t reserved[43]; -+ /* Host Periodic Transmit FIFO Size Register. Offset: 100h */ -+ uint32_t hptxfsiz; -+ /* -+ * Device Periodic Transmit FIFO#n Register. -+ * Offset: 104h + (FIFO_Number-1)*04h, -+ * 1 <= FIFO Number <= 15 (1<=n<=15). -+ */ -+ uint32_t dptxfsiz[15]; -+}; -+ -+/* -+ * This union represents the bit fields of the Core OTG Control -+ * and Status Register (GOTGCTL). Set the bits using the bit -+ * fields then write the d32 value to the register. -+ */ -+union gotgctl_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved21_31:11; -+ unsigned currmod:1; -+ unsigned bsesvld:1; -+ unsigned asesvld:1; -+ unsigned reserved17:1; -+ unsigned conidsts:1; -+ unsigned reserved12_15:4; -+ unsigned devhnpen:1; -+ unsigned hstsethnpen:1; -+ unsigned hnpreq:1; -+ unsigned hstnegscs:1; -+ unsigned reserved2_7:6; -+ unsigned sesreq:1; -+ unsigned sesreqscs:1; -+#else -+ unsigned sesreqscs:1; -+ unsigned sesreq:1; -+ unsigned reserved2_7:6; -+ unsigned hstnegscs:1; -+ unsigned hnpreq:1; -+ unsigned hstsethnpen:1; -+ unsigned devhnpen:1; -+ unsigned reserved12_15:4; -+ unsigned conidsts:1; -+ unsigned reserved17:1; -+ unsigned asesvld:1; -+ unsigned bsesvld:1; -+ unsigned currmod:1; -+ unsigned reserved21_31:11; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields of the Core OTG Interrupt Register -+ * (GOTGINT). Set/clear the bits using the bit fields then write the d32 -+ * value to the register. -+ */ -+union gotgint_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved31_20:12; -+ unsigned debdone:1; -+ unsigned adevtoutchng:1; -+ unsigned hstnegdet:1; -+ unsigned reserver10_16:7; -+ unsigned hstnegsucstschng:1; -+ unsigned sesreqsucstschng:1; -+ unsigned reserved3_7:5; -+ unsigned sesenddet:1; -+ unsigned reserved0_1:2; -+#else -+ -+ /* Current Mode */ -+ unsigned reserved0_1:2; -+ -+ /* Session End Detected */ -+ unsigned sesenddet:1; -+ -+ unsigned reserved3_7:5; -+ -+ /* Session Request Success Status Change */ -+ unsigned sesreqsucstschng:1; -+ /* Host Negotiation Success Status Change */ -+ unsigned hstnegsucstschng:1; -+ -+ unsigned reserver10_16:7; -+ -+ /* Host Negotiation Detected */ -+ unsigned hstnegdet:1; -+ /* A-Device Timeout Change */ -+ unsigned adevtoutchng:1; -+ /* Debounce Done */ -+ unsigned debdone:1; -+ -+ unsigned reserved31_20:12; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields of the Core AHB Configuration -+ * Register (GAHBCFG). Set/clear the bits using the bit fields then -+ * write the d32 value to the register. -+ */ -+union gahbcfg_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 -+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1 -+#define DWC_GAHBCFG_DMAENABLE 1 -+#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7 -+#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5 -+#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3 -+#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1 -+#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0 -+#define DWC_GAHBCFG_GLBINT_ENABLE 1 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved9_31:23; -+ unsigned ptxfemplvl:1; -+ unsigned nptxfemplvl:1; -+ unsigned reserved:1; -+ unsigned dmaenable:1; -+ unsigned hburstlen:4; -+ unsigned glblintrmsk:1; -+#else -+ unsigned glblintrmsk:1; -+ unsigned hburstlen:4; -+ unsigned dmaenable:1; -+ unsigned reserved:1; -+ unsigned nptxfemplvl:1; -+ unsigned ptxfemplvl:1; -+ unsigned reserved9_31:23; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields of the Core USB Configuration -+ * Register (GUSBCFG). Set the bits using the bit fields then write -+ * the d32 value to the register. -+ */ -+union gusbcfg_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:9; -+ unsigned term_sel_dl_pulse:1; -+ unsigned ulpi_int_vbus_indicator:1; -+ unsigned ulpi_ext_vbus_drv:1; -+ unsigned ulpi_clk_sus_m:1; -+ unsigned ulpi_auto_res:1; -+ unsigned ulpi_fsls:1; -+ unsigned otgutmifssel:1; -+ unsigned phylpwrclksel:1; -+ unsigned nptxfrwnden:1; -+ unsigned usbtrdtim:4; -+ unsigned hnpcap:1; -+ unsigned srpcap:1; -+ unsigned ddrsel:1; -+ unsigned physel:1; -+ unsigned fsintf:1; -+ unsigned ulpi_utmi_sel:1; -+ unsigned phyif:1; -+ unsigned toutcal:3; -+#else -+ unsigned toutcal:3; -+ unsigned phyif:1; -+ unsigned ulpi_utmi_sel:1; -+ unsigned fsintf:1; -+ unsigned physel:1; -+ unsigned ddrsel:1; -+ unsigned srpcap:1; -+ unsigned hnpcap:1; -+ unsigned usbtrdtim:4; -+ unsigned nptxfrwnden:1; -+ unsigned phylpwrclksel:1; -+ unsigned otgutmifssel:1; -+ unsigned ulpi_fsls:1; -+ unsigned ulpi_auto_res:1; -+ unsigned ulpi_clk_sus_m:1; -+ unsigned ulpi_ext_vbus_drv:1; -+ unsigned ulpi_int_vbus_indicator:1; -+ unsigned term_sel_dl_pulse:1; -+ unsigned reserved:9; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields of the Core Reset Register -+ * (GRSTCTL). Set/clear the bits using the bit fields then write the -+ * d32 value to the register. -+ */ -+union grstctl_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned ahbidle:1; -+ unsigned dmareq:1; -+ unsigned reserved11_29:19; -+ unsigned txfnum:5; -+ unsigned txfflsh:1; -+ unsigned rxfflsh:1; -+ unsigned intknqflsh:1; -+ unsigned hstfrm:1; -+ unsigned hsftrst:1; -+ unsigned csftrst:1; -+#else -+ -+ /* -+ * Core Soft Reset (CSftRst) (Device and Host) -+ * -+ * The application can flush the control logic in the -+ * entire core using this bit. This bit resets the -+ * pipelines in the AHB Clock domain as well as the -+ * PHY Clock domain. -+ * -+ * The state machines are reset to an IDLE state, the -+ * control bits in the CSRs are cleared, all the -+ * transmit FIFOs and the receive FIFO are flushed. -+ * -+ * The status mask bits that control the generation of -+ * the interrupt, are cleared, to clear the -+ * interrupt. The interrupt status bits are not -+ * cleared, so the application can get the status of -+ * any events that occurred in the core after it has -+ * set this bit. -+ * -+ * Any transactions on the AHB are terminated as soon -+ * as possible following the protocol. Any -+ * transactions on the USB are terminated immediately. -+ * -+ * The configuration settings in the CSRs are -+ * unchanged, so the software doesn't have to -+ * reprogram these registers (Device -+ * Configuration/Host Configuration/Core System -+ * Configuration/Core PHY Configuration). -+ * -+ * The application can write to this bit, any time it -+ * wants to reset the core. This is a self clearing -+ * bit and the core clears this bit after all the -+ * necessary logic is reset in the core, which may -+ * take several clocks, depending on the current state -+ * of the core. -+ */ -+ unsigned csftrst:1; -+ /* -+ * Hclk Soft Reset -+ * -+ * The application uses this bit to reset the control logic in -+ * the AHB clock domain. Only AHB clock domain pipelines are -+ * reset. -+ */ -+ unsigned hsftrst:1; -+ /* -+ * Host Frame Counter Reset (Host Only)
-+ * -+ * The application can reset the (micro)frame number -+ * counter inside the core, using this bit. When the -+ * (micro)frame counter is reset, the subsequent SOF -+ * sent out by the core, will have a (micro)frame -+ * number of 0. -+ */ -+ unsigned hstfrm:1; -+ /* -+ * In Token Sequence Learning Queue Flush -+ * (INTknQFlsh) (Device Only) -+ */ -+ unsigned intknqflsh:1; -+ /* -+ * RxFIFO Flush (RxFFlsh) (Device and Host) -+ * -+ * The application can flush the entire Receive FIFO -+ * using this bit.

The application must first -+ * ensure that the core is not in the middle of a -+ * transaction.

The application should write into -+ * this bit, only after making sure that neither the -+ * DMA engine is reading from the RxFIFO nor the MAC -+ * is writing the data in to the FIFO.

The -+ * application should wait until the bit is cleared -+ * before performing any other operations. This bit -+ * will takes 8 clocks (slowest of PHY or AHB clock) -+ * to clear. -+ */ -+ unsigned rxfflsh:1; -+ /* -+ * TxFIFO Flush (TxFFlsh) (Device and Host). -+ * -+ * This bit is used to selectively flush a single or -+ * all transmit FIFOs. The application must first -+ * ensure that the core is not in the middle of a -+ * transaction.

The application should write into -+ * this bit, only after making sure that neither the -+ * DMA engine is writing into the TxFIFO nor the MAC -+ * is reading the data out of the FIFO.

The -+ * application should wait until the core clears this -+ * bit, before performing any operations. This bit -+ * will takes 8 clocks (slowest of PHY or AHB clock) -+ * to clear. -+ */ -+ unsigned txfflsh:1; -+ -+ /* -+ * TxFIFO Number (TxFNum) (Device and Host). -+ * -+ * This is the FIFO number which needs to be flushed, -+ * using the TxFIFO Flush bit. This field should not -+ * be changed until the TxFIFO Flush bit is cleared by -+ * the core. -+ * - 0x0:Non Periodic TxFIFO Flush -+ * - 0x1:Periodic TxFIFO #1 Flush in device mode -+ * or Periodic TxFIFO in host mode -+ * - 0x2:Periodic TxFIFO #2 Flush in device mode. -+ * - ... -+ * - 0xF:Periodic TxFIFO #15 Flush in device mode -+ * - 0x10: Flush all the Transmit NonPeriodic and -+ * Transmit Periodic FIFOs in the core -+ */ -+ unsigned txfnum:5; -+ /* Reserved */ -+ unsigned reserved11_29:19; -+ /* -+ * DMA Request Signal. Indicated DMA request is in -+ * probress. Used for debug purpose. -+ */ -+ unsigned dmareq:1; -+ /* -+ * AHB Master Idle. Indicates the AHB Master State -+ * Machine is in IDLE condition. -+ */ -+ unsigned ahbidle:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields of the Core Interrupt Mask -+ * Register (GINTMSK). Set/clear the bits using the bit fields then -+ * write the d32 value to the register. -+ */ -+union gintmsk_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned wkupintr:1; -+ unsigned sessreqintr:1; -+ unsigned disconnect:1; -+ unsigned conidstschng:1; -+ unsigned reserved27:1; -+ unsigned ptxfempty:1; -+ unsigned hcintr:1; -+ unsigned portintr:1; -+ unsigned reserved22_23:2; -+ unsigned incomplisoout:1; -+ unsigned incomplisoin:1; -+ unsigned outepintr:1; -+ unsigned inepintr:1; -+ unsigned epmismatch:1; -+ unsigned reserved16:1; -+ unsigned eopframe:1; -+ unsigned isooutdrop:1; -+ unsigned enumdone:1; -+ unsigned usbreset:1; -+ unsigned usbsuspend:1; -+ unsigned erlysuspend:1; -+ unsigned i2cintr:1; -+ unsigned reserved8:1; -+ unsigned goutnakeff:1; -+ unsigned ginnakeff:1; -+ unsigned nptxfempty:1; -+ unsigned rxstsqlvl:1; -+ unsigned sofintr:1; -+ unsigned otgintr:1; -+ unsigned modemismatch:1; -+ unsigned reserved0:1; -+#else -+ unsigned reserved0:1; -+ unsigned modemismatch:1; -+ unsigned otgintr:1; -+ unsigned sofintr:1; -+ unsigned rxstsqlvl:1; -+ unsigned nptxfempty:1; -+ unsigned ginnakeff:1; -+ unsigned goutnakeff:1; -+ unsigned reserved8:1; -+ unsigned i2cintr:1; -+ unsigned erlysuspend:1; -+ unsigned usbsuspend:1; -+ unsigned usbreset:1; -+ unsigned enumdone:1; -+ unsigned isooutdrop:1; -+ unsigned eopframe:1; -+ unsigned reserved16:1; -+ unsigned epmismatch:1; -+ unsigned inepintr:1; -+ unsigned outepintr:1; -+ unsigned incomplisoin:1; -+ unsigned incomplisoout:1; -+ unsigned reserved22_23:2; -+ unsigned portintr:1; -+ unsigned hcintr:1; -+ unsigned ptxfempty:1; -+ unsigned reserved27:1; -+ unsigned conidstschng:1; -+ unsigned disconnect:1; -+ unsigned sessreqintr:1; -+ unsigned wkupintr:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields of the Core Interrupt Register -+ * (GINTSTS). Set/clear the bits using the bit fields then write the -+ * d32 value to the register. -+ */ -+union gintsts_data { -+ /* raw register data */ -+ uint32_t d32; -+#define DWC_SOF_INTR_MASK 0x0008 -+ -+ /* register bits */ -+ struct { -+#define DWC_HOST_MODE 1 -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned wkupintr:1; -+ unsigned sessreqintr:1; -+ unsigned disconnect:1; -+ unsigned conidstschng:1; -+ unsigned reserved27:1; -+ unsigned ptxfempty:1; -+ unsigned hcintr:1; -+ unsigned portintr:1; -+ unsigned reserved22_23:2; -+ unsigned incomplisoout:1; -+ unsigned incomplisoin:1; -+ unsigned outepintr:1; -+ unsigned inepint:1; -+ unsigned epmismatch:1; -+ unsigned intokenrx:1; -+ unsigned eopframe:1; -+ unsigned isooutdrop:1; -+ unsigned enumdone:1; -+ unsigned usbreset:1; -+ unsigned usbsuspend:1; -+ unsigned erlysuspend:1; -+ unsigned i2cintr:1; -+ unsigned reserved8:1; -+ unsigned goutnakeff:1; -+ unsigned ginnakeff:1; -+ unsigned nptxfempty:1; -+ unsigned rxstsqlvl:1; -+ unsigned sofintr:1; -+ unsigned otgintr:1; -+ unsigned modemismatch:1; -+ unsigned curmode:1; -+#else -+ unsigned curmode:1; -+ unsigned modemismatch:1; -+ unsigned otgintr:1; -+ unsigned sofintr:1; -+ unsigned rxstsqlvl:1; -+ unsigned nptxfempty:1; -+ unsigned ginnakeff:1; -+ unsigned goutnakeff:1; -+ unsigned reserved8:1; -+ unsigned i2cintr:1; -+ unsigned erlysuspend:1; -+ unsigned usbsuspend:1; -+ unsigned usbreset:1; -+ unsigned enumdone:1; -+ unsigned isooutdrop:1; -+ unsigned eopframe:1; -+ unsigned intokenrx:1; -+ unsigned epmismatch:1; -+ unsigned inepint:1; -+ unsigned outepintr:1; -+ unsigned incomplisoin:1; -+ unsigned incomplisoout:1; -+ unsigned reserved22_23:2; -+ unsigned portintr:1; -+ unsigned hcintr:1; -+ unsigned ptxfempty:1; -+ unsigned reserved27:1; -+ unsigned conidstschng:1; -+ unsigned disconnect:1; -+ unsigned sessreqintr:1; -+ unsigned wkupintr:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Device Receive Status Read and -+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 -+ * element then read out the bits using the bit elements. -+ */ -+union device_grxsts_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_DSTS_SETUP_UPDT 0x6 /* SETUP Packet */ -+#define DWC_DSTS_SETUP_COMP 0x4 /* Setup Phase Complete */ -+#define DWC_DSTS_GOUT_NAK 0x1 /* Global OUT NAK */ -+#define DWC_STS_XFER_COMP 0x3 /* OUT Data Transfer Complete */ -+#define DWC_STS_DATA_UPDT 0x2 /* OUT Data Packet */ -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:7; -+ unsigned fn:4; -+ unsigned pktsts:4; -+ unsigned dpid:2; -+ unsigned bcnt:11; -+ unsigned epnum:4; -+#else -+ unsigned epnum:4; -+ unsigned bcnt:11; -+ unsigned dpid:2; -+ unsigned pktsts:4; -+ unsigned fn:4; -+ unsigned reserved:7; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Host Receive Status Read and -+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 -+ * element then read out the bits using the bit elements. -+ */ -+union host_grxsts_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7 -+#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 -+#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3 -+#define DWC_GRXSTS_PKTSTS_IN 0x2 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:11; -+ unsigned pktsts:4; -+ unsigned dpid:2; -+ unsigned bcnt:11; -+ unsigned chnum:4; -+#else -+ unsigned chnum:4; -+ unsigned bcnt:11; -+ unsigned dpid:2; -+ unsigned pktsts:4; -+ unsigned reserved:11; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ, -+ * GNPTXFSIZ, DPTXFSIZn). Read the register into the d32 element then -+ * read out the bits using the bit elements. -+ */ -+union fifosize_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned depth:16; -+ unsigned startaddr:16; -+#else -+ unsigned startaddr:16; -+ unsigned depth:16; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Non-Periodic Transmit -+ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the -+ * d32 element then read out the bits using the bit -+ * elements. -+ */ -+union gnptxsts_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:1; -+ unsigned nptxqtop_chnep:4; -+ unsigned nptxqtop_token:2; -+ unsigned nptxqtop_terminate:1; -+ unsigned nptxqspcavail:8; -+ unsigned nptxfspcavail:16; -+#else -+ unsigned nptxfspcavail:16; -+ unsigned nptxqspcavail:8; -+ /* -+ * Top of the Non-Periodic Transmit Request Queue -+ * - bit 24 - Terminate (Last entry for the selected -+ * channel/EP) -+ * - bits 26:25 - Token Type -+ * - 2'b00 - IN/OUT -+ * - 2'b01 - Zero Length OUT -+ * - 2'b10 - PING/Complete Split -+ * - 2'b11 - Channel Halt -+ * - bits 30:27 - Channel/EP Number -+ */ -+ unsigned nptxqtop_terminate:1; -+ unsigned nptxqtop_token:2; -+ unsigned nptxqtop_chnep:4; -+ unsigned reserved:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the I2C Control Register -+ * (I2CCTL). Read the register into the d32 element then read out the -+ * bits using the bit elements. -+ */ -+union gi2cctl_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned bsydne:1; -+ unsigned rw:1; -+ unsigned reserved:2; -+ unsigned i2cdevaddr:2; -+ unsigned i2csuspctl:1; -+ unsigned ack:1; -+ unsigned i2cen:1; -+ unsigned addr:7; -+ unsigned regaddr:8; -+ unsigned rwdata:8; -+#else -+ unsigned rwdata:8; -+ unsigned regaddr:8; -+ unsigned addr:7; -+ unsigned i2cen:1; -+ unsigned ack:1; -+ unsigned i2csuspctl:1; -+ unsigned i2cdevaddr:2; -+ unsigned reserved:2; -+ unsigned rw:1; -+ unsigned bsydne:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the User HW Config1 -+ * Register. Read the register into the d32 element then read -+ * out the bits using the bit elements. -+ */ -+union hwcfg1_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned ep_dir15:2; -+ unsigned ep_dir14:2; -+ unsigned ep_dir13:2; -+ unsigned ep_dir12:2; -+ unsigned ep_dir11:2; -+ unsigned ep_dir10:2; -+ unsigned ep_dir9:2; -+ unsigned ep_dir8:2; -+ unsigned ep_dir7:2; -+ unsigned ep_dir6:2; -+ unsigned ep_dir5:2; -+ unsigned ep_dir4:2; -+ unsigned ep_dir3:2; -+ unsigned ep_dir2:2; -+ unsigned ep_dir1:2; -+ unsigned ep_dir0:2; -+#else -+ unsigned ep_dir0:2; -+ unsigned ep_dir1:2; -+ unsigned ep_dir2:2; -+ unsigned ep_dir3:2; -+ unsigned ep_dir4:2; -+ unsigned ep_dir5:2; -+ unsigned ep_dir6:2; -+ unsigned ep_dir7:2; -+ unsigned ep_dir8:2; -+ unsigned ep_dir9:2; -+ unsigned ep_dir10:2; -+ unsigned ep_dir11:2; -+ unsigned ep_dir12:2; -+ unsigned ep_dir13:2; -+ unsigned ep_dir14:2; -+ unsigned ep_dir15:2; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the User HW Config2 -+ * Register. Read the register into the d32 element then read -+ * out the bits using the bit elements. -+ */ -+union hwcfg2_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 -+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2 -+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1 -+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 -+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 -+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 -+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 -+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 -+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2 -+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1 -+#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved31:1; -+ unsigned dev_token_q_depth:5; -+ unsigned host_perio_tx_q_depth:2; -+ unsigned nonperio_tx_q_depth:2; -+ unsigned rx_status_q_depth:2; -+ unsigned dynamic_fifo:1; -+ unsigned perio_ep_supported:1; -+ unsigned num_host_chan:4; -+ unsigned num_dev_ep:4; -+ unsigned fs_phy_type:2; -+ unsigned hs_phy_type:2; -+ unsigned point2point:1; -+ unsigned architecture:2; -+ unsigned op_mode:3; -+#else -+ unsigned op_mode:3; -+ unsigned architecture:2; -+ unsigned point2point:1; -+ unsigned hs_phy_type:2; -+ unsigned fs_phy_type:2; -+ unsigned num_dev_ep:4; -+ unsigned num_host_chan:4; -+ unsigned perio_ep_supported:1; -+ unsigned dynamic_fifo:1; -+ unsigned rx_status_q_depth:2; -+ unsigned nonperio_tx_q_depth:2; -+ unsigned host_perio_tx_q_depth:2; -+ unsigned dev_token_q_depth:5; -+ unsigned reserved31:1; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the User HW Config3 -+ * Register. Read the register into the d32 element then read -+ * out the bits using the bit elements. -+ */ -+union hwcfg3_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+ /* GHWCFG3 */ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned dfifo_depth:16; -+ unsigned reserved15_13:3; -+ unsigned ahb_phy_clock_synch:1; -+ unsigned synch_reset_type:1; -+ unsigned optional_features:1; -+ unsigned vendor_ctrl_if:1; -+ unsigned i2c:1; -+ unsigned otg_func:1; -+ unsigned packet_size_cntr_width:3; -+ unsigned xfer_size_cntr_width:4; -+#else -+ unsigned xfer_size_cntr_width:4; -+ unsigned packet_size_cntr_width:3; -+ unsigned otg_func:1; -+ unsigned i2c:1; -+ unsigned vendor_ctrl_if:1; -+ unsigned optional_features:1; -+ unsigned synch_reset_type:1; -+ unsigned ahb_phy_clock_synch:1; -+ unsigned reserved15_13:3; -+ unsigned dfifo_depth:16; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the User HW Config4 -+ * Register. Read the register into the d32 element then read -+ * out the bits using the bit elements. -+ */ -+union hwcfg4_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved31_25:7; -+ unsigned session_end_filt_en:1; -+ unsigned b_valid_filt_en:1; -+ unsigned a_valid_filt_en:1; -+ unsigned vbus_valid_filt_en:1; -+ unsigned iddig_filt_en:1; -+ unsigned num_dev_mode_ctrl_ep:4; -+ unsigned utmi_phy_data_width:2; -+ unsigned min_ahb_freq:9; -+ unsigned power_optimiz:1; -+ unsigned num_dev_perio_in_ep:4; -+#else -+ unsigned num_dev_perio_in_ep:4; -+ unsigned power_optimiz:1; -+ unsigned min_ahb_freq:9; -+ unsigned utmi_phy_data_width:2; -+ unsigned num_dev_mode_ctrl_ep:4; -+ unsigned iddig_filt_en:1; -+ unsigned vbus_valid_filt_en:1; -+ unsigned a_valid_filt_en:1; -+ unsigned b_valid_filt_en:1; -+ unsigned session_end_filt_en:1; -+ unsigned reserved31_25:7; -+#endif -+ } b; -+}; -+ -+ -+/* -+ * Device Global Registers. Offsets 800h-BFFh -+ * -+ * The following structures define the size and relative field offsets -+ * for the Device Mode Registers. -+ * -+ * These registers are visible only in Device mode and must not be -+ * accessed in Host mode, as the results are unknown. -+ */ -+struct dwc_otg_dev_global_regs { -+ /* Device Configuration Register. Offset 800h */ -+ uint32_t dcfg; -+ /* Device Control Register. Offset: 804h */ -+ uint32_t dctl; -+ /* Device Status Register (Read Only). Offset: 808h */ -+ uint32_t dsts; -+ /* Reserved. Offset: 80Ch */ -+ uint32_t unused; -+ /* -+ * Device IN Endpoint Common Interrupt Mask Register. Offset: 810h -+ */ -+ uint32_t diepmsk; -+ /* -+ * Device OUT Endpoint Common Interrupt Mask -+ * Register. Offset: 814h -+ */ -+ uint32_t doepmsk; -+ /* -+ * Device All Endpoints Interrupt Register. Offset: 818h -+ */ -+ uint32_t daint; -+ /* -+ * Device All Endpoints Interrupt Mask Register. Offset: -+ * 81Ch -+ */ -+ uint32_t daintmsk; -+ /* -+ * Device IN Token Queue Read Register-1 (Read Only). -+ * Offset: 820h -+ */ -+ uint32_t dtknqr1; -+ /* -+ * Device IN Token Queue Read Register-2 (Read Only). -+ * Offset: 824h -+ */ -+ uint32_t dtknqr2; -+ /* -+ * Device VBUS discharge Register. Offset: 828h -+ */ -+ uint32_t dvbusdis; -+ /* -+ * Device VBUS Pulse Register. Offset: 82Ch -+ */ -+ uint32_t dvbuspulse; -+ /* -+ * Device IN Token Queue Read Register-3 (Read Only). -+ * Offset: 830h -+ */ -+ uint32_t dtknqr3; -+ /* -+ * Device IN Token Queue Read Register-4 (Read Only). -+ * Offset: 834h -+ */ -+ uint32_t dtknqr4; -+}; -+ -+/* -+ * This union represents the bit fields in the Device Configuration -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. Write the -+ * d32 member to the dcfg register. -+ */ -+union dcfg_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_DCFG_FRAME_INTERVAL_95 3 -+#define DWC_DCFG_FRAME_INTERVAL_90 2 -+#define DWC_DCFG_FRAME_INTERVAL_85 1 -+#define DWC_DCFG_FRAME_INTERVAL_80 0 -+#define DWC_DCFG_SEND_STALL 1 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved9:10; -+ unsigned epmscnt:4; -+ unsigned reserved13_17:5; -+ unsigned perfrint:2; -+ unsigned devaddr:7; -+ unsigned reserved3:1; -+ unsigned nzstsouthshk:1; -+ unsigned devspd:2; -+#else -+ -+ /* Device Speed */ -+ unsigned devspd:2; -+ /* Non Zero Length Status OUT Handshake */ -+ unsigned nzstsouthshk:1; -+ unsigned reserved3:1; -+ /* Device Addresses */ -+ unsigned devaddr:7; -+ /* Periodic Frame Interval */ -+ unsigned perfrint:2; -+ unsigned reserved13_17:5; -+ /* In Endpoint Mis-match count */ -+ unsigned epmscnt:4; -+ unsigned reserved9:10; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Device Control -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+union dctl_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:21; -+ unsigned cgoutnak:1; -+ unsigned sgoutnak:1; -+ unsigned cgnpinnak:1; -+ unsigned sgnpinnak:1; -+ unsigned tstctl:3; -+ unsigned goutnaksts:1; -+ unsigned gnpinnaksts:1; -+ unsigned sftdiscon:1; -+ unsigned rmtwkupsig:1; -+#else -+ -+ /* Remote Wakeup */ -+ unsigned rmtwkupsig:1; -+ /* Soft Disconnect */ -+ unsigned sftdiscon:1; -+ /* Global Non-Periodic IN NAK Status */ -+ unsigned gnpinnaksts:1; -+ /* Global OUT NAK Status */ -+ unsigned goutnaksts:1; -+ /* Test Control */ -+ unsigned tstctl:3; -+ /* Set Global Non-Periodic IN NAK */ -+ unsigned sgnpinnak:1; -+ /* Clear Global Non-Periodic IN NAK */ -+ unsigned cgnpinnak:1; -+ /* Set Global OUT NAK */ -+ unsigned sgoutnak:1; -+ /* Clear Global OUT NAK */ -+ unsigned cgoutnak:1; -+ -+ unsigned reserved:21; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Device Status -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+union dsts_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3 -+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2 -+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 -+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved22_31:10; -+ unsigned soffn:14; -+ unsigned reserved4_7:4; -+ unsigned errticerr:1; -+ unsigned enumspd:2; -+ unsigned suspsts:1; -+#else -+ -+ /* Suspend Status */ -+ unsigned suspsts:1; -+ /* Enumerated Speed */ -+ unsigned enumspd:2; -+ /* Erratic Error */ -+ unsigned errticerr:1; -+ unsigned reserved4_7:4; -+ /* Frame or Microframe Number of the received SOF */ -+ unsigned soffn:14; -+ unsigned reserved22_31:10; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Device IN EP Interrupt -+ * Register and the Device IN EP Common Mask Register. -+ * -+ * It also represents the bit fields in the Device IN EP Common -+ * Interrupt Mask Register. -+ -+ * - Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+union diepint_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved07_31:25; -+ unsigned inepnakeff:1; -+ unsigned intknepmis:1; -+ unsigned intktxfemp:1; -+ unsigned timeout:1; -+ unsigned ahberr:1; -+ unsigned epdisabled:1; -+ unsigned xfercompl:1; -+#else -+ -+y /* Transfer complete mask */ -+ unsigned xfercompl:1; -+ /* Endpoint disable mask */ -+ unsigned epdisabled:1; -+ /* AHB Error mask */ -+ unsigned ahberr:1; -+ /* TimeOUT Handshake mask (non-ISOC EPs) */ -+ unsigned timeout:1; -+ /* IN Token received with TxF Empty mask */ -+ unsigned intktxfemp:1; -+ /* IN Token Received with EP mismatch mask */ -+ unsigned intknepmis:1; -+ /* IN Endpoint HAK Effective mask */ -+ unsigned inepnakeff:1; -+ unsigned reserved07_31:25; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Device OUT EP Interrupt -+ * Registerand Device OUT EP Common Interrupt Mask Register. -+ * -+ * It also represents the bit fields in the Device OUT EP Common -+ * Interrupt Mask Register. -+ * -+ * - Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+union doepint_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved04_31:28; -+ unsigned setup:1; -+ unsigned ahberr:1; -+ unsigned epdisabled:1; -+ unsigned xfercompl:1; -+#else -+ -+ /* Transfer complete */ -+ unsigned xfercompl:1; -+ /* Endpoint disable */ -+ unsigned epdisabled:1; -+ /* AHB Error */ -+ unsigned ahberr:1; -+ /* Setup Phase Done (contorl EPs) */ -+ unsigned setup:1; -+ unsigned reserved04_31:28; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Device All EP Interrupt -+ * and Mask Registers. -+ * - Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+union daint_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned out:16; -+ unsigned in:16; -+#else -+ -+ /* IN Endpoint bits */ -+ unsigned in:16; -+ /* OUT Endpoint bits */ -+ unsigned out:16; -+#endif -+ } ep; -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned outep15:1; -+ unsigned outep14:1; -+ unsigned outep13:1; -+ unsigned outep12:1; -+ unsigned outep11:1; -+ unsigned outep10:1; -+ unsigned outep9:1; -+ unsigned outep8:1; -+ unsigned outep7:1; -+ unsigned outep6:1; -+ unsigned outep5:1; -+ unsigned outep4:1; -+ unsigned outep3:1; -+ unsigned outep2:1; -+ unsigned outep1:1; -+ unsigned outep0:1; -+ unsigned inep15:1; -+ unsigned inep14:1; -+ unsigned inep13:1; -+ unsigned inep12:1; -+ unsigned inep11:1; -+ unsigned inep10:1; -+ unsigned inep9:1; -+ unsigned inep8:1; -+ unsigned inep7:1; -+ unsigned inep6:1; -+ unsigned inep5:1; -+ unsigned inep4:1; -+ unsigned inep3:1; -+ unsigned inep2:1; -+ unsigned inep1:1; -+ unsigned inep0:1; -+#else -+ -+ /* IN Endpoint bits */ -+ unsigned inep0:1; -+ unsigned inep1:1; -+ unsigned inep2:1; -+ unsigned inep3:1; -+ unsigned inep4:1; -+ unsigned inep5:1; -+ unsigned inep6:1; -+ unsigned inep7:1; -+ unsigned inep8:1; -+ unsigned inep9:1; -+ unsigned inep10:1; -+ unsigned inep11:1; -+ unsigned inep12:1; -+ unsigned inep13:1; -+ unsigned inep14:1; -+ unsigned inep15:1; -+ /* OUT Endpoint bits */ -+ unsigned outep0:1; -+ unsigned outep1:1; -+ unsigned outep2:1; -+ unsigned outep3:1; -+ unsigned outep4:1; -+ unsigned outep5:1; -+ unsigned outep6:1; -+ unsigned outep7:1; -+ unsigned outep8:1; -+ unsigned outep9:1; -+ unsigned outep10:1; -+ unsigned outep11:1; -+ unsigned outep12:1; -+ unsigned outep13:1; -+ unsigned outep14:1; -+ unsigned outep15:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Device IN Token Queue -+ * Read Registers. -+ * - Read the register into the d32 member. -+ * - READ-ONLY Register -+ */ -+union dtknq1_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned epnums0_5:24; -+ unsigned wrap_bit:1; -+ unsigned reserved05_06:2; -+ unsigned intknwptr:5; -+#else -+ -+ /* In Token Queue Write Pointer */ -+ unsigned intknwptr:5; -+ /* Reserved */ -+ unsigned reserved05_06:2; -+ /* write pointer has wrapped. */ -+ unsigned wrap_bit:1; -+ /* EP Numbers of IN Tokens 0 ... 4 */ -+ unsigned epnums0_5:24; -+#endif -+ } b; -+}; -+ -+/* -+ * Device Logical IN Endpoint-Specific Registers. Offsets -+ * 900h-AFCh -+ * -+ * There will be one set of endpoint registers per logical endpoint -+ * implemented. -+ * -+ * These registers are visible only in Device mode and must not be -+ * accessed in Host mode, as the results are unknown. -+ */ -+struct dwc_otg_dev_in_ep_regs { -+ /* -+ * Device IN Endpoint Control Register. Offset:900h + -+ * (ep_num * 20h) + 00h -+ */ -+ uint32_t diepctl; -+ /* Reserved. Offset:900h + (ep_num * 20h) + 04h */ -+ uint32_t reserved04; -+ /* -+ * Device IN Endpoint Interrupt Register. Offset:900h + -+ * (ep_num * 20h) + 08h -+ */ -+ uint32_t diepint; -+ /* Reserved. Offset:900h + (ep_num * 20h) + 0Ch */ -+ uint32_t reserved0C; -+ /* -+ * Device IN Endpoint Transfer Size -+ * Register. Offset:900h + (ep_num * 20h) + 10h -+ */ -+ uint32_t dieptsiz; -+ /* -+ * Device IN Endpoint DMA Address Register. Offset:900h + -+ * (ep_num * 20h) + 14h -+ */ -+ uint32_t diepdma; -+ /* -+ * Reserved. Offset:900h + (ep_num * 20h) + 18h - 900h + -+ * (ep_num * 20h) + 1Ch -+ */ -+ uint32_t reserved18[2]; -+}; -+ -+/** -+ * Device Logical OUT Endpoint-Specific Registers. Offsets: -+ * B00h-CFCh -+ * -+ * There will be one set of endpoint registers per logical endpoint -+ * implemented. -+ * -+ * These registers are visible only in Device mode and must not be -+ * accessed in Host mode, as the results are unknown. -+ */ -+struct dwc_otg_dev_out_ep_regs { -+ /* -+ * Device OUT Endpoint Control Register. Offset:B00h + -+ * (ep_num * 20h) + 00h -+ */ -+ uint32_t doepctl; -+ /* -+ * Device OUT Endpoint Frame number Register. Offset: -+ * B00h + (ep_num * 20h) + 04h -+ */ -+ uint32_t doepfn; -+ /* -+ * Device OUT Endpoint Interrupt Register. Offset:B00h + -+ * (ep_num * 20h) + 08h -+ */ -+ uint32_t doepint; -+ /* -+ * Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */ -+ uint32_t reserved0C; -+ /* -+ * Device OUT Endpoint Transfer Size Register. Offset: -+ * B00h + (ep_num * 20h) + 10h -+ */ -+ uint32_t doeptsiz; -+ /* -+ * Device OUT Endpoint DMA Address Register. Offset:B00h -+ * + (ep_num * 20h) + 14h -+ */ -+ uint32_t doepdma; -+ /* -+ * Reserved. Offset:B00h + (ep_num * 20h) + 18h - B00h + -+ * (ep_num * 20h) + 1Ch -+ */ -+ uint32_t unused[2]; -+}; -+ -+/* -+ * This union represents the bit fields in the Device EP Control -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+union depctl_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#define DWC_DEP0CTL_MPS_64 0 -+#define DWC_DEP0CTL_MPS_32 1 -+#define DWC_DEP0CTL_MPS_16 2 -+#define DWC_DEP0CTL_MPS_8 3 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned mps:11; -+ unsigned epena:1; -+ unsigned epdis:1; -+ unsigned setd1pid:1; -+ unsigned setd0pid:1; -+ unsigned snak:1; -+ unsigned cnak:1; -+ unsigned txfnum:4; -+ unsigned stall:1; -+ unsigned snp:1; -+ unsigned eptype:2; -+ unsigned naksts:1; -+ unsigned dpid:1; -+ unsigned usbactep:1; -+ unsigned nextep:4; -+#else -+ -+ /* -+ * Maximum Packet Size -+ * IN/OUT EPn -+ * IN/OUT EP0 - 2 bits -+ * 2'b00: 64 Bytes -+ * 2'b01: 32 -+ * 2'b10: 16 -+ * 2'b11: 8 -+ */ -+ unsigned mps:11; -+ /* -+ * Next Endpoint -+ * IN EPn/IN EP0 -+ * OUT EPn/OUT EP0 - reserved -+ */ -+ unsigned nextep:4; -+ -+ /* USB Active Endpoint */ -+ unsigned usbactep:1; -+ -+ /* -+ * Endpoint DPID (INTR/Bulk IN and OUT endpoints) -+ * This field contains the PID of the packet going to -+ * be received or transmitted on this endpoint. The -+ * application should program the PID of the first -+ * packet going to be received or transmitted on this -+ * endpoint , after the endpoint is -+ * activated. Application use the SetD1PID and -+ * SetD0PID fields of this register to program either -+ * D0 or D1 PID. -+ * -+ * The encoding for this field is -+ * - 0: D0 -+ * - 1: D1 -+ */ -+ unsigned dpid:1; -+ -+ /* NAK Status */ -+ unsigned naksts:1; -+ -+ /* -+ * Endpoint Type -+ * 2'b00: Control -+ * 2'b01: Isochronous -+ * 2'b10: Bulk -+ * 2'b11: Interrupt -+ */ -+ unsigned eptype:2; -+ -+ /* -+ * Snoop Mode -+ * OUT EPn/OUT EP0 -+ * IN EPn/IN EP0 - reserved -+ */ -+ unsigned snp:1; -+ -+ /* Stall Handshake */ -+ unsigned stall:1; -+ -+ /* -+ * Tx Fifo Number -+ * IN EPn/IN EP0 -+ * OUT EPn/OUT EP0 - reserved -+ */ -+ unsigned txfnum:4; -+ -+ /* Clear NAK */ -+ unsigned cnak:1; -+ /* Set NAK */ -+ unsigned snak:1; -+ /* -+ * Set DATA0 PID (INTR/Bulk IN and OUT endpoints) -+ * Writing to this field sets the Endpoint DPID (DPID) -+ * field in this register to DATA0. Set Even -+ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) -+ * Writing to this field sets the Even/Odd -+ * (micro)frame (EO_FrNum) field to even (micro) -+ * frame. -+ */ -+ unsigned setd0pid:1; -+ /* -+ * Set DATA1 PID (INTR/Bulk IN and OUT endpoints) -+ * Writing to this field sets the Endpoint DPID (DPID) -+ * field in this register to DATA1 Set Odd -+ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) -+ * Writing to this field sets the Even/Odd -+ * (micro)frame (EO_FrNum) field to odd (micro) frame. -+ */ -+ unsigned setd1pid:1; -+ -+ /* Endpoint Disable */ -+ unsigned epdis:1; -+ /* Endpoint Enable */ -+ unsigned epena:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Device EP Transfer -+ * Size Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+union deptsiz_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:1; -+ unsigned mc:2; -+ unsigned pktcnt:10; -+ unsigned xfersize:19; -+#else -+ -+ /* Transfer size */ -+ unsigned xfersize:19; -+ /* Packet Count */ -+ unsigned pktcnt:10; -+ /* Multi Count - Periodic IN endpoints */ -+ unsigned mc:2; -+ unsigned reserved:1; -+#endif -+ } b; -+}; -+ -+/* -+ * This union represents the bit fields in the Device EP 0 Transfer -+ * Size Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+union deptsiz0_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved31:1; -+ unsigned supcnt:2; -+ unsigned reserved20_28:9; -+ unsigned pktcnt:1; -+ unsigned reserved7_18:12; -+ unsigned xfersize:7; -+#else -+ -+ /* Transfer size */ -+ unsigned xfersize:7; -+ /* Reserved */ -+ unsigned reserved7_18:12; -+ /* Packet Count */ -+ unsigned pktcnt:1; -+ /* Reserved */ -+ unsigned reserved20_28:9; -+ /* Setup Packet Count (DOEPTSIZ0 Only) */ -+ unsigned supcnt:2; -+ unsigned reserved31:1; -+#endif -+ } b; -+}; -+ -+/** Maximum number of Periodic FIFOs */ -+#define MAX_PERIO_FIFOS 15 -+ -+/** Maximum number of Endpoints/HostChannels */ -+#define MAX_EPS_CHANNELS 16 -+ -+/* -+ * The dwc_otg_dev_if structure contains information needed to manage -+ * the DWC_otg controller acting in device mode. It represents the -+ * programming view of the device-specific aspects of the controller. -+ */ -+struct dwc_otg_dev_if { -+ /* -+ * Pointer to device Global registers. -+ * Device Global Registers starting at offset 800h -+ */ -+ struct dwc_otg_dev_global_regs *dev_global_regs; -+#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 -+ -+ /* -+ * Device Logical IN Endpoint-Specific Registers 900h-AFCh -+ */ -+ struct dwc_otg_dev_in_ep_regs *in_ep_regs[MAX_EPS_CHANNELS]; -+#define DWC_DEV_IN_EP_REG_OFFSET 0x900 -+#define DWC_EP_REG_OFFSET 0x20 -+ -+ /* Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ -+ struct dwc_otg_dev_out_ep_regs *out_ep_regs[MAX_EPS_CHANNELS]; -+#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00 -+ -+ /* Device configuration information */ -+ uint8_t speed; /* Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ -+ uint8_t num_eps; /* Number of EPs range: 1-16 (includes EP0) */ -+ uint8_t num_perio_eps; /* # of Periodic EP range: 0-15 */ -+ -+ /* Size of periodic FIFOs (Bytes) */ -+ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; -+ -+}; -+ -+ -+/* Host Mode Register Structures */ -+ -+/* -+ * The Host Global Registers structure defines the size and relative -+ * field offsets for the Host Mode Global Registers. Host Global -+ * Registers offsets 400h-7FFh. -+ */ -+struct dwc_otg_host_global_regs { -+ /* Host Configuration Register. Offset: 400h */ -+ uint32_t hcfg; -+ /* Host Frame Interval Register. Offset: 404h */ -+ uint32_t hfir; -+ /* Host Frame Number / Frame Remaining Register. Offset: 408h */ -+ uint32_t hfnum; -+ /* Reserved. Offset: 40Ch */ -+ uint32_t reserved40C; -+ /* Host Periodic Transmit FIFO/ Queue Status Register. Offset: 410h */ -+ uint32_t hptxsts; -+ /* Host All Channels Interrupt Register. Offset: 414h */ -+ uint32_t haint; -+ /* Host All Channels Interrupt Mask Register. Offset: 418h */ -+ uint32_t haintmsk; -+}; -+ -+/* -+ * This union represents the bit fields in the Host Configuration Register. -+ * Read the register into the d32 member then set/clear the bits using -+ * the bit elements. Write the d32 member to the hcfg register. -+ */ -+union hcfg_data { -+ /** raw register data */ -+ uint32_t d32; -+ -+ /** register bits */ -+ struct { -+#define DWC_HCFG_6_MHZ 2 -+#define DWC_HCFG_48_MHZ 1 -+#define DWC_HCFG_30_60_MHZ 0 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:29; -+ unsigned fslssupp:1; -+ unsigned fslspclksel:2; -+#else -+ -+ /* FS/LS Phy Clock Select */ -+ unsigned fslspclksel:2; -+ /* FS/LS Only Support */ -+ unsigned fslssupp:1; -+ unsigned reserved:29; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host Frame Remaing/Number -+ * Register. -+ */ -+union hfir_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:16; -+ unsigned frint:16; -+#else -+ unsigned frint:16; -+ unsigned reserved:16; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host Frame Remaing/Number -+ * Register. -+ */ -+union hfnum_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /* register bits */ -+ struct { -+#define DWC_HFNUM_MAX_FRNUM 0x3FFF -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned frrem:16; -+ unsigned frnum:16; -+#else -+ unsigned frnum:16; -+ unsigned frrem:16; -+#endif -+ } b; -+}; -+ -+union hptxsts_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned ptxqtop_odd:1; -+ unsigned ptxqtop_chnum:4; -+ unsigned ptxqtop_token:2; -+ unsigned ptxqtop_terminate:1; -+ unsigned ptxqspcavail:8; -+ unsigned ptxfspcavail:16; -+#else -+ unsigned ptxfspcavail:16; -+ unsigned ptxqspcavail:8; -+ /* -+ * Top of the Periodic Transmit Request Queue -+ * - bit 24 - Terminate (last entry for the selected channel) -+ * - bits 26:25 - Token Type -+ * - 2'b00 - Zero length -+ * - 2'b01 - Ping -+ * - 2'b10 - Disable -+ * - bits 30:27 - Channel Number -+ * - bit 31 - Odd/even microframe -+ */ -+ unsigned ptxqtop_terminate:1; -+ unsigned ptxqtop_token:2; -+ unsigned ptxqtop_chnum:4; -+ unsigned ptxqtop_odd:1; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host Port Control and Status -+ * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. Write the d32 member to the -+ * hprt0 register. -+ */ -+union hprt0_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+#define DWC_HPRT0_PRTSPD_LOW_SPEED 2 -+#define DWC_HPRT0_PRTSPD_FULL_SPEED 1 -+#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved19_31:13; -+ unsigned prtspd:2; -+ unsigned prttstctl:4; -+ unsigned prtpwr:1; -+ unsigned prtlnsts:2; -+ unsigned reserved9:1; -+ unsigned prtrst:1; -+ unsigned prtsusp:1; -+ unsigned prtres:1; -+ unsigned prtovrcurrchng:1; -+ unsigned prtovrcurract:1; -+ unsigned prtenchng:1; -+ unsigned prtena:1; -+ unsigned prtconndet:1; -+ unsigned prtconnsts:1; -+#else -+ unsigned prtconnsts:1; -+ unsigned prtconndet:1; -+ unsigned prtena:1; -+ unsigned prtenchng:1; -+ unsigned prtovrcurract:1; -+ unsigned prtovrcurrchng:1; -+ unsigned prtres:1; -+ unsigned prtsusp:1; -+ unsigned prtrst:1; -+ unsigned reserved9:1; -+ unsigned prtlnsts:2; -+ unsigned prtpwr:1; -+ unsigned prttstctl:4; -+ unsigned prtspd:2; -+ unsigned reserved19_31:13; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. -+ */ -+union haint_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:16; -+ unsigned ch15:1; -+ unsigned ch14:1; -+ unsigned ch13:1; -+ unsigned ch12:1; -+ unsigned ch11:1; -+ unsigned ch10:1; -+ unsigned ch9:1; -+ unsigned ch8:1; -+ unsigned ch7:1; -+ unsigned ch6:1; -+ unsigned ch5:1; -+ unsigned ch4:1; -+ unsigned ch3:1; -+ unsigned ch2:1; -+ unsigned ch1:1; -+ unsigned ch0:1; -+#else -+ unsigned ch0:1; -+ unsigned ch1:1; -+ unsigned ch2:1; -+ unsigned ch3:1; -+ unsigned ch4:1; -+ unsigned ch5:1; -+ unsigned ch6:1; -+ unsigned ch7:1; -+ unsigned ch8:1; -+ unsigned ch9:1; -+ unsigned ch10:1; -+ unsigned ch11:1; -+ unsigned ch12:1; -+ unsigned ch13:1; -+ unsigned ch14:1; -+ unsigned ch15:1; -+ unsigned reserved:16; -+#endif -+ } b; -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:16; -+ unsigned chint:16; -+#else -+ unsigned chint:16; -+ unsigned reserved:16; -+#endif -+ } b2; -+}; -+ -+/** -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. -+ */ -+union haintmsk_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:16; -+ unsigned ch15:1; -+ unsigned ch14:1; -+ unsigned ch13:1; -+ unsigned ch12:1; -+ unsigned ch11:1; -+ unsigned ch10:1; -+ unsigned ch9:1; -+ unsigned ch8:1; -+ unsigned ch7:1; -+ unsigned ch6:1; -+ unsigned ch5:1; -+ unsigned ch4:1; -+ unsigned ch3:1; -+ unsigned ch2:1; -+ unsigned ch1:1; -+ unsigned ch0:1; -+#else -+ unsigned ch0:1; -+ unsigned ch1:1; -+ unsigned ch2:1; -+ unsigned ch3:1; -+ unsigned ch4:1; -+ unsigned ch5:1; -+ unsigned ch6:1; -+ unsigned ch7:1; -+ unsigned ch8:1; -+ unsigned ch9:1; -+ unsigned ch10:1; -+ unsigned ch11:1; -+ unsigned ch12:1; -+ unsigned ch13:1; -+ unsigned ch14:1; -+ unsigned ch15:1; -+ unsigned reserved:16; -+#endif -+ } b; -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:16; -+ unsigned chint:16; -+#else -+ unsigned chint:16; -+ unsigned reserved:16; -+#endif -+ } b2; -+}; -+ -+/* -+ * Host Channel Specific Registers. 500h-5FCh -+ */ -+struct dwc_otg_hc_regs { -+ /* -+ * Host Channel 0 Characteristic Register. -+ * Offset: 500h + (chan_num * 20h) + 00h -+ */ -+ uint32_t hcchar; -+ /* -+ * Host Channel 0 Split Control Register. -+ * Offset: 500h + (chan_num * 20h) + 04h -+ */ -+ uint32_t hcsplt; -+ /* -+ * Host Channel 0 Interrupt Register. -+ * Offset: 500h + (chan_num * 20h) + 08h -+ */ -+ uint32_t hcint; -+ /* -+ * Host Channel 0 Interrupt Mask Register. -+ * Offset: 500h + (chan_num * 20h) + 0Ch -+ */ -+ uint32_t hcintmsk; -+ /* -+ * Host Channel 0 Transfer Size Register. -+ * Offset: 500h + (chan_num * 20h) + 10h -+ */ -+ uint32_t hctsiz; -+ /* -+ * Host Channel 0 DMA Address Register. -+ * Offset: 500h + (chan_num * 20h) + 14h -+ */ -+ uint32_t hcdma; -+ /* -+ * Reserved. -+ * Offset: 500h + (chan_num * 20h) + 18h - -+ * 500h + (chan_num * 20h) + 1Ch -+ */ -+ uint32_t reserved[2]; -+}; -+ -+/** -+ * This union represents the bit fields in the Host Channel Characteristics -+ * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. Write the d32 member to the -+ * hcchar register. -+ */ -+union hcchar_data { -+ /** raw register data */ -+ uint32_t d32; -+ -+ /** register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned chen:1; -+ unsigned chdis:1; -+ unsigned oddfrm:1; -+ unsigned devaddr:7; -+ unsigned multicnt:2; -+ unsigned eptype:2; -+ unsigned lspddev:1; -+ unsigned reserved:1; -+ unsigned epdir:1; -+ unsigned epnum:4; -+ unsigned mps:11; -+#else -+ -+ /* Maximum packet size in bytes */ -+ unsigned mps:11; -+ -+ /* Endpoint number */ -+ unsigned epnum:4; -+ -+ /* 0: OUT, 1: IN */ -+ unsigned epdir:1; -+ -+ unsigned reserved:1; -+ -+ /* 0: Full/high speed device, 1: Low speed device */ -+ unsigned lspddev:1; -+ -+ /* 0: Control, 1: Isoc, 2: Bulk, 3: Intr */ -+ unsigned eptype:2; -+ -+ /* Packets per frame for periodic transfers. 0 is reserved. */ -+ unsigned multicnt:2; -+ -+ /* Device address */ -+ unsigned devaddr:7; -+ -+ /* -+ * Frame to transmit periodic transaction. -+ * 0: even, 1: odd -+ */ -+ unsigned oddfrm:1; -+ -+ /* Channel disable */ -+ unsigned chdis:1; -+ -+ /* Channel enable */ -+ unsigned chen:1; -+#endif -+ } b; -+}; -+ -+union hcsplt_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /* register bits */ -+ struct { -+#define DWC_HCSPLIT_XACTPOS_ALL 3 -+#define DWC_HCSPLIT_XACTPOS_BEGIN 2 -+#define DWC_HCSPLIT_XACTPOS_END 1 -+#define DWC_HCSPLIT_XACTPOS_MID 0 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned spltena:1; -+ unsigned reserved:14; -+ unsigned compsplt:1; -+ unsigned xactpos:2; -+ unsigned hubaddr:7; -+ unsigned prtaddr:7; -+#else -+ -+ /* Port Address */ -+ unsigned prtaddr:7; -+ -+ /* Hub Address */ -+ unsigned hubaddr:7; -+ -+ /* Transaction Position */ -+ unsigned xactpos:2; -+ -+ /* Do Complete Split */ -+ unsigned compsplt:1; -+ -+ /* Reserved */ -+ unsigned reserved:14; -+ -+ /* Split Enble */ -+ unsigned spltena:1; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. -+ */ -+union hcint_data { -+ /* raw register data */ -+ uint32_t d32; -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:21; -+ unsigned datatglerr:1; -+ unsigned frmovrun:1; -+ unsigned bblerr:1; -+ unsigned xacterr:1; -+ unsigned nyet:1; -+ unsigned ack:1; -+ unsigned nak:1; -+ unsigned stall:1; -+ unsigned ahberr:1; -+ unsigned chhltd:1; -+ unsigned xfercomp:1; -+#else -+ -+ /* Transfer Complete */ -+ unsigned xfercomp:1; -+ /* Channel Halted */ -+ unsigned chhltd:1; -+ /* AHB Error */ -+ unsigned ahberr:1; -+ /* STALL Response Received */ -+ unsigned stall:1; -+ /* NAK Response Received */ -+ unsigned nak:1; -+ /* ACK Response Received */ -+ unsigned ack:1; -+ /* NYET Response Received */ -+ unsigned nyet:1; -+ /* Transaction Err */ -+ unsigned xacterr:1; -+ /* Babble Error */ -+ unsigned bblerr:1; -+ /* Frame Overrun */ -+ unsigned frmovrun:1; -+ /* Data Toggle Error */ -+ unsigned datatglerr:1; -+ /* Reserved */ -+ unsigned reserved:21; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host Channel Transfer Size -+ * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. Write the d32 member to the -+ * hcchar register. -+ */ -+union hctsiz_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /* register bits */ -+ struct { -+#define DWC_HCTSIZ_SETUP 3 -+#define DWC_HCTSIZ_MDATA 3 -+#define DWC_HCTSIZ_DATA2 1 -+#define DWC_HCTSIZ_DATA1 2 -+#define DWC_HCTSIZ_DATA0 0 -+ -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned dopng:1; -+ unsigned pid:2; -+ unsigned pktcnt:10; -+ unsigned xfersize:19; -+#else -+ -+ /* Total transfer size in bytes */ -+ unsigned xfersize:19; -+ -+ /* Data packets to transfer */ -+ unsigned pktcnt:10; -+ -+ /* -+ * Packet ID for next data packet -+ * 0: DATA0 -+ * 1: DATA2 -+ * 2: DATA1 -+ * 3: MDATA (non-Control), SETUP (Control) -+ */ -+ unsigned pid:2; -+ -+ /* Do PING protocol when 1 */ -+ unsigned dopng:1; -+#endif -+ } b; -+}; -+ -+/** -+ * This union represents the bit fields in the Host Channel Interrupt Mask -+ * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. Write the d32 member to the -+ * hcintmsk register. -+ */ -+union hcintmsk_data { -+ /** raw register data */ -+ uint32_t d32; -+ -+ /** register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:21; -+ unsigned datatglerr:1; -+ unsigned frmovrun:1; -+ unsigned bblerr:1; -+ unsigned xacterr:1; -+ unsigned nyet:1; -+ unsigned ack:1; -+ unsigned nak:1; -+ unsigned stall:1; -+ unsigned ahberr:1; -+ unsigned chhltd:1; -+ unsigned xfercompl:1; -+#else -+ unsigned xfercompl:1; -+ unsigned chhltd:1; -+ unsigned ahberr:1; -+ unsigned stall:1; -+ unsigned nak:1; -+ unsigned ack:1; -+ unsigned nyet:1; -+ unsigned xacterr:1; -+ unsigned bblerr:1; -+ unsigned frmovrun:1; -+ unsigned datatglerr:1; -+ unsigned reserved:21; -+#endif -+ } b; -+}; -+ -+/** OTG Host Interface Structure. -+ * -+ * The OTG Host Interface Structure structure contains information -+ * needed to manage the DWC_otg controller acting in host mode. It -+ * represents the programming view of the host-specific aspects of the -+ * controller. -+ */ -+struct dwc_otg_host_if { -+ /* Host Global Registers starting at offset 400h.*/ -+ struct dwc_otg_host_global_regs *host_global_regs; -+#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400 -+ -+ /* Host Port 0 Control and Status Register */ -+ uint32_t *hprt0; -+#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440 -+ -+ /* Host Channel Specific Registers at offsets 500h-5FCh. */ -+ struct dwc_otg_hc_regs *hc_regs[MAX_EPS_CHANNELS]; -+#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500 -+#define DWC_OTG_CHAN_REGS_OFFSET 0x20 -+ -+ /* Host configuration information */ -+ /* Number of Host Channels (range: 1-16) */ -+ uint8_t num_host_channels; -+ /* Periodic EPs supported (0: no, 1: yes) */ -+ uint8_t perio_eps_supported; -+ /* Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */ -+ uint16_t perio_tx_fifo_size; -+ -+}; -+ -+/** -+ * This union represents the bit fields in the Power and Clock Gating Control -+ * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+union pcgcctl_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /* register bits */ -+ struct { -+#ifdef __BIG_ENDIAN_BITFIELD -+ unsigned reserved:27; -+ unsigned physuspended:1; -+ unsigned rstpdwnmodule:1; -+ unsigned pwrclmp:1; -+ unsigned gatehclk:1; -+ unsigned stoppclk:1; -+#else -+ -+ /* Stop Pclk */ -+ unsigned stoppclk:1; -+ /* Gate Hclk */ -+ unsigned gatehclk:1; -+ /* Power Clamp */ -+ unsigned pwrclmp:1; -+ /* Reset Power Down Modules */ -+ unsigned rstpdwnmodule:1; -+ /* PHY Suspended */ -+ unsigned physuspended:1; -+ -+ unsigned reserved:27; -+#endif -+ } b; -+}; -+ -+#endif --- -1.6.0.6 - diff --git a/target/linux/octeon/patches/100-wndap330_hacks.patch b/target/linux/octeon/patches/100-wndap330_hacks.patch deleted file mode 100644 index c4ca4217c0..0000000000 --- a/target/linux/octeon/patches/100-wndap330_hacks.patch +++ /dev/null @@ -1,77 +0,0 @@ ---- a/drivers/staging/octeon/cvmx-helper-board.c -+++ b/drivers/staging/octeon/cvmx-helper-board.c -@@ -90,7 +90,7 @@ int cvmx_helper_board_get_mii_address(in - case CVMX_BOARD_TYPE_KODAMA: - case CVMX_BOARD_TYPE_EBH3100: - case CVMX_BOARD_TYPE_HIKARI: -- case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ //case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ - case CVMX_BOARD_TYPE_CN3005_EVB_HS5: - case CVMX_BOARD_TYPE_CN3020_EVB_HS5: - /* -@@ -103,6 +103,12 @@ int cvmx_helper_board_get_mii_address(in - return 9; - else - return -1; -+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ -+ /* We have only one port, using GMII */ -+ if (ipd_port == 0) -+ return 9; -+ else -+ return -1; - case CVMX_BOARD_TYPE_NAC38: - /* Board has 8 RGMII ports PHYs are 0-7 */ - if ((ipd_port >= 0) && (ipd_port < 4)) -@@ -205,7 +211,7 @@ cvmx_helper_link_info_t __cvmx_helper_bo - result.s.speed = 1000; - return result; - case CVMX_BOARD_TYPE_EBH3100: -- case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ //case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ - case CVMX_BOARD_TYPE_CN3005_EVB_HS5: - case CVMX_BOARD_TYPE_CN3020_EVB_HS5: - /* Port 1 on these boards is always Gigabit */ -@@ -217,6 +223,9 @@ cvmx_helper_link_info_t __cvmx_helper_bo - } - /* Fall through to the generic code below */ - break; -+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: /* hack for the WNDAP330 */ -+ is_broadcom_phy = 1; -+ break; - case CVMX_BOARD_TYPE_CUST_NB5: - /* Port 1 on these boards is always Gigabit */ - if (ipd_port == 1) { ---- a/drivers/staging/octeon/cvmx-helper-rgmii.c -+++ b/drivers/staging/octeon/cvmx-helper-rgmii.c -@@ -66,13 +66,15 @@ int __cvmx_helper_rgmii_probe(int interf - cvmx_dprintf("ERROR: RGMII initialize called in " - "SPI interface\n"); - } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) -- || OCTEON_IS_MODEL(OCTEON_CN30XX) -+ //|| OCTEON_IS_MODEL(OCTEON_CN30XX) - || OCTEON_IS_MODEL(OCTEON_CN50XX)) { - /* - * On these chips "type" says we're in - * GMII/MII mode. This limits us to 2 ports - */ - num_ports = 2; -+ } else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) { -+ num_ports = 1; - } else { - cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", - __func__); ---- a/arch/mips/cavium-octeon/pci.c -+++ b/arch/mips/cavium-octeon/pci.c -@@ -95,9 +95,11 @@ const char *octeon_get_pci_interrupts(vo - case CVMX_BOARD_TYPE_EBH3000: - return ""; - case CVMX_BOARD_TYPE_EBH3100: -- case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ //case CVMX_BOARD_TYPE_CN3010_EVB_HS5: - case CVMX_BOARD_TYPE_CN3005_EVB_HS5: - return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; -+ case CVMX_BOARD_TYPE_CN3010_EVB_HS5: -+ return "AAAAAAAAAAAAAABAAAAAAAAAAAAAAABA"; - case CVMX_BOARD_TYPE_BBGW_REF: - return "AABCD"; - default: diff --git a/target/linux/octeon/patches/105-nb5_fixup.patch b/target/linux/octeon/patches/105-nb5_fixup.patch deleted file mode 100644 index 2165eb0a1b..0000000000 --- a/target/linux/octeon/patches/105-nb5_fixup.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/arch/mips/cavium-octeon/pci.c -+++ b/arch/mips/cavium-octeon/pci.c -@@ -102,6 +102,8 @@ const char *octeon_get_pci_interrupts(vo - return "AAAAAAAAAAAAAABAAAAAAAAAAAAAAABA"; - case CVMX_BOARD_TYPE_BBGW_REF: - return "AABCD"; -+ case CVMX_BOARD_TYPE_CUST_NB5: -+ return "ABDABAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - default: - return ""; - } ---- a/drivers/staging/octeon/cvmx-helper-board.c -+++ b/drivers/staging/octeon/cvmx-helper-board.c -@@ -699,6 +699,7 @@ cvmx_helper_board_usb_clock_types_t __cv - { - switch (cvmx_sysinfo_get()->board_type) { - case CVMX_BOARD_TYPE_BBGW_REF: -+ case CVMX_BOARD_TYPE_CUST_NB5: - return USB_CLOCK_TYPE_CRYSTAL_12; - } - return USB_CLOCK_TYPE_REF_48; diff --git a/target/linux/octeon/patches/106-no_module_reloc.patch b/target/linux/octeon/patches/106-no_module_reloc.patch deleted file mode 100644 index 449bda7567..0000000000 --- a/target/linux/octeon/patches/106-no_module_reloc.patch +++ /dev/null @@ -1,372 +0,0 @@ -diff -urN linux-2.6.30.10/arch/mips/Makefile linux-2.6.30.10.new//arch/mips/Makefile ---- linux-2.6.30.10/arch/mips/Makefile 2010-01-29 16:12:01.000000000 +0100 -+++ linux-2.6.30.10.new//arch/mips/Makefile 2009-12-04 07:00:07.000000000 +0100 -@@ -83,7 +83,7 @@ - cflags-y += -G 0 -mno-abicalls -fno-pic -pipe - cflags-y += -msoft-float - LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --MODFLAGS += -mno-long-calls -+MODFLAGS += -mlong-calls - - cflags-y += -ffreestanding - -diff -urN linux-2.6.30.10/arch/mips/include/asm/module.h linux-2.6.30.10.new//arch/mips/include/asm/module.h ---- linux-2.6.30.10/arch/mips/include/asm/module.h 2010-01-29 16:12:01.000000000 +0100 -+++ linux-2.6.30.10.new//arch/mips/include/asm/module.h 2009-12-04 07:00:07.000000000 +0100 -@@ -9,11 +9,6 @@ - struct list_head dbe_list; - const struct exception_table_entry *dbe_start; - const struct exception_table_entry *dbe_end; -- -- void *phys_plt_tbl; -- void *virt_plt_tbl; -- unsigned int phys_plt_offset; -- unsigned int virt_plt_offset; - }; - - typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ -diff -urN linux-2.6.30.10/arch/mips/kernel/module.c linux-2.6.30.10.new//arch/mips/kernel/module.c ---- linux-2.6.30.10/arch/mips/kernel/module.c 2010-01-29 16:12:01.000000000 +0100 -+++ linux-2.6.30.10.new//arch/mips/kernel/module.c 2009-12-04 07:00:07.000000000 +0100 -@@ -43,116 +43,6 @@ - static LIST_HEAD(dbe_list); - static DEFINE_SPINLOCK(dbe_lock); - --/* -- * Get the potential max trampolines size required of the init and -- * non-init sections. Only used if we cannot find enough contiguous -- * physically mapped memory to put the module into. -- */ --static unsigned int --get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, -- const char *secstrings, unsigned int symindex, bool is_init) --{ -- unsigned long ret = 0; -- unsigned int i, j; -- Elf_Sym *syms; -- -- /* Everything marked ALLOC (this includes the exported symbols) */ -- for (i = 1; i < hdr->e_shnum; ++i) { -- unsigned int info = sechdrs[i].sh_info; -- -- if (sechdrs[i].sh_type != SHT_REL -- && sechdrs[i].sh_type != SHT_RELA) -- continue; -- -- /* Not a valid relocation section? */ -- if (info >= hdr->e_shnum) -- continue; -- -- /* Don't bother with non-allocated sections */ -- if (!(sechdrs[info].sh_flags & SHF_ALLOC)) -- continue; -- -- /* If it's called *.init*, and we're not init, we're -- not interested */ -- if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) -- != is_init) -- continue; -- -- syms = (Elf_Sym *) sechdrs[symindex].sh_addr; -- if (sechdrs[i].sh_type == SHT_REL) { -- Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; -- unsigned int size = sechdrs[i].sh_size / sizeof(*rel); -- -- for (j = 0; j < size; ++j) { -- Elf_Sym *sym; -- -- if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) -- continue; -- -- sym = syms + ELF_MIPS_R_SYM(rel[j]); -- if (!is_init && sym->st_shndx != SHN_UNDEF) -- continue; -- -- ret += 4 * sizeof(int); -- } -- } else { -- Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; -- unsigned int size = sechdrs[i].sh_size / sizeof(*rela); -- -- for (j = 0; j < size; ++j) { -- Elf_Sym *sym; -- -- if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) -- continue; -- -- sym = syms + ELF_MIPS_R_SYM(rela[j]); -- if (!is_init && sym->st_shndx != SHN_UNDEF) -- continue; -- -- ret += 4 * sizeof(int); -- } -- } -- } -- -- return ret; --} -- --#ifndef MODULE_START --static void *alloc_phys(unsigned long size) --{ -- unsigned order; -- struct page *page; -- struct page *p; -- -- size = PAGE_ALIGN(size); -- order = get_order(size); -- -- page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | -- __GFP_THISNODE, order); -- if (!page) -- return NULL; -- -- split_page(page, order); -- -- for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) -- __free_page(p); -- -- return page_address(page); --} --#endif -- --static void free_phys(void *ptr, unsigned long size) --{ -- struct page *page; -- struct page *end; -- -- page = virt_to_page(ptr); -- end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT); -- -- for (; page < end; ++page) -- __free_page(page); --} -- - void *module_alloc(unsigned long size) - { - #ifdef MODULE_START -@@ -168,101 +58,23 @@ - - return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); - #else -- void *ptr; -- - if (size == 0) - return NULL; -- -- ptr = alloc_phys(size); -- -- /* If we failed to allocate physically contiguous memory, -- * fall back to regular vmalloc. The module loader code will -- * create jump tables to handle long jumps */ -- if (!ptr) -- return vmalloc(size); -- -- return ptr; --#endif --} -- --static inline bool is_phys_addr(void *ptr) --{ --#ifdef CONFIG_64BIT -- return (KSEGX((unsigned long)ptr) == CKSEG0); --#else -- return (KSEGX(ptr) == KSEG0); -+ return vmalloc(size); - #endif - } - - /* Free memory returned from module_alloc */ - void module_free(struct module *mod, void *module_region) - { -- if (is_phys_addr(module_region)) { -- if (mod->module_init == module_region) -- free_phys(module_region, mod->init_size); -- else if (mod->module_core == module_region) -- free_phys(module_region, mod->core_size); -- else -- BUG(); -- } else { -- vfree(module_region); -- } -+ vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ - } - --static void *__module_alloc(int size, bool phys) --{ -- void *ptr; -- -- if (phys) -- ptr = kmalloc(size, GFP_KERNEL); -- else -- ptr = vmalloc(size); -- return ptr; --} -- --static void __module_free(void *ptr) --{ -- if (is_phys_addr(ptr)) -- kfree(ptr); -- else -- vfree(ptr); --} -- - int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, - char *secstrings, struct module *mod) - { -- unsigned int symindex = 0; -- unsigned int core_size, init_size; -- int i; -- -- for (i = 1; i < hdr->e_shnum; i++) -- if (sechdrs[i].sh_type == SHT_SYMTAB) -- symindex = i; -- -- core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); -- init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); -- -- mod->arch.phys_plt_offset = 0; -- mod->arch.virt_plt_offset = 0; -- mod->arch.phys_plt_tbl = NULL; -- mod->arch.virt_plt_tbl = NULL; -- -- if ((core_size + init_size) == 0) -- return 0; -- -- mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); -- if (!mod->arch.phys_plt_tbl) -- return -ENOMEM; -- -- mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); -- if (!mod->arch.virt_plt_tbl) { -- __module_free(mod->arch.phys_plt_tbl); -- mod->arch.phys_plt_tbl = NULL; -- return -ENOMEM; -- } -- - return 0; - } - -@@ -285,37 +97,27 @@ - return 0; - } - --static Elf_Addr add_plt_entry_to(unsigned *plt_offset, -- void *start, Elf_Addr v) -+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) - { -- unsigned *tramp = start + *plt_offset; -- -- *plt_offset += 4 * sizeof(int); -- -- /* adjust carry for addiu */ -- if (v & 0x00008000) -- v += 0x10000; -- -- tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ -- tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ -- tramp[2] = 0x03200008; /* jr t9 */ -- tramp[3] = 0x00000000; /* nop */ -+ if (v % 4) { -+ printk(KERN_ERR "module %s: dangerous relocation\n", me->name); -+ return -ENOEXEC; -+ } - -- return (Elf_Addr) tramp; --} -+ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { -+ printk(KERN_ERR -+ "module %s: relocation overflow\n", -+ me->name); -+ return -ENOEXEC; -+ } - --static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) --{ -- if (is_phys_addr(location)) -- return add_plt_entry_to(&me->arch.phys_plt_offset, -- me->arch.phys_plt_tbl, v); -- else -- return add_plt_entry_to(&me->arch.virt_plt_offset, -- me->arch.virt_plt_tbl, v); -+ *location = (*location & ~0x03ffffff) | -+ ((*location + (v >> 2)) & 0x03ffffff); - -+ return 0; - } - --static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) -+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) - { - if (v % 4) { - printk(KERN_ERR "module %s: dangerous relocation\n", me->name); -@@ -323,31 +125,17 @@ - } - - if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { -- v = add_plt_entry(me, location, v + (ofs << 2)); -- if (!v) { -- printk(KERN_ERR -+ printk(KERN_ERR - "module %s: relocation overflow\n", - me->name); -- return -ENOEXEC; -- } -- ofs = 0; -+ return -ENOEXEC; - } - -- *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff); -+ *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); - - return 0; - } - --static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) --{ -- return set_r_mips_26(me, location, *location & 0x03ffffff, v); --} -- --static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) --{ -- return set_r_mips_26(me, location, 0, v); --} -- - static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) - { - struct mips_hi16 *n; -@@ -612,32 +400,11 @@ - list_add(&me->arch.dbe_list, &dbe_list); - spin_unlock_irq(&dbe_lock); - } -- -- /* Get rid of the fixup trampoline if we're running the module -- * from physically mapped address space */ -- if (me->arch.phys_plt_offset == 0) { -- __module_free(me->arch.phys_plt_tbl); -- me->arch.phys_plt_tbl = NULL; -- } -- if (me->arch.virt_plt_offset == 0) { -- __module_free(me->arch.virt_plt_tbl); -- me->arch.virt_plt_tbl = NULL; -- } -- - return 0; - } - - void module_arch_cleanup(struct module *mod) - { -- if (mod->arch.phys_plt_tbl) { -- __module_free(mod->arch.phys_plt_tbl); -- mod->arch.phys_plt_tbl = NULL; -- } -- if (mod->arch.virt_plt_tbl) { -- __module_free(mod->arch.virt_plt_tbl); -- mod->arch.virt_plt_tbl = NULL; -- } -- - spin_lock_irq(&dbe_lock); - list_del(&mod->arch.dbe_list); - spin_unlock_irq(&dbe_lock);

Parameter NameMeaning
otg_capSpecifies the OTG capabilities. The driver will automatically detect the -+ value for this parameter if none is specified. -+ - 0: HNP and SRP capable (default, if available) -+ - 1: SRP Only capable -+ - 2: No HNP/SRP capable -+
dma_enableSpecifies whether to use slave or DMA mode for accessing the data FIFOs. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: Slave -+ - 1: DMA (default, if available) -+
dma_burst_sizeThe DMA Burst size (applicable only for External DMA Mode). -+ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32) -+
speedSpecifies the maximum speed of operation in host and device mode. The -+ actual speed depends on the speed of the attached device and the value of -+ phy_type. -+ - 0: High Speed (default) -+ - 1: Full Speed -+
host_support_fs_ls_low_powerSpecifies whether low power mode is supported when attached to a Full -+ Speed or Low Speed device in host mode. -+ - 0: Don't support low power mode (default) -+ - 1: Support low power mode -+
host_ls_low_power_phy_clkSpecifies the PHY clock rate in low power mode when connected to a Low -+ Speed device in host mode. This parameter is applicable only if -+ HOST_SUPPORT_FS_LS_LOW_POWER is enabled. -+ - 0: 48 MHz (default) -+ - 1: 6 MHz -+
enable_dynamic_fifo Specifies whether FIFOs may be resized by the driver software. -+ - 0: Use cC FIFO size parameters -+ - 1: Allow dynamic FIFO sizing (default) -+
data_fifo_sizeTotal number of 4-byte words in the data FIFO memory. This memory -+ includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs. -+ - Values: 32 to 32768 (default 8192) -+ -+ Note: The total FIFO memory depth in the FPGA configuration is 8192. -+
dev_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in device mode when dynamic -+ FIFO sizing is enabled. -+ - Values: 16 to 32768 (default 1064) -+
dev_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in device mode when -+ dynamic FIFO sizing is enabled. -+ - Values: 16 to 32768 (default 1024) -+
dev_perio_tx_fifo_size_n (n = 1 to 15)Number of 4-byte words in each of the periodic Tx FIFOs in device mode -+ when dynamic FIFO sizing is enabled. -+ - Values: 4 to 768 (default 256) -+
host_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in host mode when dynamic FIFO -+ sizing is enabled. -+ - Values: 16 to 32768 (default 1024) -+
host_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in host mode when -+ dynamic FIFO sizing is enabled in the core. -+ - Values: 16 to 32768 (default 1024) -+
host_perio_tx_fifo_sizeNumber of 4-byte words in the host periodic Tx FIFO when dynamic FIFO -+ sizing is enabled. -+ - Values: 16 to 32768 (default 1024) -+
max_transfer_sizeThe maximum transfer size supported in bytes. -+ - Values: 2047 to 65,535 (default 65,535) -+
max_packet_countThe maximum number of packets in a transfer. -+ - Values: 15 to 511 (default 511) -+
host_channelsThe number of host channel registers to use. -+ - Values: 1 to 16 (default 12) -+ -+ Note: The FPGA configuration supports a maximum of 12 host channels. -+
dev_endpointsThe number of endpoints in addition to EP0 available for device mode -+ operations. -+ - Values: 1 to 15 (default 6 IN and OUT) -+ -+ Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in -+ addition to EP0. -+
phy_typeSpecifies the type of PHY interface to use. By default, the driver will -+ automatically detect the phy_type. -+ - 0: Full Speed -+ - 1: UTMI+ (default, if available) -+ - 2: ULPI -+
phy_utmi_widthSpecifies the UTMI+ Data Width. This parameter is applicable for a -+ phy_type of UTMI+. Also, this parameter is applicable only if the -+ OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the -+ core has been configured to work at either data path width. -+ - Values: 8 or 16 bits (default 16) -+
phy_ulpi_ddrSpecifies whether the ULPI operates at double or single data rate. This -+ parameter is only applicable if phy_type is ULPI. -+ - 0: single data rate ULPI interface with 8 bit wide data bus (default) -+ - 1: double data rate ULPI interface with 4 bit wide data bus -+
i2c_enableSpecifies whether to use the I2C interface for full speed PHY. This -+ parameter is only applicable if PHY_TYPE is FS. -+ - 0: Disabled (default) -+ - 1: Enabled -+