octeon: remove linux 3.10 support

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 43635
This commit is contained in:
Felix Fietkau 2014-12-11 20:07:39 +00:00
parent c095c7c202
commit 3cc3c0a518
23 changed files with 0 additions and 8719 deletions

View file

@ -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.

View file

@ -1,3 +0,0 @@
obj-${CONFIG_OCTEON_USB} := octeon-usb.o
octeon-usb-y := octeon-hcd.o
octeon-usb-y += cvmx-usb.o

View file

@ -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>

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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";

View file

@ -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/

View file

@ -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");

View file

@ -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 */
/*

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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,

View file

@ -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... */

View file

@ -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++) {

View file

@ -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())

View file

@ -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