This is the SoC used be the ESR Lite made by ubnt.com Signed-off-by: John Crispin <blogic@openwrt.org> SVN-Revision: 37684master
parent
8a4726bca8
commit
3a2040ffee
@ -0,0 +1,25 @@ |
||||
#
|
||||
# Copyright (C) 2013 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk |
||||
|
||||
ARCH:=mips
|
||||
BOARD:=octeon
|
||||
BOARDNAME:=Cavium Networks Octeon
|
||||
FEATURES:=squashfs jffs2 pci usb
|
||||
CFLAGS:=-Os -pipe -march=octeon -fno-caller-saves
|
||||
MAINTAINER:=John Crispin <blogic@openwrt.org>
|
||||
|
||||
LINUX_VERSION:=3.10
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk |
||||
|
||||
|
||||
define Target/Description |
||||
Build firmware images for Cavium Networks Octeon-based boards.
|
||||
endef |
||||
|
||||
$(eval $(call BuildTarget)) |
@ -0,0 +1,18 @@ |
||||
# Copyright (C) 2009 OpenWrt.org |
||||
|
||||
config interface loopback |
||||
option ifname lo |
||||
option proto static |
||||
option ipaddr 127.0.0.1 |
||||
option netmask 255.0.0.0 |
||||
|
||||
config interface lan |
||||
option ifname eth1 |
||||
option type bridge |
||||
option proto static |
||||
option ipaddr 192.168.1.1 |
||||
option netmask 255.255.255.0 |
||||
|
||||
config interface wan |
||||
option ifname eth0 |
||||
option proto dhcp |
@ -0,0 +1,228 @@ |
||||
CONFIG_64BIT=y |
||||
CONFIG_64BIT_PHYS_ADDR=y |
||||
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y |
||||
CONFIG_ARCH_DISCARD_MEMBLOCK=y |
||||
CONFIG_ARCH_DMA_ADDR_T_64BIT=y |
||||
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y |
||||
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y |
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y |
||||
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y |
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y |
||||
CONFIG_ARCH_SUPPORTS_MSI=y |
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y |
||||
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y |
||||
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y |
||||
CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y |
||||
# CONFIG_ARPD is not set |
||||
CONFIG_BINFMT_ELF32=y |
||||
CONFIG_BLK_DEV_SD=y |
||||
CONFIG_BLOCK_COMPAT=y |
||||
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set |
||||
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 |
||||
# CONFIG_CAVIUM_CN63XXP1 is not set |
||||
# 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_CC_OPTIMIZE_FOR_SIZE=y |
||||
CONFIG_CEVT_R4K=y |
||||
CONFIG_CLONE_BACKWARDS=y |
||||
CONFIG_COMPAT=y |
||||
CONFIG_COMPAT_BRK=y |
||||
CONFIG_COMPAT_NETLINK_MESSAGES=y |
||||
CONFIG_CPU_BIG_ENDIAN=y |
||||
CONFIG_CPU_CAVIUM_OCTEON=y |
||||
CONFIG_CPU_GENERIC_DUMP_TLB=y |
||||
CONFIG_CPU_HAS_PREFETCH=y |
||||
CONFIG_CPU_HAS_SYNC=y |
||||
CONFIG_CPU_MIPSR2=y |
||||
CONFIG_CPU_RMAP=y |
||||
CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y |
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y |
||||
CONFIG_CPU_SUPPORTS_HUGEPAGES=y |
||||
CONFIG_CRAMFS=y |
||||
CONFIG_CRC16=y |
||||
CONFIG_CRYPTO_CRC32C=y |
||||
CONFIG_CRYPTO_HASH=y |
||||
CONFIG_CRYPTO_HASH2=y |
||||
CONFIG_DEBUG_INFO=y |
||||
CONFIG_DEBUG_SPINLOCK=y |
||||
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 |
||||
CONFIG_DETECT_HUNG_TASK=y |
||||
CONFIG_DEVKMEM=y |
||||
CONFIG_DMA_COHERENT=y |
||||
CONFIG_DNOTIFY=y |
||||
CONFIG_DTC=y |
||||
CONFIG_EARLY_PRINTK=y |
||||
CONFIG_EDAC_SUPPORT=y |
||||
CONFIG_ENABLE_MUST_CHECK=y |
||||
CONFIG_EXT4_FS=y |
||||
CONFIG_FAT_FS=y |
||||
CONFIG_FRAME_WARN=2048 |
||||
CONFIG_FS_MBCACHE=y |
||||
# CONFIG_FW_LOADER is not set |
||||
CONFIG_GENERIC_CLOCKEVENTS=y |
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y |
||||
CONFIG_GENERIC_CMOS_UPDATE=y |
||||
CONFIG_GENERIC_IO=y |
||||
CONFIG_GENERIC_IRQ_SHOW=y |
||||
CONFIG_GENERIC_PCI_IOMAP=y |
||||
CONFIG_GENERIC_SMP_IDLE_THREAD=y |
||||
CONFIG_GPIO_DEVRES=y |
||||
# CONFIG_HAMRADIO is not set |
||||
CONFIG_HARDWARE_WATCHPOINTS=y |
||||
CONFIG_HAS_DMA=y |
||||
CONFIG_HAS_IOMEM=y |
||||
CONFIG_HAS_IOPORT=y |
||||
CONFIG_HAVE_64BIT_ALIGNED_ACCESS=y |
||||
CONFIG_HAVE_ARCH_JUMP_LABEL=y |
||||
CONFIG_HAVE_ARCH_KGDB=y |
||||
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y |
||||
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set |
||||
CONFIG_HAVE_C_RECORDMCOUNT=y |
||||
CONFIG_HAVE_DEBUG_KMEMLEAK=y |
||||
CONFIG_HAVE_DMA_API_DEBUG=y |
||||
CONFIG_HAVE_DMA_ATTRS=y |
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y |
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y |
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y |
||||
CONFIG_HAVE_FUNCTION_TRACER=y |
||||
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y |
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y |
||||
CONFIG_HAVE_GENERIC_HARDIRQS=y |
||||
CONFIG_HAVE_IDE=y |
||||
CONFIG_HAVE_MEMBLOCK=y |
||||
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y |
||||
CONFIG_HAVE_MEMORY_PRESENT=y |
||||
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y |
||||
CONFIG_HAVE_NET_DSA=y |
||||
CONFIG_HAVE_OPROFILE=y |
||||
CONFIG_HAVE_PERF_EVENTS=y |
||||
# CONFIG_HIGH_RES_TIMERS is not set |
||||
CONFIG_HOLES_IN_ZONE=y |
||||
# CONFIG_HUGETLBFS 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_HZ_PERIODIC=y |
||||
CONFIG_INITRAMFS_SOURCE="" |
||||
CONFIG_IOMMU_HELPER=y |
||||
CONFIG_IRQCHIP=y |
||||
CONFIG_IRQ_DOMAIN=y |
||||
CONFIG_IRQ_FORCED_THREADING=y |
||||
CONFIG_IRQ_WORK=y |
||||
CONFIG_JBD2=y |
||||
CONFIG_KALLSYMS=y |
||||
CONFIG_KEXEC=y |
||||
CONFIG_LIBFDT=y |
||||
CONFIG_MDIO_BOARDINFO=y |
||||
CONFIG_MDIO_OCTEON=y |
||||
CONFIG_MIPS=y |
||||
CONFIG_MIPS32_COMPAT=y |
||||
CONFIG_MIPS32_N32=y |
||||
CONFIG_MIPS32_O32=y |
||||
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set |
||||
CONFIG_MIPS_L1_CACHE_SHIFT=7 |
||||
# CONFIG_MIPS_MACHINE is not set |
||||
CONFIG_MIPS_MT_DISABLED=y |
||||
CONFIG_MIPS_PGD_C0_CONTEXT=y |
||||
CONFIG_MODULES_USE_ELF_REL=y |
||||
CONFIG_MODULES_USE_ELF_RELA=y |
||||
# CONFIG_MTD_CFI_INTELEXT is not set |
||||
CONFIG_MTD_CMDLINE_PARTS=y |
||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set |
||||
CONFIG_MTD_OF_PARTS=y |
||||
CONFIG_MTD_PHYSMAP=y |
||||
CONFIG_MTD_PHYSMAP_OF=y |
||||
CONFIG_MUTEX_SPIN_ON_OWNER=y |
||||
CONFIG_NEED_SG_DMA_LENGTH=y |
||||
# CONFIG_NETWORK_FILESYSTEMS is not set |
||||
CONFIG_NLS=y |
||||
CONFIG_NLS_CODEPAGE_437=y |
||||
CONFIG_NLS_ISO8859_1=y |
||||
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y |
||||
CONFIG_NR_CPUS=16 |
||||
CONFIG_NR_CPUS_DEFAULT_16=y |
||||
CONFIG_OCTEON_ETHERNET=y |
||||
# CONFIG_OCTEON_ILM is not set |
||||
CONFIG_OCTEON_MGMT_ETHERNET=y |
||||
CONFIG_OCTEON_USB=y |
||||
CONFIG_OCTEON_WDT=y |
||||
CONFIG_OF=y |
||||
CONFIG_OF_ADDRESS=y |
||||
CONFIG_OF_DEVICE=y |
||||
CONFIG_OF_EARLY_FLATTREE=y |
||||
CONFIG_OF_FLATTREE=y |
||||
CONFIG_OF_IRQ=y |
||||
CONFIG_OF_MDIO=y |
||||
CONFIG_OF_MTD=y |
||||
CONFIG_OF_NET=y |
||||
CONFIG_OF_PCI=y |
||||
CONFIG_OF_PCI_IRQ=y |
||||
CONFIG_PAGEFLAGS_EXTENDED=y |
||||
# CONFIG_PARTITION_ADVANCED is not set |
||||
CONFIG_PCI=y |
||||
CONFIG_PCI_DOMAINS=y |
||||
CONFIG_PERF_USE_VMALLOC=y |
||||
CONFIG_PHYLIB=y |
||||
CONFIG_PHYS_ADDR_T_64BIT=y |
||||
CONFIG_POSIX_MQUEUE=y |
||||
CONFIG_POSIX_MQUEUE_SYSCTL=y |
||||
# CONFIG_PREEMPT_RCU is not set |
||||
CONFIG_PROC_PAGE_MONITOR=y |
||||
CONFIG_RCU_STALL_COMMON=y |
||||
CONFIG_RELAY=y |
||||
CONFIG_RFS_ACCEL=y |
||||
CONFIG_RPS=y |
||||
CONFIG_SCHED_DEBUG=y |
||||
CONFIG_SCSI=y |
||||
CONFIG_SECCOMP=y |
||||
CONFIG_SMP=y |
||||
CONFIG_SPARSEMEM=y |
||||
CONFIG_SPARSEMEM_STATIC=y |
||||
CONFIG_SPLIT_PTLOCK_CPUS=999999 |
||||
CONFIG_STOP_MACHINE=y |
||||
CONFIG_SWAP_IO_SPACE=y |
||||
CONFIG_SWIOTLB=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_HOTPLUG_CPU=y |
||||
CONFIG_SYS_SUPPORTS_HUGETLBFS=y |
||||
CONFIG_SYS_SUPPORTS_SMP=y |
||||
CONFIG_TICK_CPU_ACCOUNTING=y |
||||
CONFIG_TREE_RCU=y |
||||
CONFIG_UIDGID_CONVERTED=y |
||||
CONFIG_UNINLINE_SPIN_UNLOCK=y |
||||
CONFIG_USB=y |
||||
CONFIG_USB_ARCH_HAS_XHCI=y |
||||
CONFIG_USB_COMMON=y |
||||
CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y |
||||
# CONFIG_USB_EHCI_HCD is not set |
||||
CONFIG_USB_STORAGE=y |
||||
CONFIG_USB_SUPPORT=y |
||||
# CONFIG_USB_UHCI_HCD is not set |
||||
CONFIG_USE_GENERIC_SMP_HELPERS=y |
||||
CONFIG_USE_OF=y |
||||
CONFIG_VFAT_FS=y |
||||
# CONFIG_VLAN_8021Q is not set |
||||
CONFIG_VM_EVENT_COUNTERS=y |
||||
CONFIG_WEAK_ORDERING=y |
||||
CONFIG_XPS=y |
||||
CONFIG_ZLIB_INFLATE=y |
||||
CONFIG_ZONE_DMA32=y |
||||
CONFIG_ZONE_DMA_FLAG=0 |
@ -0,0 +1,10 @@ |
||||
config OCTEON_USB |
||||
tristate "Cavium Networks Octeon USB support" |
||||
depends on CPU_CAVIUM_OCTEON && USB |
||||
help |
||||
This driver supports USB host controller on some Cavium |
||||
Networks' products in the Octeon family. |
||||
|
||||
To compile this driver as a module, choose M here. The module |
||||
will be called octeon-usb. |
||||
|
@ -0,0 +1,3 @@ |
||||
obj-${CONFIG_OCTEON_USB} := octeon-usb.o
|
||||
octeon-usb-y := octeon-hcd.o
|
||||
octeon-usb-y += cvmx-usb.o
|
@ -0,0 +1,11 @@ |
||||
This driver is functional and has been tested on EdgeRouter Lite with |
||||
USB mass storage. |
||||
|
||||
TODO: |
||||
- kernel coding style |
||||
- checkpatch warnings |
||||
- dead code elimination |
||||
- device tree bindings |
||||
- possibly eliminate the extra "hardware abstraction layer" |
||||
|
||||
Contact: Aaro Koskinen <aaro.koskinen@iki.fi> |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,887 @@ |
||||
/***********************license start***************
|
||||
* Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights |
||||
* reserved. |
||||
* |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following |
||||
* disclaimer in the documentation and/or other materials provided |
||||
* with the distribution. |
||||
|
||||
* * Neither the name of Cavium Networks nor the names of |
||||
* its contributors may be used to endorse or promote products |
||||
* derived from this software without specific prior written |
||||
* permission. |
||||
|
||||
* This Software, including technical data, may be subject to U.S. export |
||||
* control laws, including the U.S. Export Administration Act and its associated |
||||
* regulations, and may be subject to export or import regulations in other |
||||
* countries. |
||||
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" |
||||
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR |
||||
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO |
||||
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION |
||||
* OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM |
||||
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, |
||||
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF |
||||
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR |
||||
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR |
||||
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU. |
||||
***********************license end**************************************/ |
||||
|
||||
|
||||
/**
|
||||
* cvmx-usbnx-defs.h |
||||
* |
||||
* Configuration and status register (CSR) type definitions for |
||||
* Octeon usbnx. |
||||
* |
||||
*/ |
||||
#ifndef __CVMX_USBNX_TYPEDEFS_H__ |
||||
#define __CVMX_USBNX_TYPEDEFS_H__ |
||||
|
||||
#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull) |
||||
#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull) |
||||
|
||||
#define CVMX_USBNXREG1(reg, bid) \ |
||||
(CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid)) |
||||
#define CVMX_USBNXREG2(reg, bid) \ |
||||
(CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid)) |
||||
|
||||
#define CVMX_USBNX_CLK_CTL(bid) CVMX_USBNXREG1(0x10, bid) |
||||
#define CVMX_USBNX_DMA0_INB_CHN0(bid) CVMX_USBNXREG2(0x818, bid) |
||||
#define CVMX_USBNX_DMA0_OUTB_CHN0(bid) CVMX_USBNXREG2(0x858, bid) |
||||
#define CVMX_USBNX_USBP_CTL_STATUS(bid) CVMX_USBNXREG1(0x18, bid) |
||||
|
||||
/**
|
||||
* cvmx_usbn#_clk_ctl |
||||
* |
||||
* USBN_CLK_CTL = USBN's Clock Control |
||||
* |
||||
* This register is used to control the frequency of the hclk and the |
||||
* hreset and phy_rst signals. |
||||
*/ |
||||
union cvmx_usbnx_clk_ctl { |
||||
uint64_t u64; |
||||
/**
|
||||
* struct cvmx_usbnx_clk_ctl_s |
||||
* @divide2: The 'hclk' used by the USB subsystem is derived |
||||
* from the eclk. |
||||
* Also see the field DIVIDE. DIVIDE2<1> must currently |
||||
* be zero because it is not implemented, so the maximum |
||||
* ratio of eclk/hclk is currently 16. |
||||
* The actual divide number for hclk is: |
||||
* (DIVIDE2 + 1) * (DIVIDE + 1) |
||||
* @hclk_rst: When this field is '0' the HCLK-DIVIDER used to |
||||
* generate the hclk in the USB Subsystem is held |
||||
* in reset. This bit must be set to '0' before |
||||
* changing the value os DIVIDE in this register. |
||||
* The reset to the HCLK_DIVIDERis also asserted |
||||
* when core reset is asserted. |
||||
* @p_x_on: Force USB-PHY on during suspend. |
||||
* '1' USB-PHY XO block is powered-down during |
||||
* suspend. |
||||
* '0' USB-PHY XO block is powered-up during |
||||
* suspend. |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to |
||||
* remain powered in Suspend Mode. |
||||
* '1' The USB-PHY XO Bias, Bandgap and PLL are |
||||
* powered down in suspend mode. |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* @p_c_sel: Phy clock speed select. |
||||
* Selects the reference clock / crystal frequency. |
||||
* '11': Reserved |
||||
* '10': 48 MHz (reserved when a crystal is used) |
||||
* '01': 24 MHz (reserved when a crystal is used) |
||||
* '00': 12 MHz |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* NOTE: if a crystal is used as a reference clock, |
||||
* this field must be set to 12 MHz. |
||||
* @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. |
||||
* @sd_mode: Scaledown mode for the USBC. Control timing events |
||||
* in the USBC, for normal operation this must be '0'. |
||||
* @s_bist: Starts bist on the hclk memories, during the '0' |
||||
* to '1' transition. |
||||
* @por: Power On Reset for the PHY. |
||||
* Resets all the PHYS registers and state machines. |
||||
* @enable: When '1' allows the generation of the hclk. When |
||||
* '0' the hclk will not be generated. SEE DIVIDE |
||||
* field of this register. |
||||
* @prst: When this field is '0' the reset associated with |
||||
* the phy_clk functionality in the USB Subsystem is |
||||
* help in reset. This bit should not be set to '1' |
||||
* until the time it takes 6 clocks (hclk or phy_clk, |
||||
* whichever is slower) has passed. Under normal |
||||
* operation once this bit is set to '1' it should not |
||||
* be set to '0'. |
||||
* @hrst: When this field is '0' the reset associated with |
||||
* the hclk functioanlity in the USB Subsystem is |
||||
* held in reset.This bit should not be set to '1' |
||||
* until 12ms after phy_clk is stable. Under normal |
||||
* operation, once this bit is set to '1' it should |
||||
* not be set to '0'. |
||||
* @divide: The frequency of 'hclk' used by the USB subsystem |
||||
* is the eclk frequency divided by the value of |
||||
* (DIVIDE2 + 1) * (DIVIDE + 1), also see the field |
||||
* DIVIDE2 of this register. |
||||
* The hclk frequency should be less than 125Mhz. |
||||
* After writing a value to this field the SW should |
||||
* read the field for the value written. |
||||
* The ENABLE field of this register should not be set |
||||
* until AFTER this field is set and then read. |
||||
*/ |
||||
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 |
||||
* @hclk_rst: When this field is '0' the HCLK-DIVIDER used to |
||||
* generate the hclk in the USB Subsystem is held |
||||
* in reset. This bit must be set to '0' before |
||||
* changing the value os DIVIDE in this register. |
||||
* The reset to the HCLK_DIVIDERis also asserted |
||||
* when core reset is asserted. |
||||
* @p_x_on: Force USB-PHY on during suspend. |
||||
* '1' USB-PHY XO block is powered-down during |
||||
* suspend. |
||||
* '0' USB-PHY XO block is powered-up during |
||||
* suspend. |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* @p_rclk: Phy refrence clock enable. |
||||
* '1' The PHY PLL uses the XO block output as a |
||||
* reference. |
||||
* '0' Reserved. |
||||
* @p_xenbn: Phy external clock enable. |
||||
* '1' The XO block uses the clock from a crystal. |
||||
* '0' The XO block uses an external clock supplied |
||||
* on the XO pin. USB_XI should be tied to |
||||
* ground for this usage. |
||||
* @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to |
||||
* remain powered in Suspend Mode. |
||||
* '1' The USB-PHY XO Bias, Bandgap and PLL are |
||||
* powered down in suspend mode. |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* @p_c_sel: Phy clock speed select. |
||||
* Selects the reference clock / crystal frequency. |
||||
* '11': Reserved |
||||
* '10': 48 MHz |
||||
* '01': 24 MHz |
||||
* '00': 12 MHz |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. |
||||
* @sd_mode: Scaledown mode for the USBC. Control timing events |
||||
* in the USBC, for normal operation this must be '0'. |
||||
* @s_bist: Starts bist on the hclk memories, during the '0' |
||||
* to '1' transition. |
||||
* @por: Power On Reset for the PHY. |
||||
* Resets all the PHYS registers and state machines. |
||||
* @enable: When '1' allows the generation of the hclk. When |
||||
* '0' the hclk will not be generated. |
||||
* @prst: When this field is '0' the reset associated with |
||||
* the phy_clk functionality in the USB Subsystem is |
||||
* help in reset. This bit should not be set to '1' |
||||
* until the time it takes 6 clocks (hclk or phy_clk, |
||||
* whichever is slower) has passed. Under normal |
||||
* operation once this bit is set to '1' it should not |
||||
* be set to '0'. |
||||
* @hrst: When this field is '0' the reset associated with |
||||
* the hclk functioanlity in the USB Subsystem is |
||||
* held in reset.This bit should not be set to '1' |
||||
* until 12ms after phy_clk is stable. Under normal |
||||
* operation, once this bit is set to '1' it should |
||||
* not be set to '0'. |
||||
* @divide: The 'hclk' used by the USB subsystem is derived |
||||
* from the eclk. The eclk will be divided by the |
||||
* value of this field +1 to determine the hclk |
||||
* frequency. (Also see HRST of this register). |
||||
* The hclk frequency must be less than 125 MHz. |
||||
*/ |
||||
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 |
||||
* @divide2: The 'hclk' used by the USB subsystem is derived |
||||
* from the eclk. |
||||
* Also see the field DIVIDE. DIVIDE2<1> must currently |
||||
* be zero because it is not implemented, so the maximum |
||||
* ratio of eclk/hclk is currently 16. |
||||
* The actual divide number for hclk is: |
||||
* (DIVIDE2 + 1) * (DIVIDE + 1) |
||||
* @hclk_rst: When this field is '0' the HCLK-DIVIDER used to |
||||
* generate the hclk in the USB Subsystem is held |
||||
* in reset. This bit must be set to '0' before |
||||
* changing the value os DIVIDE in this register. |
||||
* The reset to the HCLK_DIVIDERis also asserted |
||||
* when core reset is asserted. |
||||
* @p_rtype: PHY reference clock type |
||||
* '0' The USB-PHY uses a 12MHz crystal as a clock |
||||
* source at the USB_XO and USB_XI pins |
||||
* '1' Reserved |
||||
* '2' The USB_PHY uses 12/24/48MHz 2.5V board clock |
||||
* at the USB_XO pin. USB_XI should be tied to |
||||
* ground in this case. |
||||
* '3' Reserved |
||||
* (bit 14 was P_XENBN on 3xxx) |
||||
* (bit 15 was P_RCLK on 3xxx) |
||||
* @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to |
||||
* remain powered in Suspend Mode. |
||||
* '1' The USB-PHY XO Bias, Bandgap and PLL are |
||||
* powered down in suspend mode. |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* @p_c_sel: Phy clock speed select. |
||||
* Selects the reference clock / crystal frequency. |
||||
* '11': Reserved |
||||
* '10': 48 MHz (reserved when a crystal is used) |
||||
* '01': 24 MHz (reserved when a crystal is used) |
||||
* '00': 12 MHz |
||||
* The value of this field must be set while POR is |
||||
* active. |
||||
* NOTE: if a crystal is used as a reference clock, |
||||
* this field must be set to 12 MHz. |
||||
* @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. |
||||
* @sd_mode: Scaledown mode for the USBC. Control timing events |
||||
* in the USBC, for normal operation this must be '0'. |
||||
* @s_bist: Starts bist on the hclk memories, during the '0' |
||||
* to '1' transition. |
||||
* @por: Power On Reset for the PHY. |
||||
* Resets all the PHYS registers and state machines. |
||||
* @enable: When '1' allows the generation of the hclk. When |
||||
* '0' the hclk will not be generated. SEE DIVIDE |
||||
* field of this register. |
||||
* @prst: When this field is '0' the reset associated with |
||||
* the phy_clk functionality in the USB Subsystem is |
||||
* help in reset. This bit should not be set to '1' |
||||
* until the time it takes 6 clocks (hclk or phy_clk, |
||||
* whichever is slower) has passed. Under normal |
||||
* operation once this bit is set to '1' it should not |
||||
* be set to '0'. |
||||
* @hrst: When this field is '0' the reset associated with |
||||
* the hclk functioanlity in the USB Subsystem is |
||||
* held in reset.This bit should not be set to '1' |
||||
* until 12ms after phy_clk is stable. Under normal |
||||
* operation, once this bit is set to '1' it should |
||||
* not be set to '0'. |
||||
* @divide: The frequency of 'hclk' used by the USB subsystem |
||||
* is the eclk frequency divided by the value of |
||||
* (DIVIDE2 + 1) * (DIVIDE + 1), also see the field |
||||
* DIVIDE2 of this register. |
||||
* The hclk frequency should be less than 125Mhz. |
||||
* After writing a value to this field the SW should |
||||
* read the field for the value written. |
||||
* The ENABLE field of this register should not be set |
||||
* until AFTER this field is set and then read. |
||||
*/ |
||||
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 cn56xx; |
||||
}; |
||||
typedef union cvmx_usbnx_clk_ctl cvmx_usbnx_clk_ctl_t; |
||||
|
||||
/**
|
||||
* cvmx_usbn#_usbp_ctl_status |
||||
* |
||||
* USBN_USBP_CTL_STATUS = USBP Control And Status Register |
||||
* |
||||
* Contains general control and status information for the USBN block. |
||||
*/ |
||||
union cvmx_usbnx_usbp_ctl_status { |
||||
uint64_t u64; |
||||
/**
|
||||
* struct cvmx_usbnx_usbp_ctl_status_s |
||||
* @txrisetune: HS Transmitter Rise/Fall Time Adjustment |
||||
* @txvreftune: HS DC Voltage Level Adjustment |
||||
* @txfslstune: FS/LS Source Impedence Adjustment |
||||
* @txhsxvtune: Transmitter High-Speed Crossover Adjustment |
||||
* @sqrxtune: Squelch Threshold Adjustment |
||||
* @compdistune: Disconnect Threshold Adjustment |
||||
* @otgtune: VBUS Valid Threshold Adjustment |
||||
* @otgdisable: OTG Block Disable |
||||
* @portreset: Per_Port Reset |
||||
* @drvvbus: Drive VBUS |
||||
* @lsbist: Low-Speed BIST Enable. |
||||
* @fsbist: Full-Speed BIST Enable. |
||||
* @hsbist: High-Speed BIST Enable. |
||||
* @bist_done: PHY Bist Done. |
||||
* Asserted at the end of the PHY BIST sequence. |
||||
* @bist_err: PHY Bist Error. |
||||
* Indicates an internal error was detected during |
||||
* the BIST sequence. |
||||
* @tdata_out: PHY Test Data Out. |
||||
* Presents either internaly generated signals or |
||||
* test register contents, based upon the value of |
||||
* test_data_out_sel. |
||||
* @siddq: Drives the USBP (USB-PHY) SIDDQ input. |
||||
* Normally should be set to zero. |
||||
* When customers have no intent to use USB PHY |
||||
* interface, they should: |
||||
* - still provide 3.3V to USB_VDD33, and |
||||
* - tie USB_REXT to 3.3V supply, and |
||||
* - set USBN*_USBP_CTL_STATUS[SIDDQ]=1 |
||||
* @txpreemphasistune: HS Transmitter Pre-Emphasis Enable |
||||
* @dma_bmode: When set to 1 the L2C DMA address will be updated |
||||
* with byte-counts between packets. When set to 0 |
||||
* the L2C DMA address is incremented to the next |
||||
* 4-byte aligned address after adding byte-count. |
||||
* @usbc_end: Bigendian input to the USB Core. This should be |
||||
* set to '0' for operation. |
||||
* @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. |
||||
* @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. |
||||
* @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D+ line. '1' pull down-resistance is connected |
||||
* to D+/ '0' pull down resistance is not connected |
||||
* to D+. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D- line. '1' pull down-resistance is connected |
||||
* to D-. '0' pull down resistance is not connected |
||||
* to D-. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @hst_mode: When '0' the USB is acting as HOST, when '1' |
||||
* USB is acting as device. This field needs to be |
||||
* set while the USB is in reset. |
||||
* @tuning: Transmitter Tuning for High-Speed Operation. |
||||
* Tunes the current supply and rise/fall output |
||||
* times for high-speed operation. |
||||
* [20:19] == 11: Current supply increased |
||||
* approximately 9% |
||||
* [20:19] == 10: Current supply increased |
||||
* approximately 4.5% |
||||
* [20:19] == 01: Design default. |
||||
* [20:19] == 00: Current supply decreased |
||||
* approximately 4.5% |
||||
* [22:21] == 11: Rise and fall times are increased. |
||||
* [22:21] == 10: Design default. |
||||
* [22:21] == 01: Rise and fall times are decreased. |
||||
* [22:21] == 00: Rise and fall times are decreased |
||||
* further as compared to the 01 setting. |
||||
* @tx_bs_enh: Transmit Bit Stuffing on [15:8]. |
||||
* Enables or disables bit stuffing on data[15:8] |
||||
* when bit-stuffing is enabled. |
||||
* @tx_bs_en: Transmit Bit Stuffing on [7:0]. |
||||
* Enables or disables bit stuffing on data[7:0] |
||||
* when bit-stuffing is enabled. |
||||
* @loop_enb: PHY Loopback Test Enable. |
||||
* '1': During data transmission the receive is |
||||
* enabled. |
||||
* '0': During data transmission the receive is |
||||
* disabled. |
||||
* Must be '0' for normal operation. |
||||
* @vtest_enb: Analog Test Pin Enable. |
||||
* '1' The PHY's analog_test pin is enabled for the |
||||
* input and output of applicable analog test signals. |
||||
* '0' THe analog_test pin is disabled. |
||||
* @bist_enb: Built-In Self Test Enable. |
||||
* Used to activate BIST in the PHY. |
||||
* @tdata_sel: Test Data Out Select. |
||||
* '1' test_data_out[3:0] (PHY) register contents |
||||
* are output. '0' internaly generated signals are |
||||
* output. |
||||
* @taddr_in: Mode Address for Test Interface. |
||||
* Specifies the register address for writing to or |
||||
* reading from the PHY test interface register. |
||||
* @tdata_in: Internal Testing Register Input Data and Select |
||||
* This is a test bus. Data is present on [3:0], |
||||
* and its corresponding select (enable) is present |
||||
* on bits [7:4]. |
||||
* @ate_reset: Reset input from automatic test equipment. |
||||
* This is a test signal. When the USB Core is |
||||
* powered up (not in Susned Mode), an automatic |
||||
* tester can use this to disable phy_clock and |
||||
* free_clk, then re-eanable them with an aligned |
||||
* phase. |
||||
* '1': The phy_clk and free_clk outputs are |
||||
* disabled. "0": The phy_clock and free_clk outputs |
||||
* are available within a specific period after the |
||||
* de-assertion. |
||||
*/ |
||||
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 |
||||
* @bist_done: PHY Bist Done. |
||||
* Asserted at the end of the PHY BIST sequence. |
||||
* @bist_err: PHY Bist Error. |
||||
* Indicates an internal error was detected during |
||||
* the BIST sequence. |
||||
* @tdata_out: PHY Test Data Out. |
||||
* Presents either internaly generated signals or |
||||
* test register contents, based upon the value of |
||||
* test_data_out_sel. |
||||
* @dma_bmode: When set to 1 the L2C DMA address will be updated |
||||
* with byte-counts between packets. When set to 0 |
||||
* the L2C DMA address is incremented to the next |
||||
* 4-byte aligned address after adding byte-count. |
||||
* @usbc_end: Bigendian input to the USB Core. This should be |
||||
* set to '0' for operation. |
||||
* @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. |
||||
* @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. |
||||
* @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D+ line. '1' pull down-resistance is connected |
||||
* to D+/ '0' pull down resistance is not connected |
||||
* to D+. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D- line. '1' pull down-resistance is connected |
||||
* to D-. '0' pull down resistance is not connected |
||||
* to D-. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @hst_mode: When '0' the USB is acting as HOST, when '1' |
||||
* USB is acting as device. This field needs to be |
||||
* set while the USB is in reset. |
||||
* @tuning: Transmitter Tuning for High-Speed Operation. |
||||
* Tunes the current supply and rise/fall output |
||||
* times for high-speed operation. |
||||
* [20:19] == 11: Current supply increased |
||||
* approximately 9% |
||||
* [20:19] == 10: Current supply increased |
||||
* approximately 4.5% |
||||
* [20:19] == 01: Design default. |
||||
* [20:19] == 00: Current supply decreased |
||||
* approximately 4.5% |
||||
* [22:21] == 11: Rise and fall times are increased. |
||||
* [22:21] == 10: Design default. |
||||
* [22:21] == 01: Rise and fall times are decreased. |
||||
* [22:21] == 00: Rise and fall times are decreased |
||||
* further as compared to the 01 setting. |
||||
* @tx_bs_enh: Transmit Bit Stuffing on [15:8]. |
||||
* Enables or disables bit stuffing on data[15:8] |
||||
* when bit-stuffing is enabled. |
||||
* @tx_bs_en: Transmit Bit Stuffing on [7:0]. |
||||
* Enables or disables bit stuffing on data[7:0] |
||||
* when bit-stuffing is enabled. |
||||
* @loop_enb: PHY Loopback Test Enable. |
||||
* '1': During data transmission the receive is |
||||
* enabled. |
||||
* '0': During data transmission the receive is |
||||
* disabled. |
||||
* Must be '0' for normal operation. |
||||
* @vtest_enb: Analog Test Pin Enable. |
||||
* '1' The PHY's analog_test pin is enabled for the |
||||
* input and output of applicable analog test signals. |
||||
* '0' THe analog_test pin is disabled. |
||||
* @bist_enb: Built-In Self Test Enable. |
||||
* Used to activate BIST in the PHY. |
||||
* @tdata_sel: Test Data Out Select. |
||||
* '1' test_data_out[3:0] (PHY) register contents |
||||
* are output. '0' internaly generated signals are |
||||
* output. |
||||
* @taddr_in: Mode Address for Test Interface. |
||||
* Specifies the register address for writing to or |
||||
* reading from the PHY test interface register. |
||||
* @tdata_in: Internal Testing Register Input Data and Select |
||||
* This is a test bus. Data is present on [3:0], |
||||
* and its corresponding select (enable) is present |
||||
* on bits [7:4]. |
||||
* @ate_reset: Reset input from automatic test equipment. |
||||
* This is a test signal. When the USB Core is |
||||
* powered up (not in Susned Mode), an automatic |
||||
* tester can use this to disable phy_clock and |
||||
* free_clk, then re-eanable them with an aligned |
||||
* phase. |
||||
* '1': The phy_clk and free_clk outputs are |
||||
* disabled. "0": The phy_clock and free_clk outputs |
||||
* are available within a specific period after the |
||||
* de-assertion. |
||||
*/ |
||||
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_cn50xx |
||||
* @txrisetune: HS Transmitter Rise/Fall Time Adjustment |
||||
* @txvreftune: HS DC Voltage Level Adjustment |
||||
* @txfslstune: FS/LS Source Impedence Adjustment |
||||
* @txhsxvtune: Transmitter High-Speed Crossover Adjustment |
||||
* @sqrxtune: Squelch Threshold Adjustment |
||||
* @compdistune: Disconnect Threshold Adjustment |
||||
* @otgtune: VBUS Valid Threshold Adjustment |
||||
* @otgdisable: OTG Block Disable |
||||
* @portreset: Per_Port Reset |
||||
* @drvvbus: Drive VBUS |
||||
* @lsbist: Low-Speed BIST Enable. |
||||
* @fsbist: Full-Speed BIST Enable. |
||||
* @hsbist: High-Speed BIST Enable. |
||||
* @bist_done: PHY Bist Done. |
||||
* Asserted at the end of the PHY BIST sequence. |
||||
* @bist_err: PHY Bist Error. |
||||
* Indicates an internal error was detected during |
||||
* the BIST sequence. |
||||
* @tdata_out: PHY Test Data Out. |
||||
* Presents either internaly generated signals or |
||||
* test register contents, based upon the value of |
||||
* test_data_out_sel. |
||||
* @txpreemphasistune: HS Transmitter Pre-Emphasis Enable |
||||
* @dma_bmode: When set to 1 the L2C DMA address will be updated |
||||
* with byte-counts between packets. When set to 0 |
||||
* the L2C DMA address is incremented to the next |
||||
* 4-byte aligned address after adding byte-count. |
||||
* @usbc_end: Bigendian input to the USB Core. This should be |
||||
* set to '0' for operation. |
||||
* @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. |
||||
* @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. |
||||
* @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D+ line. '1' pull down-resistance is connected |
||||
* to D+/ '0' pull down resistance is not connected |
||||
* to D+. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D- line. '1' pull down-resistance is connected |
||||
* to D-. '0' pull down resistance is not connected |
||||
* to D-. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @hst_mode: When '0' the USB is acting as HOST, when '1' |
||||
* USB is acting as device. This field needs to be |
||||
* set while the USB is in reset. |
||||
* @tx_bs_enh: Transmit Bit Stuffing on [15:8]. |
||||
* Enables or disables bit stuffing on data[15:8] |
||||
* when bit-stuffing is enabled. |
||||
* @tx_bs_en: Transmit Bit Stuffing on [7:0]. |
||||
* Enables or disables bit stuffing on data[7:0] |
||||
* when bit-stuffing is enabled. |
||||
* @loop_enb: PHY Loopback Test Enable. |
||||
* '1': During data transmission the receive is |
||||
* enabled. |
||||
* '0': During data transmission the receive is |
||||
* disabled. |
||||
* Must be '0' for normal operation. |
||||
* @vtest_enb: Analog Test Pin Enable. |
||||
* '1' The PHY's analog_test pin is enabled for the |
||||
* input and output of applicable analog test signals. |
||||
* '0' THe analog_test pin is disabled. |
||||
* @bist_enb: Built-In Self Test Enable. |
||||
* Used to activate BIST in the PHY. |
||||
* @tdata_sel: Test Data Out Select. |
||||
* '1' test_data_out[3:0] (PHY) register contents |
||||
* are output. '0' internaly generated signals are |
||||
* output. |
||||
* @taddr_in: Mode Address for Test Interface. |
||||
* Specifies the register address for writing to or |
||||
* reading from the PHY test interface register. |
||||
* @tdata_in: Internal Testing Register Input Data and Select |
||||
* This is a test bus. Data is present on [3:0], |
||||
* and its corresponding select (enable) is present |
||||
* on bits [7:4]. |
||||
* @ate_reset: Reset input from automatic test equipment. |
||||
* This is a test signal. When the USB Core is |
||||
* powered up (not in Susned Mode), an automatic |
||||
* tester can use this to disable phy_clock and |
||||
* free_clk, then re-eanable them with an aligned |
||||
* phase. |
||||
* '1': The phy_clk and free_clk outputs are |
||||
* disabled. "0": The phy_clock and free_clk outputs |
||||
* are available within a specific period after the |
||||
* de-assertion. |
||||
*/ |
||||
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_cn52xx |
||||
* @txrisetune: HS Transmitter Rise/Fall Time Adjustment |
||||
* @txvreftune: HS DC Voltage Level Adjustment |
||||
* @txfslstune: FS/LS Source Impedence Adjustment |
||||
* @txhsxvtune: Transmitter High-Speed Crossover Adjustment |
||||
* @sqrxtune: Squelch Threshold Adjustment |
||||
* @compdistune: Disconnect Threshold Adjustment |
||||
* @otgtune: VBUS Valid Threshold Adjustment |
||||
* @otgdisable: OTG Block Disable |
||||
* @portreset: Per_Port Reset |
||||
* @drvvbus: Drive VBUS |
||||
* @lsbist: Low-Speed BIST Enable. |
||||
* @fsbist: Full-Speed BIST Enable. |
||||
* @hsbist: High-Speed BIST Enable. |
||||
* @bist_done: PHY Bist Done. |
||||
* Asserted at the end of the PHY BIST sequence. |
||||
* @bist_err: PHY Bist Error. |
||||
* Indicates an internal error was detected during |
||||
* the BIST sequence. |
||||
* @tdata_out: PHY Test Data Out. |
||||
* Presents either internaly generated signals or |
||||
* test register contents, based upon the value of |
||||
* test_data_out_sel. |
||||
* @siddq: Drives the USBP (USB-PHY) SIDDQ input. |
||||
* Normally should be set to zero. |
||||
* When customers have no intent to use USB PHY |
||||
* interface, they should: |
||||
* - still provide 3.3V to USB_VDD33, and |
||||
* - tie USB_REXT to 3.3V supply, and |
||||
* - set USBN*_USBP_CTL_STATUS[SIDDQ]=1 |
||||
* @txpreemphasistune: HS Transmitter Pre-Emphasis Enable |
||||
* @dma_bmode: When set to 1 the L2C DMA address will be updated |
||||
* with byte-counts between packets. When set to 0 |
||||
* the L2C DMA address is incremented to the next |
||||
* 4-byte aligned address after adding byte-count. |
||||
* @usbc_end: Bigendian input to the USB Core. This should be |
||||
* set to '0' for operation. |
||||
* @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. |
||||
* @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. |
||||
* @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D+ line. '1' pull down-resistance is connected |
||||
* to D+/ '0' pull down resistance is not connected |
||||
* to D+. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. |
||||
* This signal enables the pull-down resistance on |
||||
* the D- line. '1' pull down-resistance is connected |
||||
* to D-. '0' pull down resistance is not connected |
||||
* to D-. When an A/B device is acting as a host |
||||
* (downstream-facing port), dp_pulldown and |
||||
* dm_pulldown are enabled. This must not toggle |
||||
* during normal opeartion. |
||||
* @hst_mode: When '0' the USB is acting as HOST, when '1' |
||||
* USB is acting as device. This field needs to be |
||||
* set while the USB is in reset. |
||||
* @tx_bs_enh: Transmit Bit Stuffing on [15:8]. |
||||
* Enables or disables bit stuffing on data[15:8] |
||||
* when bit-stuffing is enabled. |
||||
* @tx_bs_en: Transmit Bit Stuffing on [7:0]. |
||||
* Enables or disables bit stuffing on data[7:0] |
||||
* when bit-stuffing is enabled. |
||||
* @loop_enb: PHY Loopback Test Enable. |
||||
* '1': During data transmission the receive is |
||||
* enabled. |
||||
* '0': During data transmission the receive is |
||||
* disabled. |
||||
* Must be '0' for normal operation. |
||||
* @vtest_enb: Analog Test Pin Enable. |
||||
* '1' The PHY's analog_test pin is enabled for the |
||||
* input and output of applicable analog test signals. |
||||
* '0' THe analog_test pin is disabled. |
||||
* @bist_enb: Built-In Self Test Enable. |
||||
* Used to activate BIST in the PHY. |
||||
* @tdata_sel: Test Data Out Select. |
||||
* '1' test_data_out[3:0] (PHY) register contents |
||||
* are output. '0' internaly generated signals are |
||||
* output. |
||||
* @taddr_in: Mode Address for Test Interface. |
||||
* Specifies the register address for writing to or |
||||
* reading from the PHY test interface register. |
||||
* @tdata_in: Internal Testing Register Input Data and Select |
||||
* This is a test bus. Data is present on [3:0], |
||||
* and its corresponding select (enable) is present |
||||
* on bits [7:4]. |
||||
* @ate_reset: Reset input from automatic test equipment. |
||||
* This is a test signal. When the USB Core is |
||||
* powered up (not in Susned Mode), an automatic |
||||
* tester can use this to disable phy_clock and |
||||
* free_clk, then re-eanable them with an aligned |
||||
* phase. |
||||
* '1': The phy_clk and free_clk outputs are |
||||
* disabled. "0": The phy_clock and free_clk outputs |
||||
* are available within a specific period after the |
||||
* de-assertion. |
||||
*/ |
||||
struct cvmx_usbnx_usbp_ctl_status_cn52xx { |
||||
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; |
||||
} cn52xx; |
||||
}; |
||||
typedef union cvmx_usbnx_usbp_ctl_status cvmx_usbnx_usbp_ctl_status_t; |
||||
|
||||
#endif |
@ -0,0 +1,832 @@ |
||||
/*
|
||||
* 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 |
||||
*/ |
||||
#include <linux/kernel.h> |
||||
#include <linux/module.h> |
||||
#include <linux/init.h> |
||||
#include <linux/pci.h> |
||||
#include <linux/interrupt.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/usb.h> |
||||
|
||||
#include <linux/time.h> |
||||
#include <linux/delay.h> |
||||
|
||||
#include <asm/octeon/cvmx.h> |
||||
#include "cvmx-usb.h" |
||||
#include <asm/octeon/cvmx-iob-defs.h> |
||||
|
||||
#include <linux/usb/hcd.h> |
||||
|
||||
#include <linux/err.h> |
||||
|
||||
struct octeon_hcd { |
||||
spinlock_t lock; |
||||
cvmx_usb_state_t usb; |
||||
struct tasklet_struct dequeue_tasklet; |
||||
struct list_head dequeue_list; |
||||
}; |
||||
|
||||
/* convert between an HCD pointer and the corresponding struct octeon_hcd */ |
||||
static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd) |
||||
{ |
||||
return (struct octeon_hcd *)(hcd->hcd_priv); |
||||
} |
||||
|
||||
static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) |
||||
{ |
||||
return container_of((void *)p, struct usb_hcd, hcd_priv); |
||||
} |
||||
|
||||
static inline struct octeon_hcd *cvmx_usb_to_octeon(cvmx_usb_state_t *p) |
||||
{ |
||||
return container_of(p, struct octeon_hcd, usb); |
||||
} |
||||
|
||||
static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_poll(&priv->usb); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
return IRQ_HANDLED; |
||||
} |
||||
|
||||
static void octeon_usb_port_callback(cvmx_usb_state_t *usb, |
||||
cvmx_usb_callback_t reason, |
||||
cvmx_usb_complete_t status, |
||||
int pipe_handle, |
||||
int submit_handle, |
||||
int bytes_transferred, |
||||
void *user_data) |
||||
{ |
||||
struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); |
||||
|
||||
spin_unlock(&priv->lock); |
||||
usb_hcd_poll_rh_status(octeon_to_hcd(priv)); |
||||
spin_lock(&priv->lock); |
||||
} |
||||
|
||||
static int octeon_usb_start(struct usb_hcd *hcd) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
unsigned long flags; |
||||
|
||||
hcd->state = HC_STATE_RUNNING; |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED, |
||||
octeon_usb_port_callback, NULL); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
return 0; |
||||
} |
||||
|
||||
static void octeon_usb_stop(struct usb_hcd *hcd) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED, |
||||
NULL, NULL); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
hcd->state = HC_STATE_HALT; |
||||
} |
||||
|
||||
static int octeon_usb_get_frame_number(struct usb_hcd *hcd) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
|
||||
return cvmx_usb_get_frame_number(&priv->usb); |
||||
} |
||||
|
||||
static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb, |
||||
cvmx_usb_callback_t reason, |
||||
cvmx_usb_complete_t status, |
||||
int pipe_handle, |
||||
int submit_handle, |
||||
int bytes_transferred, |
||||
void *user_data) |
||||
{ |
||||
struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); |
||||
struct usb_hcd *hcd = octeon_to_hcd(priv); |
||||
struct device *dev = hcd->self.controller; |
||||
struct urb *urb = user_data; |
||||
|
||||
urb->actual_length = bytes_transferred; |
||||
urb->hcpriv = NULL; |
||||
|
||||
if (!list_empty(&urb->urb_list)) { |
||||
/*
|
||||
* It is on the dequeue_list, but we are going to call |
||||
* usb_hcd_giveback_urb(), so we must clear it from |
||||
* the list. We got to it before the |
||||
* octeon_usb_urb_dequeue_work() tasklet did. |
||||
*/ |
||||
list_del(&urb->urb_list); |
||||
/* No longer on the dequeue_list. */ |
||||
INIT_LIST_HEAD(&urb->urb_list); |
||||
} |
||||
|
||||
/* For Isochronous transactions we need to update the URB packet status
|
||||
list from data in our private copy */ |
||||
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { |
||||
int i; |
||||
/*
|
||||
* The pointer to the private list is stored in the setup_packet |
||||
* field. |
||||
*/ |
||||
cvmx_usb_iso_packet_t *iso_packet = (cvmx_usb_iso_packet_t *) urb->setup_packet; |
||||
/* Recalculate the transfer size by adding up each packet */ |
||||
urb->actual_length = 0; |
||||
for (i = 0; i < urb->number_of_packets; i++) { |
||||
if (iso_packet[i].status == CVMX_USB_COMPLETE_SUCCESS) { |
||||
urb->iso_frame_desc[i].status = 0; |
||||
urb->iso_frame_desc[i].actual_length = iso_packet[i].length; |
||||
urb->actual_length += urb->iso_frame_desc[i].actual_length; |
||||
} else { |
||||
dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n", |
||||
i, urb->number_of_packets, |
||||
iso_packet[i].status, pipe_handle, |
||||
submit_handle, iso_packet[i].length); |
||||
urb->iso_frame_desc[i].status = -EREMOTEIO; |
||||
} |
||||
} |
||||
/* Free the private list now that we don't need it anymore */ |
||||
kfree(iso_packet); |
||||
urb->setup_packet = NULL; |
||||
} |
||||
|
||||
switch (status) { |
||||
case CVMX_USB_COMPLETE_SUCCESS: |
||||
urb->status = 0; |
||||
break; |
||||
case CVMX_USB_COMPLETE_CANCEL: |
||||
if (urb->status == 0) |
||||
urb->status = -ENOENT; |
||||
break; |
||||
case CVMX_USB_COMPLETE_STALL: |
||||
dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n", |
||||
pipe_handle, submit_handle, bytes_transferred); |
||||
urb->status = -EPIPE; |
||||
break; |
||||
case CVMX_USB_COMPLETE_BABBLEERR: |
||||
dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n", |
||||
pipe_handle, submit_handle, bytes_transferred); |
||||
urb->status = -EPIPE; |
||||
break; |
||||
case CVMX_USB_COMPLETE_SHORT: |
||||
dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n", |
||||
pipe_handle, submit_handle, bytes_transferred); |
||||
urb->status = -EREMOTEIO; |
||||
break; |
||||
case CVMX_USB_COMPLETE_ERROR: |
||||
case CVMX_USB_COMPLETE_XACTERR: |
||||
case CVMX_USB_COMPLETE_DATATGLERR: |
||||
case CVMX_USB_COMPLETE_FRAMEERR: |
||||
dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n", |
||||
status, pipe_handle, submit_handle, bytes_transferred); |
||||
urb->status = -EPROTO; |
||||
break; |
||||
} |
||||
spin_unlock(&priv->lock); |
||||
usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status); |
||||
spin_lock(&priv->lock); |
||||
} |
||||
|
||||
static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, |
||||
struct urb *urb, |
||||
gfp_t mem_flags) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
struct device *dev = hcd->self.controller; |
||||
int submit_handle = -1; |
||||
int pipe_handle; |
||||
unsigned long flags; |
||||
cvmx_usb_iso_packet_t *iso_packet; |
||||
struct usb_host_endpoint *ep = urb->ep; |
||||
|
||||
urb->status = 0; |
||||
INIT_LIST_HEAD(&urb->urb_list); /* not enqueued on dequeue_list */ |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
|
||||
if (!ep->hcpriv) { |
||||
cvmx_usb_transfer_t transfer_type; |
||||
cvmx_usb_speed_t speed; |
||||
int split_device = 0; |
||||
int split_port = 0; |
||||
switch (usb_pipetype(urb->pipe)) { |
||||
case PIPE_ISOCHRONOUS: |
||||
transfer_type = CVMX_USB_TRANSFER_ISOCHRONOUS; |
||||
break; |
||||
case PIPE_INTERRUPT: |
||||
transfer_type = CVMX_USB_TRANSFER_INTERRUPT; |
||||
break; |
||||
case PIPE_CONTROL: |
||||
transfer_type = CVMX_USB_TRANSFER_CONTROL; |
||||
break; |
||||
default: |
||||
transfer_type = CVMX_USB_TRANSFER_BULK; |
||||
break; |
||||
} |
||||
switch (urb->dev->speed) { |
||||
case USB_SPEED_LOW: |
||||
speed = CVMX_USB_SPEED_LOW; |
||||
break; |
||||
case USB_SPEED_FULL: |
||||
speed = CVMX_USB_SPEED_FULL; |
||||
break; |
||||
default: |
||||
speed = CVMX_USB_SPEED_HIGH; |
||||
break; |
||||
} |
||||
/*
|
||||
* For slow devices on high speed ports we need to find the hub |
||||
* that does the speed translation so we know where to send the |
||||
* split transactions. |
||||
*/ |
||||
if (speed != CVMX_USB_SPEED_HIGH) { |
||||
/*
|
||||
* Start at this device and work our way up the usb |
||||
* tree. |
||||
*/ |
||||
struct usb_device *dev = urb->dev; |
||||
while (dev->parent) { |
||||
/*
|
||||
* If our parent is high speed then he'll |
||||
* receive the splits. |
||||
*/ |
||||
if (dev->parent->speed == USB_SPEED_HIGH) { |
||||
split_device = dev->parent->devnum; |
||||
split_port = dev->portnum; |
||||
break; |
||||
} |
||||
/*
|
||||
* Move up the tree one level. If we make it all |
||||
* the way up the tree, then the port must not |
||||
* be in high speed mode and we don't need a |
||||
* split. |
||||
*/ |
||||
dev = dev->parent; |
||||
} |
||||
} |
||||
pipe_handle = cvmx_usb_open_pipe(&priv->usb, |
||||
0, |
||||
usb_pipedevice(urb->pipe), |
||||
usb_pipeendpoint(urb->pipe), |
||||
speed, |
||||
le16_to_cpu(ep->desc.wMaxPacketSize) & 0x7ff, |
||||
transfer_type, |
||||
usb_pipein(urb->pipe) ? CVMX_USB_DIRECTION_IN : CVMX_USB_DIRECTION_OUT, |
||||
urb->interval, |
||||
(le16_to_cpu(ep->desc.wMaxPacketSize) >> 11) & 0x3, |
||||
split_device, |
||||
split_port); |
||||
if (pipe_handle < 0) { |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
dev_dbg(dev, "Failed to create pipe\n"); |
||||
return -ENOMEM; |
||||
} |
||||
ep->hcpriv = (void *)(0x10000L + pipe_handle); |
||||
} else { |
||||
pipe_handle = 0xffff & (long)ep->hcpriv; |
||||
} |
||||
|
||||
switch (usb_pipetype(urb->pipe)) { |
||||
case PIPE_ISOCHRONOUS: |
||||
dev_dbg(dev, "Submit isochronous to %d.%d\n", |
||||
usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe)); |
||||
/*
|
||||
* Allocate a structure to use for our private list of |
||||
* isochronous packets. |
||||
*/ |
||||
iso_packet = kmalloc(urb->number_of_packets * sizeof(cvmx_usb_iso_packet_t), GFP_ATOMIC); |
||||
if (iso_packet) { |
||||
int i; |
||||
/* Fill the list with the data from the URB */ |
||||
for (i = 0; i < urb->number_of_packets; i++) { |
||||
iso_packet[i].offset = urb->iso_frame_desc[i].offset; |
||||
iso_packet[i].length = urb->iso_frame_desc[i].length; |
||||
iso_packet[i].status = CVMX_USB_COMPLETE_ERROR; |
||||
} |
||||
/*
|
||||
* Store a pointer to the list in the URB setup_packet |
||||
* field. We know this currently isn't being used and |
||||
* this saves us a bunch of logic. |
||||
*/ |
||||
urb->setup_packet = (char *)iso_packet; |
||||
submit_handle = cvmx_usb_submit_isochronous(&priv->usb, pipe_handle, |
||||
urb->start_frame, |
||||
0 /* flags */ , |
||||
urb->number_of_packets, |
||||
iso_packet, |
||||
urb->transfer_dma, |
||||
urb->transfer_buffer_length, |
||||
octeon_usb_urb_complete_callback, |
||||
urb); |
||||
/*
|
||||
* If submit failed we need to free our private packet |
||||
* list. |
||||
*/ |
||||
if (submit_handle < 0) { |
||||
urb->setup_packet = NULL; |
||||
kfree(iso_packet); |
||||
} |
||||
} |
||||
break; |
||||
case PIPE_INTERRUPT: |
||||
dev_dbg(dev, "Submit interrupt to %d.%d\n", |
||||
usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe)); |
||||
submit_handle = cvmx_usb_submit_interrupt(&priv->usb, pipe_handle, |
||||
urb->transfer_dma, |
||||
urb->transfer_buffer_length, |
||||
octeon_usb_urb_complete_callback, |
||||
urb); |
||||
break; |
||||
case PIPE_CONTROL: |
||||
dev_dbg(dev, "Submit control to %d.%d\n", |
||||
usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe)); |
||||
submit_handle = cvmx_usb_submit_control(&priv->usb, pipe_handle, |
||||
urb->setup_dma, |
||||
urb->transfer_dma, |
||||
urb->transfer_buffer_length, |
||||
octeon_usb_urb_complete_callback, |
||||
urb); |
||||
break; |
||||
case PIPE_BULK: |
||||
dev_dbg(dev, "Submit bulk to %d.%d\n", |
||||
usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe)); |
||||
submit_handle = cvmx_usb_submit_bulk(&priv->usb, pipe_handle, |
||||
urb->transfer_dma, |
||||
urb->transfer_buffer_length, |
||||
octeon_usb_urb_complete_callback, |
||||
urb); |
||||
break; |
||||
} |
||||
if (submit_handle < 0) { |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
dev_dbg(dev, "Failed to submit\n"); |
||||
return -ENOMEM; |
||||
} |
||||
urb->hcpriv = (void *)(long)(((submit_handle & 0xffff) << 16) | pipe_handle); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
return 0; |
||||
} |
||||
|
||||
static void octeon_usb_urb_dequeue_work(unsigned long arg) |
||||
{ |
||||
unsigned long flags; |
||||
struct octeon_hcd *priv = (struct octeon_hcd *)arg; |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
|
||||
while (!list_empty(&priv->dequeue_list)) { |
||||
int pipe_handle; |
||||
int submit_handle; |
||||
struct urb *urb = container_of(priv->dequeue_list.next, struct urb, urb_list); |
||||
list_del(&urb->urb_list); |
||||
/* not enqueued on dequeue_list */ |
||||
INIT_LIST_HEAD(&urb->urb_list); |
||||
pipe_handle = 0xffff & (long)urb->hcpriv; |
||||
submit_handle = ((long)urb->hcpriv) >> 16; |
||||
cvmx_usb_cancel(&priv->usb, pipe_handle, submit_handle); |
||||
} |
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
} |
||||
|
||||
static int octeon_usb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
unsigned long flags; |
||||
|
||||
if (!urb->dev) |
||||
return -EINVAL; |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
|
||||
urb->status = status; |
||||
list_add_tail(&urb->urb_list, &priv->dequeue_list); |
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
|
||||
tasklet_schedule(&priv->dequeue_tasklet); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) |
||||
{ |
||||
struct device *dev = hcd->self.controller; |
||||
|
||||
if (ep->hcpriv) { |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
int pipe_handle = 0xffff & (long)ep->hcpriv; |
||||
unsigned long flags; |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_cancel_all(&priv->usb, pipe_handle); |
||||
if (cvmx_usb_close_pipe(&priv->usb, pipe_handle)) |
||||
dev_dbg(dev, "Closing pipe %d failed\n", pipe_handle); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
ep->hcpriv = NULL; |
||||
} |
||||
} |
||||
|
||||
static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
cvmx_usb_port_status_t port_status; |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
port_status = cvmx_usb_get_status(&priv->usb); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
buf[0] = 0; |
||||
buf[0] = port_status.connect_change << 1; |
||||
|
||||
return (buf[0] != 0); |
||||
} |
||||
|
||||
static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) |
||||
{ |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
struct device *dev = hcd->self.controller; |
||||
cvmx_usb_port_status_t usb_port_status; |
||||
int port_status; |
||||
struct usb_hub_descriptor *desc; |
||||
unsigned long flags; |
||||
|
||||
switch (typeReq) { |
||||
case ClearHubFeature: |
||||
dev_dbg(dev, "ClearHubFeature\n"); |
||||
switch (wValue) { |
||||
case C_HUB_LOCAL_POWER: |
||||
case C_HUB_OVER_CURRENT: |
||||
/* Nothing required here */ |
||||
break; |
||||
default: |
||||
return -EINVAL; |
||||
} |
||||
break; |
||||
case ClearPortFeature: |
||||
dev_dbg(dev, "ClearPortFeature\n"); |
||||
if (wIndex != 1) { |
||||
dev_dbg(dev, " INVALID\n"); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
switch (wValue) { |
||||
case USB_PORT_FEAT_ENABLE: |
||||
dev_dbg(dev, " ENABLE\n"); |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_disable(&priv->usb); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
break; |
||||
case USB_PORT_FEAT_SUSPEND: |
||||
dev_dbg(dev, " SUSPEND\n"); |
||||
/* Not supported on Octeon */ |
||||
break; |
||||
case USB_PORT_FEAT_POWER: |
||||
dev_dbg(dev, " POWER\n"); |
||||
/* Not supported on Octeon */ |
||||
break; |
||||
case USB_PORT_FEAT_INDICATOR: |
||||
dev_dbg(dev, " INDICATOR\n"); |
||||
/* Port inidicator not supported */ |
||||
break; |
||||
case USB_PORT_FEAT_C_CONNECTION: |
||||
dev_dbg(dev, " C_CONNECTION\n"); |
||||
/* Clears drivers internal connect status change flag */ |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb)); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
break; |
||||
case USB_PORT_FEAT_C_RESET: |
||||
dev_dbg(dev, " C_RESET\n"); |
||||
/*
|
||||
* Clears the driver's internal Port Reset Change flag. |
||||
*/ |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb)); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
break; |
||||
case USB_PORT_FEAT_C_ENABLE: |
||||
dev_dbg(dev, " C_ENABLE\n"); |
||||
/*
|
||||
* Clears the driver's internal Port Enable/Disable |
||||
* Change flag. |
||||
*/ |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb)); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
break; |
||||
case USB_PORT_FEAT_C_SUSPEND: |
||||
dev_dbg(dev, " C_SUSPEND\n"); |
||||
/*
|
||||
* Clears the driver's internal Port Suspend Change |
||||
* flag, which is set when resume signaling on the host |
||||
* port is complete. |
||||
*/ |
||||
break; |
||||
case USB_PORT_FEAT_C_OVER_CURRENT: |
||||
dev_dbg(dev, " C_OVER_CURRENT\n"); |
||||
/* Clears the driver's overcurrent Change flag */ |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb)); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
break; |
||||
default: |
||||
dev_dbg(dev, " UNKNOWN\n"); |
||||
return -EINVAL; |
||||
} |
||||
break; |
||||
case GetHubDescriptor: |
||||
dev_dbg(dev, "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->u.hs.DeviceRemovable[0] = 0; |
||||
desc->u.hs.DeviceRemovable[1] = 0xff; |
||||
break; |
||||
case GetHubStatus: |
||||
dev_dbg(dev, "GetHubStatus\n"); |
||||
*(__le32 *) buf = 0; |
||||
break; |
||||
case GetPortStatus: |
||||
dev_dbg(dev, "GetPortStatus\n"); |
||||
if (wIndex != 1) { |
||||
dev_dbg(dev, " INVALID\n"); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
usb_port_status = cvmx_usb_get_status(&priv->usb); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
port_status = 0; |
||||
|
||||
if (usb_port_status.connect_change) { |
||||
port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); |
||||
dev_dbg(dev, " C_CONNECTION\n"); |
||||
} |
||||
|
||||
if (usb_port_status.port_enabled) { |
||||
port_status |= (1 << USB_PORT_FEAT_C_ENABLE); |
||||
dev_dbg(dev, " C_ENABLE\n"); |
||||
} |
||||
|
||||
if (usb_port_status.connected) { |
||||
port_status |= (1 << USB_PORT_FEAT_CONNECTION); |
||||
dev_dbg(dev, " CONNECTION\n"); |
||||
} |
||||
|
||||
if (usb_port_status.port_enabled) { |
||||
port_status |= (1 << USB_PORT_FEAT_ENABLE); |
||||
dev_dbg(dev, " ENABLE\n"); |
||||
} |
||||
|
||||
if (usb_port_status.port_over_current) { |
||||
port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT); |
||||
dev_dbg(dev, " OVER_CURRENT\n"); |
||||
} |
||||
|
||||
if (usb_port_status.port_powered) { |
||||
port_status |= (1 << USB_PORT_FEAT_POWER); |
||||
dev_dbg(dev, " POWER\n"); |
||||
} |
||||
|
||||
if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH) { |
||||
port_status |= USB_PORT_STAT_HIGH_SPEED; |
||||
dev_dbg(dev, " HIGHSPEED\n"); |
||||
} else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW) { |
||||
port_status |= (1 << USB_PORT_FEAT_LOWSPEED); |
||||
dev_dbg(dev, " LOWSPEED\n"); |
||||
} |
||||
|
||||
*((__le32 *) buf) = cpu_to_le32(port_status); |
||||
break; |
||||
case SetHubFeature: |
||||
dev_dbg(dev, "SetHubFeature\n"); |
||||
/* No HUB features supported */ |
||||
break; |
||||
case SetPortFeature: |
||||
dev_dbg(dev, "SetPortFeature\n"); |
||||
if (wIndex != 1) { |
||||
dev_dbg(dev, " INVALID\n"); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
switch (wValue) { |
||||
case USB_PORT_FEAT_SUSPEND: |
||||
dev_dbg(dev, " SUSPEND\n"); |
||||
return -EINVAL; |
||||
case USB_PORT_FEAT_POWER: |
||||
dev_dbg(dev, " POWER\n"); |
||||
return -EINVAL; |
||||
case USB_PORT_FEAT_RESET: |
||||
dev_dbg(dev, " RESET\n"); |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_disable(&priv->usb); |
||||
if (cvmx_usb_enable(&priv->usb)) |
||||
dev_dbg(dev, "Failed to enable the port\n"); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
return 0; |
||||
case USB_PORT_FEAT_INDICATOR: |
||||
dev_dbg(dev, " INDICATOR\n"); |
||||
/* Not supported */ |
||||
break; |
||||
default: |
||||
dev_dbg(dev, " UNKNOWN\n"); |
||||
return -EINVAL; |
||||
} |
||||
break; |
||||
default: |
||||
dev_dbg(dev, "Unknown root hub request\n"); |
||||
return -EINVAL; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
static const struct hc_driver octeon_hc_driver = { |
||||
.description = "Octeon USB", |
||||
.product_desc = "Octeon Host Controller", |
||||
.hcd_priv_size = sizeof(struct octeon_hcd), |
||||
.irq = octeon_usb_irq, |
||||
.flags = HCD_MEMORY | HCD_USB2, |
||||
.start = octeon_usb_start, |
||||
.stop = octeon_usb_stop, |
||||
.urb_enqueue = octeon_usb_urb_enqueue, |
||||
.urb_dequeue = octeon_usb_urb_dequeue, |
||||
.endpoint_disable = octeon_usb_endpoint_disable, |
||||
.get_frame_number = octeon_usb_get_frame_number, |
||||
.hub_status_data = octeon_usb_hub_status_data, |
||||
.hub_control = octeon_usb_hub_control, |
||||
}; |
||||
|
||||
|
||||
static int octeon_usb_driver_probe(struct device *dev) |
||||
{ |
||||
int status; |
||||
int usb_num = to_platform_device(dev)->id; |
||||
int irq = platform_get_irq(to_platform_device(dev), 0); |
||||
struct octeon_hcd *priv; |
||||
struct usb_hcd *hcd; |
||||
unsigned long flags; |
||||
|
||||
/*
|
||||
* Set the DMA mask to 64bits so we get buffers already translated for |
||||
* DMA. |
||||
*/ |
||||
dev->coherent_dma_mask = ~0; |
||||
dev->dma_mask = &dev->coherent_dma_mask; |
||||
|
||||
hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev)); |
||||
if (!hcd) { |
||||
dev_dbg(dev, "Failed to allocate memory for HCD\n"); |
||||
return -1; |
||||
} |
||||
hcd->uses_new_polling = 1; |
||||
priv = (struct octeon_hcd *)hcd->hcd_priv; |
||||
|
||||
spin_lock_init(&priv->lock); |
||||
|
||||
tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv); |
||||
INIT_LIST_HEAD(&priv->dequeue_list); |
||||
|
||||
status = cvmx_usb_initialize(&priv->usb, usb_num, CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO); |
||||
if (status) { |
||||
dev_dbg(dev, "USB initialization failed with %d\n", status); |
||||
kfree(hcd); |
||||
return -1; |
||||
} |
||||
|
||||
/* This delay is needed for CN3010, but I don't know why... */ |
||||
mdelay(10); |
||||
|
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
cvmx_usb_poll(&priv->usb); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
|
||||
status = usb_add_hcd(hcd, irq, IRQF_SHARED); |
||||
if (status) { |
||||
dev_dbg(dev, "USB add HCD failed with %d\n", status); |
||||
kfree(hcd); |
||||
return -1; |
||||
} |
||||
|
||||
dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int octeon_usb_driver_remove(struct device *dev) |
||||
{ |
||||
int status; |
||||
struct usb_hcd *hcd = dev_get_drvdata(dev); |
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd); |
||||
unsigned long flags; |
||||
|
||||
usb_remove_hcd(hcd); |
||||
tasklet_kill(&priv->dequeue_tasklet); |
||||
spin_lock_irqsave(&priv->lock, flags); |
||||
status = cvmx_usb_shutdown(&priv->usb); |
||||
spin_unlock_irqrestore(&priv->lock, flags); |
||||
if (status) |
||||
dev_dbg(dev, "USB shutdown failed with %d\n", status); |
||||
|
||||
kfree(hcd); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static struct device_driver octeon_usb_driver = { |
||||
.name = "OcteonUSB", |
||||
.bus = &platform_bus_type, |
||||
.probe = octeon_usb_driver_probe, |
||||
.remove = octeon_usb_driver_remove, |
||||
}; |
||||
|
||||
|
||||
#define MAX_USB_PORTS 10 |
||||
static struct platform_device *pdev_glob[MAX_USB_PORTS]; |
||||
static int octeon_usb_registered; |
||||
static int __init octeon_usb_module_init(void) |
||||
{ |
||||
int num_devices = cvmx_usb_get_num_ports(); |
||||
int device; |
||||
|
||||
if (usb_disabled() || num_devices == 0) |
||||
return -ENODEV; |
||||
|
||||
if (driver_register(&octeon_usb_driver)) |
||||
return -ENOMEM; |
||||
|
||||
octeon_usb_registered = 1; |
||||
|
||||
/*
|
||||
* Only cn52XX and cn56XX have DWC_OTG USB hardware and the |
||||
* IOB priority registers. Under heavy network load USB |
||||
* hardware can be starved by the IOB causing a crash. Give |
||||
* it a priority boost if it has been waiting more than 400 |
||||
* cycles to avoid this situation. |
||||
* |
||||
* Testing indicates that a cnt_val of 8192 is not sufficient, |
||||
* but no failures are seen with 4096. We choose a value of |
||||
* 400 to give a safety factor of 10. |
||||
*/ |
||||
if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { |
||||
union cvmx_iob_n2c_l2c_pri_cnt pri_cnt; |
||||
|
||||
pri_cnt.u64 = 0; |
||||
pri_cnt.s.cnt_enb = 1; |
||||
pri_cnt.s.cnt_val = 400; |
||||
cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64); |
||||
} |
||||
|
||||
for (device = 0; device < num_devices; device++) { |
||||
struct resource irq_resource; |
||||
struct platform_device *pdev; |
||||
memset(&irq_resource, 0, sizeof(irq_resource)); |
||||
irq_resource.start = (device == 0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1; |
||||
irq_resource.end = irq_resource.start; |
||||
irq_resource.flags = IORESOURCE_IRQ; |
||||
pdev = platform_device_register_simple((char *)octeon_usb_driver. name, device, &irq_resource, 1); |
||||
if (IS_ERR(pdev)) { |
||||
driver_unregister(&octeon_usb_driver); |
||||
octeon_usb_registered = 0; |
||||
return PTR_ERR(pdev); |
||||
} |
||||
if (device < MAX_USB_PORTS) |
||||
pdev_glob[device] = pdev; |
||||
|
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static void __exit octeon_usb_module_cleanup(void) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i < MAX_USB_PORTS; i++) |
||||
if (pdev_glob[i]) { |
||||
platform_device_unregister(pdev_glob[i]); |
||||
pdev_glob[i] = NULL; |
||||
} |
||||
if (octeon_usb_registered) |
||||
driver_unregister(&octeon_usb_driver); |
||||
} |
||||
|
||||
MODULE_LICENSE("GPL"); |
||||
MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>"); |
||||
MODULE_DESCRIPTION("Cavium Networks Octeon USB Host driver."); |
||||
module_init(octeon_usb_module_init); |
||||
module_exit(octeon_usb_module_cleanup); |
@ -0,0 +1,26 @@ |
||||
#
|
||||
# Copyright (C) 2009-2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk |
||||
include $(INCLUDE_DIR)/image.mk |
||||
|
||||
define Image/BuildKernel |
||||
# Workaround pre-SDK-1.9.0 u-boot versions not handling the .notes section
|
||||
$(TARGET_CROSS)strip -R .notes $(KDIR)/vmlinux.elf -o $(BIN_DIR)/$(IMG_PREFIX)-vmlinux.elf
|
||||
$(STAGING_DIR_HOST)/bin/lzma e $(KDIR)/vmlinux $(KDIR)/vmlinux.bin.l7
|
||||
dd if=$(KDIR)/vmlinux.bin.l7 of=$(BIN_DIR)/$(IMG_PREFIX)-vmlinux.lzma bs=65536 conv=sync
|
||||
endef |
||||
|
||||
define Image/Build/squashfs |
||||
$(call prepare_generic_squashfs,$(KDIR)/root.squashfs)
|
||||
endef |
||||
|
||||
define Image/Build |
||||
$(call Image/Build/$(1))
|
||||
dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync
|
||||
endef |
||||
|
||||
$(eval $(call BuildImage)) |
@ -0,0 +1,46 @@ |
||||
From ab2bb148c5932712d2717a7f3a452846f07a660a Mon Sep 17 00:00:00 2001
|
||||
From: Faidon Liambotis <paravoid@debian.org>
|
||||
Date: Thu, 11 Jul 2013 21:08:09 +0000
|
||||
Subject: [PATCH] MIPS: Octeon: Fix DT pruning bug with pip ports
|
||||
|
||||
During the pruning of the device tree octeon_fdt_pip_iface() is called
|
||||
for each PIP interface and every port up to the port count is removed
|
||||
from the device tree. However, the count was set to the return value of
|
||||
cvmx_helper_interface_enumerate() which doesn't actually return the
|
||||
count but just returns zero on success. This effectively removed *all*
|
||||
ports from the tree.
|
||||
|
||||
Use cvmx_helper_ports_on_interface() instead to fix this. This
|
||||
successfully restores the 3 ports of my ERLite-3 and fixes the "kernel
|
||||
assigns random MAC addresses" issue.
|
||||
|
||||
Signed-off-by: Faidon Liambotis <paravoid@debian.org>
|
||||
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Acked-by: David Daney <david.daney@cavium.com>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/5587/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/cavium-octeon/octeon-platform.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
|
||||
index 7b746e7..1830874 100644
|
||||
--- a/arch/mips/cavium-octeon/octeon-platform.c
|
||||
+++ b/arch/mips/cavium-octeon/octeon-platform.c
|
||||
@@ -334,9 +334,10 @@ static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
|
||||
char name_buffer[20];
|
||||
int iface;
|
||||
int p;
|
||||
- int count;
|
||||
+ int count = 0;
|
||||
|
||||
- count = cvmx_helper_interface_enumerate(idx);
|
||||
+ if (cvmx_helper_interface_enumerate(idx) == 0)
|
||||
+ count = cvmx_helper_ports_on_interface(idx);
|
||||
|
||||
snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
|
||||
iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
|
||||
--
|
||||
1.7.10.4
|
||||
|
@ -0,0 +1,75 @@ |
||||
From a135a9b5d9683ace787c7d86f1e642d9acfacdde Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Date: Sun, 23 Jun 2013 20:38:44 +0000
|
||||
Subject: [PATCH] MIPS: Octeon: Enable interfaces on EdgeRouter Lite
|
||||
|
||||
Enable interfaces on EdgeRouter Lite. Tested with cavium_octeon_defconfig
|
||||
and busybox shell. DHCP & ping works with eth0, eth1 and eth2.
|
||||
|
||||
The board type "UBNT_E100" is taken from the sources of the vendor kernel
|
||||
shipped with the product.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Acked-by: David Daney <david.daney@cavium.com>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/5546/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/cavium-octeon/executive/cvmx-helper-board.c | 13 +++++++++++++
|
||||
arch/mips/include/asm/octeon/cvmx-bootinfo.h | 2 ++
|
||||
2 files changed, 15 insertions(+)
|
||||
|
||||
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
|
||||
index 7c64977..0a1283c 100644
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
|
||||
@@ -181,6 +181,11 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
|
||||
return ipd_port - 16 + 4;
|
||||
else
|
||||
return -1;
|
||||
+ case CVMX_BOARD_TYPE_UBNT_E100:
|
||||
+ if (ipd_port >= 0 && ipd_port <= 2)
|
||||
+ return 7 - ipd_port;
|
||||
+ else
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
/* Some unknown board. Somebody forgot to update this function... */
|
||||
@@ -706,6 +711,14 @@ int __cvmx_helper_board_hardware_enable(int interface)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ } else if (cvmx_sysinfo_get()->board_type ==
|
||||
+ CVMX_BOARD_TYPE_UBNT_E100) {
|
||||
+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0);
|
||||
+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0x10);
|
||||
+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0);
|
||||
+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0x10);
|
||||
+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(2, interface), 0);
|
||||
+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(2, interface), 0x10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
|
||||
index 284fa8d..7b7818d 100644
|
||||
--- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h
|
||||
+++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
|
||||
@@ -227,6 +227,7 @@ enum cvmx_board_types_enum {
|
||||
* use any numbers in this range.
|
||||
*/
|
||||
CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
|
||||
+ CVMX_BOARD_TYPE_UBNT_E100 = 20002,
|
||||
CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
|
||||
|
||||
/* The remaining range is reserved for future use. */
|
||||
@@ -325,6 +326,7 @@ static inline const char *cvmx_board_type_to_string(enum
|
||||
|
||||
/* Customer private range */
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
|
||||
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
|
||||
}
|
||||
return "Unsupported Board";
|
||||
--
|
||||
1.7.10.4
|
||||
|
@ -0,0 +1,87 @@ |
||||
From b164935b38d64557a32892e7aa45e213e9d11ea8 Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Date: Sat, 1 Jun 2013 21:42:58 +0300
|
||||
Subject: [PATCH] staging: MIPS: add Octeon USB HCD support
|
||||
|
||||
Add support for Octeon USB HCD. Tested on EdgeRouter Lite with USB
|
||||
mass storage.
|
||||
|
||||
The driver has been extracted from GPL sources of EdgeRouter Lite firmware
|
||||
(based on Linux 2.6.32.13). Some minor fixes and cleanups have been done
|
||||
to make it work with 3.10-rc3.
|
||||
|
||||
$ uname -a
|
||||
Linux (none) 3.10.0-rc3-edge-00005-g86cb5bc #41 SMP PREEMPT Sat Jun 1 20:41:46 EEST 2013 mips64 GNU/Linux
|
||||
$ modprobe octeon-usb
|
||||
[ 37.971683] octeon_usb: module is from the staging directory, the quality is unknown, you have been warned.
|
||||
[ 37.983649] OcteonUSB: Detected 1 ports
|
||||
[ 37.999360] OcteonUSB OcteonUSB.0: Octeon Host Controller
|
||||
[ 38.004847] OcteonUSB OcteonUSB.0: new USB bus registered, assigned bus number 1
|
||||
[ 38.012332] OcteonUSB OcteonUSB.0: irq 122, io mem 0x00000000
|
||||
[ 38.019970] hub 1-0:1.0: USB hub found
|
||||
[ 38.023851] hub 1-0:1.0: 1 port detected
|
||||
[ 38.028101] OcteonUSB: Registered HCD for port 0 on irq 122
|
||||
[ 38.391443] usb 1-1: new high-speed USB device number 2 using OcteonUSB
|
||||
[ 38.586922] usb-storage 1-1:1.0: USB Mass Storage device detected
|
||||
[ 38.597375] scsi0 : usb-storage 1-1:1.0
|
||||
[ 39.604111] scsi 0:0:0:0: Direct-Access USB DISK 2.0 PMAP PQ: 0 ANSI: 4
|
||||
[ 39.619113] sd 0:0:0:0: [sda] 7579008 512-byte logical blocks: (3.88 GB/3.61 GiB)
|
||||
[ 39.630696] sd 0:0:0:0: [sda] Write Protect is off
|
||||
[ 39.635945] sd 0:0:0:0: [sda] No Caching mode page present
|
||||
[ 39.641464] sd 0:0:0:0: [sda] Assuming drive cache: write through
|
||||
[ 39.651341] sd 0:0:0:0: [sda] No Caching mode page present
|
||||
[ 39.656917] sd 0:0:0:0: [sda] Assuming drive cache: write through
|
||||
[ 39.664296] sda: sda1 sda2
|
||||
[ 39.675574] sd 0:0:0:0: [sda] No Caching mode page present
|
||||
[ 39.681093] sd 0:0:0:0: [sda] Assuming drive cache: write through
|
||||
[ 39.687223] sd 0:0:0:0: [sda] Attached SCSI removable disk
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Cc: David Daney <ddaney.cavm@gmail.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/Kconfig | 2 +
|
||||
drivers/staging/Makefile | 1 +
|
||||
drivers/staging/octeon-usb/Kconfig | 10 +
|
||||
drivers/staging/octeon-usb/Makefile | 3 +
|
||||
drivers/staging/octeon-usb/TODO | 11 +
|
||||
drivers/staging/octeon-usb/cvmx-usb.c | 3344 ++++++++++++++++++++++++++
|
||||
drivers/staging/octeon-usb/cvmx-usb.h | 1085 +++++++++
|
||||
drivers/staging/octeon-usb/cvmx-usbcx-defs.h | 3086 ++++++++++++++++++++++++
|
||||
drivers/staging/octeon-usb/cvmx-usbnx-defs.h | 1596 ++++++++++++
|
||||
drivers/staging/octeon-usb/octeon-hcd.c | 854 +++++++
|
||||
10 files changed, 9992 insertions(+)
|
||||
create mode 100644 drivers/staging/octeon-usb/Kconfig
|
||||
create mode 100644 drivers/staging/octeon-usb/Makefile
|
||||
create mode 100644 drivers/staging/octeon-usb/TODO
|
||||
create mode 100644 drivers/staging/octeon-usb/cvmx-usb.c
|
||||
create mode 100644 drivers/staging/octeon-usb/cvmx-usb.h
|
||||
create mode 100644 drivers/staging/octeon-usb/cvmx-usbcx-defs.h
|
||||
create mode 100644 drivers/staging/octeon-usb/cvmx-usbnx-defs.h
|
||||
create mode 100644 drivers/staging/octeon-usb/octeon-hcd.c
|
||||
|
||||
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
|
||||
index 4464f26..f64b662 100644
|
||||
--- a/drivers/staging/Kconfig
|
||||
+++ b/drivers/staging/Kconfig
|
||||
@@ -62,6 +62,8 @@ source "drivers/staging/line6/Kconfig"
|
||||
|
||||
source "drivers/staging/octeon/Kconfig"
|
||||
|
||||
+source "drivers/staging/octeon-usb/Kconfig"
|
||||
+
|
||||
source "drivers/staging/serqt_usb2/Kconfig"
|
||||
|
||||
source "drivers/staging/vt6655/Kconfig"
|
||||
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
|
||||
index f689b9d..1fb58a1 100644
|
||||
--- a/drivers/staging/Makefile
|
||||
+++ b/drivers/staging/Makefile
|
||||
@@ -25,6 +25,7 @@ obj-$(CONFIG_LINE6_USB) += line6/
|
||||
obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/
|
||||
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
|
||||
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
|
||||
+obj-$(CONFIG_OCTEON_USB) += octeon-usb/
|
||||
obj-$(CONFIG_VT6655) += vt6655/
|
||||
obj-$(CONFIG_VT6656) += vt6656/
|
||||
obj-$(CONFIG_VME_BUS) += vme/
|
@ -0,0 +1,115 @@ |
||||
Index: linux-3.10/drivers/staging/octeon-usb/octeon-hcd.c
|
||||
===================================================================
|
||||
--- linux-3.10.orig/drivers/staging/octeon-usb/octeon-hcd.c 2013-08-03 16:11:44.269610286 +0200
|
||||
+++ linux-3.10/drivers/staging/octeon-usb/octeon-hcd.c 2013-08-04 13:18:54.011421971 +0200
|
||||
@@ -673,8 +673,9 @@
|
||||
};
|
||||
|
||||
|
||||
-static int octeon_usb_driver_probe(struct device *dev)
|
||||
+static int octeon_usb_driver_probe(struct platform_device *pdev)
|
||||
{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
int status;
|
||||
int usb_num = to_platform_device(dev)->id;
|
||||
int irq = platform_get_irq(to_platform_device(dev), 0);
|
||||
@@ -728,8 +729,9 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int octeon_usb_driver_remove(struct device *dev)
|
||||
+static int octeon_usb_driver_remove(struct platform_device *pdev)
|
||||
{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
int status;
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct octeon_hcd *priv = hcd_to_octeon(hcd);
|
||||
@@ -748,30 +750,35 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static struct device_driver octeon_usb_driver = {
|
||||
- .name = "OcteonUSB",
|
||||
- .bus = &platform_bus_type,
|
||||
+static struct platform_driver octeon_usb_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "OcteonUSB",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
.probe = octeon_usb_driver_probe,
|
||||
.remove = octeon_usb_driver_remove,
|
||||
};
|
||||
|
||||
+static struct resource octeon_usb_resources = {
|
||||
+ .start = OCTEON_IRQ_USB0,
|
||||
+ .end = OCTEON_IRQ_USB0,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device octeon_usb_device = {
|
||||
+ .name = "OcteonUSB",
|
||||
+ .id = 0,
|
||||
+ .resource = &octeon_usb_resources,
|
||||
+ .num_resources = 1,
|
||||
+};
|
||||
|
||||
-#define MAX_USB_PORTS 10
|
||||
-static struct platform_device *pdev_glob[MAX_USB_PORTS];
|
||||
-static int octeon_usb_registered;
|
||||
static int __init octeon_usb_module_init(void)
|
||||
{
|
||||
int num_devices = cvmx_usb_get_num_ports();
|
||||
- int device;
|
||||
|
||||
if (usb_disabled() || num_devices == 0)
|
||||
return -ENODEV;
|
||||
|
||||
- if (driver_register(&octeon_usb_driver))
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- octeon_usb_registered = 1;
|
||||
-
|
||||
/*
|
||||
* Only cn52XX and cn56XX have DWC_OTG USB hardware and the
|
||||
* IOB priority registers. Under heavy network load USB
|
||||
@@ -792,37 +799,14 @@
|
||||
cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64);
|
||||
}
|
||||
|
||||
- for (device = 0; device < num_devices; device++) {
|
||||
- struct resource irq_resource;
|
||||
- struct platform_device *pdev;
|
||||
- memset(&irq_resource, 0, sizeof(irq_resource));
|
||||
- irq_resource.start = (device == 0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1;
|
||||
- irq_resource.end = irq_resource.start;
|
||||
- irq_resource.flags = IORESOURCE_IRQ;
|
||||
- pdev = platform_device_register_simple((char *)octeon_usb_driver. name, device, &irq_resource, 1);
|
||||
- if (IS_ERR(pdev)) {
|
||||
- driver_unregister(&octeon_usb_driver);
|
||||
- octeon_usb_registered = 0;
|
||||
- return PTR_ERR(pdev);
|
||||
- }
|
||||
- if (device < MAX_USB_PORTS)
|
||||
- pdev_glob[device] = pdev;
|
||||
+ platform_device_register(&octeon_usb_device);
|
||||
|
||||
- }
|
||||
- return 0;
|
||||
+ return platform_driver_register(&octeon_usb_driver);
|
||||
}
|
||||
|
||||
static void __exit octeon_usb_module_cleanup(void)
|
||||
{
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < MAX_USB_PORTS; i++)
|
||||
- if (pdev_glob[i]) {
|
||||
- platform_device_unregister(pdev_glob[i]);
|
||||
- pdev_glob[i] = NULL;
|
||||
- }
|
||||
- if (octeon_usb_registered)
|
||||
- driver_unregister(&octeon_usb_driver);
|
||||
+ platform_driver_unregister(&octeon_usb_driver);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
@ -0,0 +1,17 @@ |
||||
#
|
||||
# Copyright (C) 2013 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
define Profile/generic |
||||
NAME:=Generic Octeon board
|
||||
PACKAGES:=kmod-ath9k
|
||||
endef |
||||
|
||||
define Profile/generic/Description |
||||
Base packages for Octeon boards.
|
||||
endef |
||||
$(eval $(call Profile,generic)) |
||||
|
Loading…
Reference in new issue