octeon: remove linux 3.10 support
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 43635
This commit is contained in:
parent
c095c7c202
commit
3cc3c0a518
23 changed files with 0 additions and 8719 deletions
|
@ -1,10 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
obj-${CONFIG_OCTEON_USB} := octeon-usb.o
|
||||
octeon-usb-y := octeon-hcd.o
|
||||
octeon-usb-y += cvmx-usb.o
|
|
@ -1,11 +0,0 @@
|
|||
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
|
@ -1,887 +0,0 @@
|
|||
/***********************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
|
|
@ -1,832 +0,0 @@
|
|||
/*
|
||||
* 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);
|
|
@ -1,41 +0,0 @@
|
|||
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(-)
|
||||
|
||||
--- 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(
|
||||
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,68 +0,0 @@
|
|||
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(+)
|
||||
|
||||
--- 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(in
|
||||
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(
|
||||
}
|
||||
}
|
||||
}
|
||||
+ } 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;
|
||||
}
|
||||
--- 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_typ
|
||||
|
||||
/* 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,83 +0,0 @@
|
|||
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
|
||||
|
||||
--- 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"
|
||||
--- 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/
|
|
@ -1,113 +0,0 @@
|
|||
--- a/drivers/staging/octeon-usb/octeon-hcd.c
|
||||
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
|
||||
@@ -673,8 +673,9 @@ static const struct hc_driver octeon_hc_
|
||||
};
|
||||
|
||||
|
||||
-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 @@ static int octeon_usb_driver_probe(struc
|
||||
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 @@ static int octeon_usb_driver_remove(stru
|
||||
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 @@ static int __init octeon_usb_module_init
|
||||
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");
|
|
@ -1,45 +0,0 @@
|
|||
From patchwork Thu Sep 5 18:43:59 2013
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [1/3] staging: octeon-ethernet: make dropped packets to consume NAPI
|
||||
budget
|
||||
From: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
X-Patchwork-Id: 5809
|
||||
Message-Id: <1378406641-16530-2-git-send-email-aaro.koskinen@iki.fi>
|
||||
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
|
||||
devel@driverdev.osuosl.org, linux-mips@linux-mips.org
|
||||
Cc: David Daney <david.daney@cavium.com>,
|
||||
"Jason A. Donenfeld" <Jason@zx2c4.com>, richard@nod.at,
|
||||
Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Date: Thu, 5 Sep 2013 21:43:59 +0300
|
||||
|
||||
We should count also dropped packets, otherwise the NAPI handler may
|
||||
end up running too long.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
|
||||
---
|
||||
drivers/staging/octeon/ethernet-rx.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
|
||||
index 34afc16..10e5416 100644
|
||||
--- a/drivers/staging/octeon/ethernet-rx.c
|
||||
+++ b/drivers/staging/octeon/ethernet-rx.c
|
||||
@@ -303,6 +303,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
|
||||
if (backlog > budget * cores_in_use && napi != NULL)
|
||||
cvm_oct_enable_one_cpu();
|
||||
}
|
||||
+ rx_count++;
|
||||
|
||||
skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1;
|
||||
if (likely(skb_in_hw)) {
|
||||
@@ -429,7 +430,6 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
|
||||
#endif
|
||||
}
|
||||
netif_receive_skb(skb);
|
||||
- rx_count++;
|
||||
} else {
|
||||
/* Drop any packet received for a device that isn't up */
|
||||
/*
|
|
@ -1,60 +0,0 @@
|
|||
From patchwork Thu Sep 5 18:44:00 2013
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [2/3] staging: octeon-ethernet: remove skb alloc failure warnings
|
||||
From: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
X-Patchwork-Id: 5811
|
||||
Message-Id: <1378406641-16530-3-git-send-email-aaro.koskinen@iki.fi>
|
||||
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
|
||||
devel@driverdev.osuosl.org, linux-mips@linux-mips.org
|
||||
Cc: David Daney <david.daney@cavium.com>,
|
||||
"Jason A. Donenfeld" <Jason@zx2c4.com>, richard@nod.at,
|
||||
Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Date: Thu, 5 Sep 2013 21:44:00 +0300
|
||||
|
||||
Remove skb allocation failure warnings. They will trigger a page
|
||||
allocation warning already. Also, one of the warnings was not ratelimited,
|
||||
causing the box to lock up under heavy traffic & low memory.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Acked-by: David Daney <david.daney@cavium.com>
|
||||
|
||||
---
|
||||
drivers/staging/octeon/ethernet-mem.c | 7 +------
|
||||
drivers/staging/octeon/ethernet-rx.c | 3 ---
|
||||
2 files changed, 1 insertion(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c
|
||||
index 78b6cb7..199059d 100644
|
||||
--- a/drivers/staging/octeon/ethernet-mem.c
|
||||
+++ b/drivers/staging/octeon/ethernet-mem.c
|
||||
@@ -48,13 +48,8 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements)
|
||||
while (freed) {
|
||||
|
||||
struct sk_buff *skb = dev_alloc_skb(size + 256);
|
||||
- if (unlikely(skb == NULL)) {
|
||||
- pr_warning
|
||||
- ("Failed to allocate skb for hardware pool %d\n",
|
||||
- pool);
|
||||
+ if (unlikely(skb == NULL))
|
||||
break;
|
||||
- }
|
||||
-
|
||||
skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f));
|
||||
*(struct sk_buff **)(skb->data - sizeof(void *)) = skb;
|
||||
cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128));
|
||||
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
|
||||
index 10e5416..e14a1bb 100644
|
||||
--- a/drivers/staging/octeon/ethernet-rx.c
|
||||
+++ b/drivers/staging/octeon/ethernet-rx.c
|
||||
@@ -337,9 +337,6 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
|
||||
*/
|
||||
skb = dev_alloc_skb(work->len);
|
||||
if (!skb) {
|
||||
- printk_ratelimited("Port %d failed to allocate "
|
||||
- "skbuff, packet dropped\n",
|
||||
- work->ipprt);
|
||||
cvm_oct_free_work(work);
|
||||
continue;
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
From patchwork Thu Sep 5 18:44:01 2013
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [3/3] staging: octeon-ethernet: rgmii: enable interrupts that we can
|
||||
handle
|
||||
From: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
X-Patchwork-Id: 5810
|
||||
Message-Id: <1378406641-16530-4-git-send-email-aaro.koskinen@iki.fi>
|
||||
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
|
||||
devel@driverdev.osuosl.org, linux-mips@linux-mips.org
|
||||
Cc: David Daney <david.daney@cavium.com>,
|
||||
"Jason A. Donenfeld" <Jason@zx2c4.com>, richard@nod.at,
|
||||
Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Date: Thu, 5 Sep 2013 21:44:01 +0300
|
||||
|
||||
Enable only those interrupts that we can handle & acknowledge in the
|
||||
interrupt handler.
|
||||
|
||||
At least on EdgeRouter Lite, the hardware may occasionally interrupt with
|
||||
some error condition when the physical link status changes frequently.
|
||||
Since the interrupt condition is not acked properly, this leads to the
|
||||
following warning and the IRQ gets disabled completely:
|
||||
|
||||
[ 41.324700] eth0: Link down
|
||||
[ 44.324721] eth0: 1000 Mbps Full duplex, port 0, queue 0
|
||||
[ 44.885590] irq 117: nobody cared (try booting with the "irqpoll" option)
|
||||
[ 44.892397] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.11.0-rc5-edge-los.git-27d042f-dirty-00950-gaa42f2d-dirty #8
|
||||
[ 44.902825] Stack : ffffffff815c0000 0000000000000004 0000000000000003 0000000000000000
|
||||
ffffffff81fd0000 ffffffff815c0000 0000000000000004 ffffffff8118530c
|
||||
ffffffff815c0000 ffffffff811858d8 0000000000000000 0000000000000000
|
||||
ffffffff81fd0000 ffffffff81fc0000 ffffffff8152f3a0 ffffffff815b7bf7
|
||||
ffffffff81fc6688 ffffffff815b8060 0000000000000000 0000000000000000
|
||||
0000000000000000 ffffffff815346c8 ffffffff815346b0 ffffffff814a6a18
|
||||
ffffffff8158b848 ffffffff81145614 ffffffff81593800 ffffffff81187174
|
||||
ffffffff815b7d00 ffffffff8158b760 0000000000000000 ffffffff814a9184
|
||||
0000000000000000 0000000000000000 0000000000000000 0000000000000000
|
||||
0000000000000000 ffffffff811203b8 0000000000000000 0000000000000000
|
||||
...
|
||||
[ 44.968408] Call Trace:
|
||||
[ 44.970873] [<ffffffff811203b8>] show_stack+0x68/0x80
|
||||
[ 44.975937] [<ffffffff814a9184>] dump_stack+0x78/0xb8
|
||||
[ 44.980999] [<ffffffff811aac54>] __report_bad_irq+0x44/0x108
|
||||
[ 44.986662] [<ffffffff811ab238>] note_interrupt+0x248/0x2a0
|
||||
[ 44.992240] [<ffffffff811a85e4>] handle_irq_event_percpu+0x144/0x200
|
||||
[ 44.998598] [<ffffffff811a86f4>] handle_irq_event+0x54/0x90
|
||||
[ 45.004176] [<ffffffff811ab908>] handle_level_irq+0xd0/0x148
|
||||
[ 45.009839] [<ffffffff811a7b04>] generic_handle_irq+0x34/0x50
|
||||
[ 45.015589] [<ffffffff8111dae8>] do_IRQ+0x18/0x30
|
||||
[ 45.020301] [<ffffffff8110486c>] plat_irq_dispatch+0x74/0xb8
|
||||
[ 45.025958]
|
||||
[ 45.027451] handlers:
|
||||
[ 45.029731] [<ffffffff813fca10>] cvm_oct_rgmii_rml_interrupt
|
||||
[ 45.035397] Disabling IRQ #117
|
||||
[ 45.038742] Port 0 receive error code 13, packet dropped
|
||||
[ 46.324719] eth0: Link down
|
||||
[ 48.324733] eth0: 1000 Mbps Full duplex, port 0, queue 0
|
||||
|
||||
Reported-by: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Acked-by: David Daney <david.daney@cavium.com>
|
||||
|
||||
---
|
||||
drivers/staging/octeon/ethernet-rgmii.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
|
||||
index d8f5f69..ea53af3 100644
|
||||
--- a/drivers/staging/octeon/ethernet-rgmii.c
|
||||
+++ b/drivers/staging/octeon/ethernet-rgmii.c
|
||||
@@ -373,9 +373,7 @@ int cvm_oct_rgmii_init(struct net_device *dev)
|
||||
* 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.u64 = 0;
|
||||
gmx_rx_int_en.s.phy_dupx = 1;
|
||||
gmx_rx_int_en.s.phy_link = 1;
|
||||
gmx_rx_int_en.s.phy_spd = 1;
|
|
@ -1,28 +0,0 @@
|
|||
From 8b75e77048a378339ada86eff548a5b253212859 Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nsn.com>
|
||||
Date: Fri, 1 Nov 2013 17:06:03 +0200
|
||||
Subject: [PATCH] MIPS: cavium-octeon: fix out-of-bounds array access
|
||||
|
||||
When booting with in-kernel DTBs, the pruning code will enumerate
|
||||
interfaces 0-4. However, there is memory reserved only for 4 so some
|
||||
other data will get overwritten by cvmx_helper_interface_enumerate().
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nsn.com>
|
||||
Acked-by: David Daney <david.daney@cavium.com>
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
Patchwork: http://patchwork.linux-mips.org/patch/6102/
|
||||
---
|
||||
arch/mips/cavium-octeon/executive/cvmx-helper.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
@@ -67,7 +67,7 @@ void (*cvmx_override_pko_queue_priority)
|
||||
void (*cvmx_override_ipd_port_setup) (int ipd_port);
|
||||
|
||||
/* Port count per interface */
|
||||
-static int interface_port_count[4] = { 0, 0, 0, 0 };
|
||||
+static int interface_port_count[5];
|
||||
|
||||
/* Port last configured link info index by IPD/PKO port */
|
||||
static cvmx_helper_link_info_t
|
|
@ -1,42 +0,0 @@
|
|||
From b2e4f1560f7388f8157dd2c828211abbfad0e806 Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nsn.com>
|
||||
Date: Fri, 1 Nov 2013 17:06:04 +0200
|
||||
Subject: [PATCH] MIPS: cavium-octeon: fix early boot hang on EBH5600 board
|
||||
|
||||
The boot hangs early on EBH5600 board when octeon_fdt_pip_iface() is
|
||||
trying enumerate a non-existant interface. The actual hang happens in
|
||||
cvmx_helper_interface_get_mode():
|
||||
|
||||
mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
|
||||
|
||||
when interface == 4. We can avoid this situation by first checking that
|
||||
the interface exists in the DTB.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nsn.com>
|
||||
Acked-by: David Daney <david.daney@cavium.com>
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
Patchwork: http://patchwork.linux-mips.org/patch/6101/
|
||||
---
|
||||
arch/mips/cavium-octeon/octeon-platform.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/mips/cavium-octeon/octeon-platform.c
|
||||
+++ b/arch/mips/cavium-octeon/octeon-platform.c
|
||||
@@ -336,14 +336,14 @@ static void __init octeon_fdt_pip_iface(
|
||||
int p;
|
||||
int count = 0;
|
||||
|
||||
- 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);
|
||||
if (iface < 0)
|
||||
return;
|
||||
|
||||
+ if (cvmx_helper_interface_enumerate(idx) == 0)
|
||||
+ count = cvmx_helper_ports_on_interface(idx);
|
||||
+
|
||||
for (p = 0; p < 16; p++)
|
||||
octeon_fdt_pip_port(iface, idx, p, count - 1, pmac);
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
From d8ce75934b888df0bd73dfd9c030a2b034a04977 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Smith <alex.smith@imgtec.com>
|
||||
Date: Thu, 29 May 2014 11:10:01 +0100
|
||||
Subject: [PATCH] MIPS: octeon: Add interface mode detection for Octeon II
|
||||
|
||||
Add interface mode detection for Octeon II. This is necessary to detect
|
||||
the interface modes correctly on the UBNT E200 board. Code is taken
|
||||
from the UBNT GPL source release, with some alterations: SRIO, ILK and
|
||||
RXAUI interface modes are removed and instead return disabled as these
|
||||
modes are not currently supported.
|
||||
|
||||
Signed-off-by: Alex Smith <alex.smith@imgtec.com>
|
||||
Tested-by: David Daney <david.daney@cavium.com>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7039/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/cavium-octeon/executive/cvmx-helper.c | 166 ++++++++++++++++++++++++
|
||||
1 file changed, 166 insertions(+)
|
||||
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
@@ -104,6 +104,158 @@ int cvmx_helper_ports_on_interface(int i
|
||||
}
|
||||
|
||||
/**
|
||||
+ * @INTERNAL
|
||||
+ * Return interface mode for CN68xx.
|
||||
+ */
|
||||
+static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
|
||||
+{
|
||||
+ union cvmx_mio_qlmx_cfg qlm_cfg;
|
||||
+ switch (interface) {
|
||||
+ case 0:
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
|
||||
+ /* QLM is disabled when QLM SPD is 15. */
|
||||
+ if (qlm_cfg.s.qlm_spd == 15)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ if (qlm_cfg.s.qlm_cfg == 2)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ else if (qlm_cfg.s.qlm_cfg == 3)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ case 2:
|
||||
+ case 3:
|
||||
+ case 4:
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
|
||||
+ /* QLM is disabled when QLM SPD is 15. */
|
||||
+ if (qlm_cfg.s.qlm_spd == 15)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ if (qlm_cfg.s.qlm_cfg == 2)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ else if (qlm_cfg.s.qlm_cfg == 3)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ case 7:
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
|
||||
+ /* QLM is disabled when QLM SPD is 15. */
|
||||
+ if (qlm_cfg.s.qlm_spd == 15) {
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ } else if (qlm_cfg.s.qlm_cfg != 0) {
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
|
||||
+ if (qlm_cfg.s.qlm_cfg != 0)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ }
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_NPI;
|
||||
+ case 8:
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_LOOP;
|
||||
+ default:
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * @INTERNAL
|
||||
+ * Return interface mode for an Octeon II
|
||||
+ */
|
||||
+static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
|
||||
+{
|
||||
+ union cvmx_gmxx_inf_mode mode;
|
||||
+
|
||||
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
|
||||
+ return __cvmx_get_mode_cn68xx(interface);
|
||||
+
|
||||
+ if (interface == 2)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_NPI;
|
||||
+
|
||||
+ if (interface == 3)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_LOOP;
|
||||
+
|
||||
+ /* Only present in CN63XX & CN66XX Octeon model */
|
||||
+ if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
|
||||
+ (interface == 4 || interface == 5)) ||
|
||||
+ (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
|
||||
+ interface >= 4 && interface <= 7)) {
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ }
|
||||
+
|
||||
+ if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
|
||||
+ union cvmx_mio_qlmx_cfg mio_qlm_cfg;
|
||||
+
|
||||
+ /* QLM2 is SGMII0 and QLM1 is SGMII1 */
|
||||
+ if (interface == 0)
|
||||
+ mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
|
||||
+ else if (interface == 1)
|
||||
+ mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ if (mio_qlm_cfg.s.qlm_spd == 15)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ if (mio_qlm_cfg.s.qlm_cfg == 9)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ else if (mio_qlm_cfg.s.qlm_cfg == 11)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
|
||||
+ union cvmx_mio_qlmx_cfg qlm_cfg;
|
||||
+
|
||||
+ if (interface == 0) {
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
|
||||
+ if (qlm_cfg.s.qlm_cfg == 2)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ else if (qlm_cfg.s.qlm_cfg == 3)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ } else if (interface == 1) {
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
|
||||
+ if (qlm_cfg.s.qlm_cfg == 2)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ else if (qlm_cfg.s.qlm_cfg == 3)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ }
|
||||
+ } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
|
||||
+ if (interface == 0) {
|
||||
+ union cvmx_mio_qlmx_cfg qlm_cfg;
|
||||
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
|
||||
+ if (qlm_cfg.s.qlm_cfg == 2)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ }
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ }
|
||||
+
|
||||
+ if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
|
||||
+
|
||||
+ if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
|
||||
+ switch (mode.cn63xx.mode) {
|
||||
+ case 0:
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
|
||||
+ case 1:
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
|
||||
+ default:
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (!mode.s.en)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ if (mode.s.type)
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_GMII;
|
||||
+ else
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_RGMII;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* 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.
|
||||
@@ -116,6 +268,20 @@ int cvmx_helper_ports_on_interface(int i
|
||||
cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
|
||||
{
|
||||
union cvmx_gmxx_inf_mode mode;
|
||||
+
|
||||
+ if (interface < 0 ||
|
||||
+ interface >= cvmx_helper_get_number_of_interfaces())
|
||||
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
|
||||
+
|
||||
+ /*
|
||||
+ * Octeon II models
|
||||
+ */
|
||||
+ if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
|
||||
+ return __cvmx_get_mode_octeon2(interface);
|
||||
+
|
||||
+ /*
|
||||
+ * Octeon and Octeon Plus models
|
||||
+ */
|
||||
if (interface == 2)
|
||||
return CVMX_HELPER_INTERFACE_MODE_NPI;
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From a53825ef4e9b2f42a21ad2b903f4d0ce691a5d63 Mon Sep 17 00:00:00 2001
|
||||
From: Eunbong Song <eunb.song@samsung.com>
|
||||
Date: Tue, 22 Apr 2014 06:16:15 +0000
|
||||
Subject: [PATCH] MIPS: Octeon: Add twsi interrupt initialization for OCTEON
|
||||
3XXX, 5XXX, 63XX
|
||||
|
||||
In octeon_3xxx.dts file, there is a definiton for twsi/twsi2 interrupts.
|
||||
But there is no code for initialization of this interrupts. This patch adds
|
||||
code for initialization of twsi interrupts.
|
||||
|
||||
Signed-off-by: Eunbong Song <eunb.song@samsung.com>
|
||||
Cc: linux-kernel@vger.kernel.org
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/6816/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/cavium-octeon/octeon-irq.c | 2 ++
|
||||
arch/mips/include/asm/mach-cavium-octeon/irq.h | 2 ++
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
--- a/arch/mips/cavium-octeon/octeon-irq.c
|
||||
+++ b/arch/mips/cavium-octeon/octeon-irq.c
|
||||
@@ -1260,11 +1260,13 @@ static void __init octeon_irq_init_ciu(v
|
||||
for (i = 0; i < 4; i++)
|
||||
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40);
|
||||
|
||||
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI, 0, 45);
|
||||
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46);
|
||||
for (i = 0; i < 4; i++)
|
||||
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
|
||||
|
||||
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
|
||||
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI2, 0, 59);
|
||||
|
||||
/* CIU_1 */
|
||||
for (i = 0; i < 16; i++)
|
||||
--- a/arch/mips/include/asm/mach-cavium-octeon/irq.h
|
||||
+++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h
|
||||
@@ -35,6 +35,8 @@ enum octeon_irq {
|
||||
OCTEON_IRQ_PCI_MSI2,
|
||||
OCTEON_IRQ_PCI_MSI3,
|
||||
|
||||
+ OCTEON_IRQ_TWSI,
|
||||
+ OCTEON_IRQ_TWSI2,
|
||||
OCTEON_IRQ_RML,
|
||||
OCTEON_IRQ_TIMER0,
|
||||
OCTEON_IRQ_TIMER1,
|
|
@ -1,31 +0,0 @@
|
|||
--- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h
|
||||
+++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
|
||||
@@ -228,6 +228,8 @@ enum cvmx_board_types_enum {
|
||||
*/
|
||||
CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
|
||||
CVMX_BOARD_TYPE_UBNT_E100 = 20002,
|
||||
+ CVMX_BOARD_TYPE_UBNT_E200 = 20003,
|
||||
+ CVMX_BOARD_TYPE_UBNT_E220 = 20005,
|
||||
CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
|
||||
|
||||
/* The remaining range is reserved for future use. */
|
||||
@@ -327,6 +329,8 @@ static inline const char *cvmx_board_typ
|
||||
/* 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_UBNT_E200)
|
||||
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E220)
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
|
||||
}
|
||||
return "Unsupported Board";
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
|
||||
@@ -186,6 +186,8 @@ int cvmx_helper_board_get_mii_address(in
|
||||
return 7 - ipd_port;
|
||||
else
|
||||
return -1;
|
||||
+ case CVMX_BOARD_TYPE_UBNT_E200:
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
/* Some unknown board. Somebody forgot to update this function... */
|
|
@ -1,34 +0,0 @@
|
|||
--- a/drivers/staging/octeon/ethernet.c
|
||||
+++ b/drivers/staging/octeon/ethernet.c
|
||||
@@ -623,6 +623,7 @@ static int cvm_oct_probe(struct platform
|
||||
int interface;
|
||||
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
|
||||
int qos;
|
||||
+ int i;
|
||||
struct device_node *pip;
|
||||
|
||||
octeon_mdiobus_force_mod_depencency();
|
||||
@@ -706,13 +707,19 @@ static int cvm_oct_probe(struct platform
|
||||
}
|
||||
|
||||
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);
|
||||
+ for (i = 0; i < num_interfaces; i++) {
|
||||
+ cvmx_helper_interface_mode_t imode;
|
||||
+ int interface;
|
||||
+ int num_ports;
|
||||
int port;
|
||||
int port_index;
|
||||
|
||||
+ interface = i;
|
||||
+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_UBNT_E200)
|
||||
+ interface = num_interfaces - (i + 1);
|
||||
+
|
||||
+ num_ports = cvmx_helper_ports_on_interface(interface);
|
||||
+ imode = cvmx_helper_interface_get_mode(interface);
|
||||
for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
|
||||
port < cvmx_helper_get_ipd_port(interface, num_ports);
|
||||
port_index++, port++) {
|
|
@ -1,22 +0,0 @@
|
|||
Index: linux-3.10.49/arch/mips/cavium-octeon/octeon-platform.c
|
||||
===================================================================
|
||||
--- linux-3.10.49.orig/arch/mips/cavium-octeon/octeon-platform.c 2014-07-26 20:39:48.109010152 +0100
|
||||
+++ linux-3.10.49/arch/mips/cavium-octeon/octeon-platform.c 2014-07-26 20:41:10.005008627 +0100
|
||||
@@ -82,7 +82,7 @@
|
||||
};
|
||||
|
||||
/* Only Octeon2 has ehci/ohci */
|
||||
- if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
|
||||
+ if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
|
||||
return 0;
|
||||
|
||||
if (octeon_is_simulation() || usb_disabled())
|
||||
@@ -131,7 +131,7 @@
|
||||
};
|
||||
|
||||
/* Only Octeon2 has ehci/ohci */
|
||||
- if (!OCTEON_IS_MODEL(OCTEON_CN63XX))
|
||||
+ if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
|
||||
return 0;
|
||||
|
||||
if (octeon_is_simulation() || usb_disabled())
|
|
@ -1,214 +0,0 @@
|
|||
Index: linux-3.10.49/drivers/gpio/Kconfig
|
||||
===================================================================
|
||||
--- linux-3.10.49.orig/drivers/gpio/Kconfig 2014-07-18 00:58:15.000000000 +0200
|
||||
+++ linux-3.10.49/drivers/gpio/Kconfig 2014-08-07 11:41:16.517169817 +0200
|
||||
@@ -171,6 +171,14 @@
|
||||
Qualcomm MSM chips. Most of the pins on the MSM can be
|
||||
selected for GPIO, and are controlled by this driver.
|
||||
|
||||
+config GPIO_OCTEON
|
||||
+ tristate "Cavium OCTEON GPIO"
|
||||
+ depends on GPIOLIB && CPU_CAVIUM_OCTEON
|
||||
+ default y
|
||||
+ help
|
||||
+ Say yes here to support the on-chip GPIO lines on the OCTEON
|
||||
+ family of SOCs.
|
||||
+
|
||||
config GPIO_MVEBU
|
||||
def_bool y
|
||||
depends on PLAT_ORION
|
||||
Index: linux-3.10.49/drivers/gpio/Makefile
|
||||
===================================================================
|
||||
--- linux-3.10.49.orig/drivers/gpio/Makefile 2014-07-18 00:58:15.000000000 +0200
|
||||
+++ linux-3.10.49/drivers/gpio/Makefile 2014-08-07 11:41:16.517169817 +0200
|
||||
@@ -10,6 +10,7 @@
|
||||
# Device drivers. Generally keep list sorted alphabetically
|
||||
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
|
||||
|
||||
+obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
|
||||
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
|
||||
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
|
||||
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
|
||||
Index: linux-3.10.49/drivers/gpio/gpio-octeon.c
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-3.10.49/drivers/gpio/gpio-octeon.c 2014-08-07 11:53:14.733161106 +0200
|
||||
@@ -0,0 +1,166 @@
|
||||
+/*
|
||||
+ * 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) 2011,2012 Cavium Inc.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+#include <asm/octeon/octeon.h>
|
||||
+#include <asm/octeon/cvmx-gpio-defs.h>
|
||||
+
|
||||
+#define DRV_VERSION "1.0"
|
||||
+#define DRV_DESCRIPTION "Cavium Inc. OCTEON GPIO Driver"
|
||||
+
|
||||
+#define RX_DAT 0x80
|
||||
+#define TX_SET 0x88
|
||||
+#define TX_CLEAR 0x90
|
||||
+
|
||||
+int gpio_to_irq(unsigned gpio)
|
||||
+{
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+EXPORT_SYMBOL(gpio_to_irq);
|
||||
+
|
||||
+/*
|
||||
+ * The address offset of the GPIO configuration register for a given
|
||||
+ * line.
|
||||
+ */
|
||||
+static unsigned int bit_cfg_reg(unsigned int gpio)
|
||||
+{
|
||||
+ if (gpio < 16)
|
||||
+ return 8 * gpio;
|
||||
+ else
|
||||
+ return 8 * (gpio - 16) + 0x100;
|
||||
+}
|
||||
+
|
||||
+struct octeon_gpio {
|
||||
+ struct gpio_chip chip;
|
||||
+ u64 register_base;
|
||||
+};
|
||||
+
|
||||
+static int octeon_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct octeon_gpio *gpio = container_of(chip, struct octeon_gpio, chip);
|
||||
+
|
||||
+ cvmx_write_csr(gpio->register_base + bit_cfg_reg(offset), 0);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void octeon_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
+{
|
||||
+ struct octeon_gpio *gpio = container_of(chip, struct octeon_gpio, chip);
|
||||
+ u64 mask = 1ull << offset;
|
||||
+ u64 reg = gpio->register_base + (value ? TX_SET : TX_CLEAR);
|
||||
+ cvmx_write_csr(reg, mask);
|
||||
+}
|
||||
+
|
||||
+static int octeon_gpio_dir_out(struct gpio_chip *chip, unsigned offset,
|
||||
+ int value)
|
||||
+{
|
||||
+ struct octeon_gpio *gpio = container_of(chip, struct octeon_gpio, chip);
|
||||
+ union cvmx_gpio_bit_cfgx cfgx;
|
||||
+
|
||||
+
|
||||
+ octeon_gpio_set(chip, offset, value);
|
||||
+
|
||||
+ cfgx.u64 = 0;
|
||||
+ cfgx.s.tx_oe = 1;
|
||||
+
|
||||
+ cvmx_write_csr(gpio->register_base + bit_cfg_reg(offset), cfgx.u64);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int octeon_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct octeon_gpio *gpio = container_of(chip, struct octeon_gpio, chip);
|
||||
+ u64 read_bits = cvmx_read_csr(gpio->register_base + RX_DAT);
|
||||
+
|
||||
+ return ((1ull << offset) & read_bits) != 0;
|
||||
+}
|
||||
+
|
||||
+static int octeon_gpio_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct octeon_gpio *gpio;
|
||||
+ struct gpio_chip *chip;
|
||||
+ struct resource *res_mem;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
+ if (!gpio)
|
||||
+ return -ENOMEM;
|
||||
+ chip = &gpio->chip;
|
||||
+
|
||||
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (res_mem == NULL) {
|
||||
+ dev_err(&pdev->dev, "found no memory resource\n");
|
||||
+ err = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (!devm_request_mem_region(&pdev->dev, res_mem->start,
|
||||
+ resource_size(res_mem),
|
||||
+ res_mem->name)) {
|
||||
+ dev_err(&pdev->dev, "request_mem_region failed\n");
|
||||
+ err = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ gpio->register_base = (u64)devm_ioremap(&pdev->dev, res_mem->start,
|
||||
+ resource_size(res_mem));
|
||||
+
|
||||
+
|
||||
+ pdev->dev.platform_data = chip;
|
||||
+ chip->label = "octeon-gpio";
|
||||
+ chip->dev = &pdev->dev;
|
||||
+ chip->owner = THIS_MODULE;
|
||||
+ chip->base = 0;
|
||||
+ chip->can_sleep = 0;
|
||||
+ chip->ngpio = 20;
|
||||
+ chip->direction_input = octeon_gpio_dir_in;
|
||||
+ chip->get = octeon_gpio_get;
|
||||
+ chip->direction_output = octeon_gpio_dir_out;
|
||||
+ chip->set = octeon_gpio_set;
|
||||
+ err = gpiochip_add(chip);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+
|
||||
+ dev_info(&pdev->dev, "version: " DRV_VERSION "\n");
|
||||
+out:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int octeon_gpio_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct gpio_chip *chip = pdev->dev.platform_data;
|
||||
+ return gpiochip_remove(chip);
|
||||
+}
|
||||
+
|
||||
+static struct of_device_id octeon_gpio_match[] = {
|
||||
+ {
|
||||
+ .compatible = "cavium,octeon-3860-gpio",
|
||||
+ },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, octeon_gpio_match);
|
||||
+
|
||||
+static struct platform_driver octeon_gpio_driver = {
|
||||
+ .probe = octeon_gpio_probe,
|
||||
+ .remove = octeon_gpio_remove,
|
||||
+ .driver = {
|
||||
+ .name = "octeon_gpio",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = octeon_gpio_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(octeon_gpio_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
+MODULE_AUTHOR("David Daney");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_VERSION(DRV_VERSION);
|
||||
Index: linux-3.10.49/arch/mips/Kconfig
|
||||
===================================================================
|
||||
--- linux-3.10.49.orig/arch/mips/Kconfig 2014-08-07 11:41:14.809169838 +0200
|
||||
+++ linux-3.10.49/arch/mips/Kconfig 2014-08-07 11:41:16.521169817 +0200
|
||||
@@ -769,6 +769,7 @@
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_ARCH_HAS_EHCI
|
||||
select HOLES_IN_ZONE
|
||||
+ select ARCH_REQUIRE_GPIOLIB
|
||||
help
|
||||
This option supports all of the Octeon reference boards from Cavium
|
||||
Networks. It builds a kernel that dynamically determines the Octeon
|
Loading…
Reference in a new issue