#ifndef _XUSB_H
#define _XUSB_H
+#include <linux/types.h>
+
/*
* BIT0 - BIT7 : SS ports
* BIT8 - BIT15 : USB2 UTMI ports
const char *default_firmware_file;
const struct tegra_xusb_padctl_regs *padctl_offsets;
void (*check_lane_owner_by_pad) (int pad, u32 lane_owner);
+
+ /* applicable to T210 */
+ u32 tx_term_ctrl;
+ u32 rx_ctle;
+ u32 rx_dfe;
+ u32 rx_eq_ctrl_h;
+
+ /* applicable to T114/T124/T132 */
u32 rx_wander;
u32 rx_eq;
u32 cdr_cntl;
xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
+ifeq ($(CONFIG_ARCH_TEGRA_21x_SOC),y)
+ xhci-hcd-y += xhci-tegra-t210-padctl.o
+endif
+
ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
xhci-hcd-y += xhci-plat.o
endif
--- /dev/null
+/*
+ * xhci-tegra-t210-padctl.c - Nvidia xHCI host padctl driver
+
+ *
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <mach/tegra_usb_pad_ctrl.h>
+#include "xhci-tegra.h"
+#include "xhci-tegra-t210-padreg.h"
+
+/* UPHY_USB3_PADx_ECTL_1 */
+#define TX_TERM_CTRL(x) (((x) & 0x3) << 16)
+
+/* UPHY_USB3_PADx_ECTL_2 */
+#define RX_CTLE(x) (((x) & 0xffff) << 0)
+
+/* UPHY_USB3_PADx_ECTL_3 */
+#define RX_DFE(x) (((x) & 0xffffffff) << 0)
+
+/* UPHY_USB3_PADx_ECTL_6 */
+#define RX_EQ_CTRL_H(x) (((x) & 0xffffffff) << 0)
+
+void t210_program_ss_pad(struct tegra_xhci_hcd *tegra, u8 port)
+{
+ u32 ctl1, ctl2, ctl3, ctl6, val;
+
+ xusb_ss_pad_init(port, GET_SS_PORTMAP(tegra->bdata->ss_portmap, port)
+ , XUSB_HOST_MODE);
+
+ ctl1 = tegra->padregs->uphy_usb3_padX_ectlY_0[port][0];
+ ctl2 = tegra->padregs->uphy_usb3_padX_ectlY_0[port][1];
+ ctl3 = tegra->padregs->uphy_usb3_padX_ectlY_0[port][2];
+ ctl6 = tegra->padregs->uphy_usb3_padX_ectlY_0[port][5];
+
+ val = padctl_readl(tegra, ctl1);
+ val &= ~TX_TERM_CTRL(~0);
+ val |= TX_TERM_CTRL(tegra->soc_config->tx_term_ctrl);
+ padctl_writel(tegra, val, ctl1);
+
+ val = padctl_readl(tegra, ctl2);
+ val &= ~RX_CTLE(~0);
+ val |= RX_CTLE(tegra->soc_config->rx_ctle);
+ padctl_writel(tegra, val, ctl2);
+
+ val = padctl_readl(tegra, ctl3);
+ val &= ~RX_DFE(~0);
+ val |= RX_DFE(tegra->soc_config->rx_dfe);
+ padctl_writel(tegra, val, ctl3);
+
+ val = padctl_readl(tegra, ctl6);
+ val &= ~RX_EQ_CTRL_H(~0);
+ val |= RX_EQ_CTRL_H(tegra->soc_config->rx_eq_ctrl_h);
+ padctl_writel(tegra, val, ctl6);
+}
+#ifndef _XHCI_TEGRA_T210_PADCTL_H
+#define _XHCI_TEGRA_T210_PADCTL_H
/*
- * xhci-tegra-T210-padreg.h - Nvidia xHCI host controller related data
+ * xhci-tegra-t210-padreg.h - Nvidia xHCI host controller related data
*
* Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
/* XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_0 0x344*/
#define STRB_TRIM_VAL(x) 0x0
+
+void t210_program_ss_pad(struct tegra_xhci_hcd *tegra, u8 port);
+
+
+#endif /* _XHCI_TEGRA_T210_PADCTL_H */
#else
#include "xhci-tegra-t124-padreg.h"
#endif
-#define NOT_SUPPORTED 0xFFFFFFFF
-#define PADCTL_REG_NONE 0xffff
/* macros */
#define FW_IOCTL_LOG_DEQUEUE_LOW (4)
_reg, readl(_base + _reg))
#define PMC_PORTMAP_MASK(map, pad) (((map) >> 4*(pad)) & 0xF)
-#define GET_SS_PORTMAP(map, p) (((map) >> 4*(p)) & 0xF)
#define PMC_USB_DEBOUNCE_DEL_0 0xec
#define UTMIP_LINE_DEB_CNT(x) (((x) & 0xf) << 16)
u8 padding[138]; /* padding bytes to makeup 256-bytes cfgtbl */
};
-struct xusb_save_regs {
- u32 msi_bar_sz;
- u32 msi_axi_barst;
- u32 msi_fpci_barst;
- u32 msi_vec0;
- u32 msi_en_vec0;
- u32 fpci_error_masks;
- u32 intr_mask;
- u32 ipfs_intr_enable;
- u32 ufpci_config;
- u32 clkgate_hysteresis;
- u32 xusb_host_mccif_fifo_cntrl;
-
- /* PG does not mention below */
- u32 hs_pls;
- u32 fs_pls;
- u32 hs_fs_speed;
- u32 hs_fs_pp;
- u32 cfg_aru;
- u32 cfg_order;
- u32 cfg_fladj;
- u32 cfg_sid;
- /* DFE and CTLE */
- u32 tap1_val[XUSB_SS_PORT_COUNT];
- u32 amp_val[XUSB_SS_PORT_COUNT];
- u32 ctle_z_val[XUSB_SS_PORT_COUNT];
- u32 ctle_g_val[XUSB_SS_PORT_COUNT];
-};
-
-struct tegra_xhci_firmware {
- void *data; /* kernel virtual address */
- size_t size; /* firmware size */
- dma_addr_t dma; /* dma address for controller */
-};
-
-struct tegra_xhci_firmware_log {
- dma_addr_t phys_addr; /* dma-able address */
- void *virt_addr; /* kernel va of the shared log buffer */
- struct log_entry *dequeue; /* current dequeue pointer (va) */
- struct circ_buf circ; /* big circular buffer */
- u32 seq; /* log sequence number */
-
- struct task_struct *thread; /* a thread to consume log */
- struct mutex mutex;
- wait_queue_head_t read_wait;
- wait_queue_head_t write_wait;
- wait_queue_head_t intr_wait;
- struct dentry *path;
- struct dentry *log_file;
- unsigned long flags;
-};
-
-struct tegra_xhci_hcd {
- struct platform_device *pdev;
- struct xhci_hcd *xhci;
- u16 device_id;
-
- spinlock_t lock;
- struct mutex sync_lock;
-
- int smi_irq;
- int padctl_irq;
- int usb3_irq;
- int usb2_irq;
-
- bool ss_wake_event;
- bool ss_pwr_gated;
- bool host_pwr_gated;
- bool hs_wake_event;
- bool host_resume_req;
- bool lp0_exit;
- u32 dfe_ctx_saved;
- u32 ctle_ctx_saved;
- unsigned long last_jiffies;
- unsigned long host_phy_base;
- unsigned long host_phy_size;
- void __iomem *host_phy_virt_base;
-
- void __iomem *padctl_base;
- void __iomem *fpci_base;
- void __iomem *ipfs_base;
-
- struct tegra_xusb_platform_data *pdata;
- struct tegra_xusb_board_data *bdata;
- struct tegra_xusb_chip_calib *cdata;
- struct tegra_xusb_padctl_regs *padregs;
- const struct tegra_xusb_soc_config *soc_config;
- u64 tegra_xusb_dmamask;
-
- /* mailbox variables */
- struct mutex mbox_lock;
- u32 mbox_owner;
- u32 cmd_type;
- u32 cmd_data;
-
- struct regulator **xusb_utmi_vbus_regs;
-
- struct regulator *xusb_s1p05v_reg;
- struct regulator *xusb_s3p3v_reg;
- struct regulator *xusb_s1p8v_reg;
- struct regulator *vddio_hsic_reg;
- int vddio_hsic_refcnt;
-
- struct work_struct mbox_work;
- struct work_struct ss_elpg_exit_work;
- struct work_struct host_elpg_exit_work;
-
- struct clk *host_clk;
- struct clk *ss_clk;
-
- /* XUSB Falcon SuperSpeed Clock */
- struct clk *falc_clk;
-
- /* EMC Clock */
- struct clk *emc_clk;
- /* XUSB SS PI Clock */
- struct clk *ss_src_clk;
- /* PLLE Clock */
- struct clk *plle_clk;
- struct clk *pll_u_480M;
- struct clk *clk_m;
- /* refPLLE clk */
- struct clk *pll_re_vco_clk;
- /*
- * XUSB/IPFS specific registers these need to be saved/restored in
- * addition to spec defined registers
- */
- struct xusb_save_regs sregs;
- bool usb2_rh_suspend;
- bool usb3_rh_suspend;
- bool hc_in_elpg;
-
- /* otg transceiver */
- struct usb_phy *transceiver;
- struct notifier_block otgnb;
-
- unsigned long usb2_rh_remote_wakeup_ports; /* one bit per port */
- unsigned long usb3_rh_remote_wakeup_ports; /* one bit per port */
- /* firmware loading related */
- struct tegra_xhci_firmware firmware;
-
- struct tegra_xhci_firmware_log log;
- struct device_attribute hsic_power_attr[XUSB_HSIC_COUNT];
-
- bool init_done;
-};
-
static int tegra_xhci_probe2(struct tegra_xhci_hcd *tegra);
static int tegra_xhci_remove(struct platform_device *pdev);
static void init_filesystem_firmware_done(const struct firmware *fw,
MODULE_PARM_DESC(firmware_file, FIRMWARE_FILE_HELP);
/* functions */
-static inline u32 padctl_readl(struct tegra_xhci_hcd *tegra, u32 reg)
-{
- if (reg == PADCTL_REG_NONE)
- return PADCTL_REG_NONE;
- return readl(tegra->padctl_base + reg);
-}
-
-static inline void padctl_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 reg)
-{
- if (reg == PADCTL_REG_NONE)
- return;
- writel(val, tegra->padctl_base + reg);
-}
-
static inline struct tegra_xhci_hcd *hcd_to_tegra_xhci(struct usb_hcd *hcd)
{
return (struct tegra_xhci_hcd *) dev_get_drvdata(hcd->self.controller);
return ret;
}
+
+
static void tegra_xhci_program_ss_pad(struct tegra_xhci_hcd *tegra,
u8 port)
{
if (tegra->bdata->portmap & (1 << pad)) {
tegra->soc_config->check_lane_owner_by_pad(pad
, tegra->bdata->lane_owner);
+#if defined(CONFIG_ARCH_TEGRA_21x_SOC)
+ t210_program_ss_pad(tegra, pad);
+#else
tegra_xhci_program_ss_pad(tegra, pad);
+#endif
} else {
reg = padctl_readl(tegra
, padregs->iophy_misc_pad_pX_ctlY_0[pad][2]);
.ss_pad_count = 4,
.padctl_offsets = &tegra210_padctl_offsets,
.check_lane_owner_by_pad = t210_chk_lane_owner_by_pad,
+
+ .tx_term_ctrl = 0x2,
+ .rx_ctle = 0xfb,
+ .rx_dfe = 0x77f1f,
+ .rx_eq_ctrl_h = 0xfcf01368,
};
static struct of_device_id tegra_xhci_of_match[] = {
#ifndef __XUSB_H
#define __XUSB_H
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/circ_buf.h>
+#include <linux/device.h>
+#include <linux/notifier.h>
+
+#include <mach/xusb.h>
+
#define XUSB_CSB_MP_L2IMEMOP_TRIG 0x00101A14
#define XUSB_CSB_MP_APMAP 0x0010181C
#define XUSB_CSB_ARU_SCRATCH0 0x00100100
#define XUSB_DEVICE_ID_T114 0x0E16
#define XUSB_DEVICE_ID_T124 0x0FA3
#define XUSB_DEVICE_ID_T210 0x0FAC
+#define XUSB_IS_T114_OR_T124(t) \
+ ((t->device_id == XUSB_DEVICE_ID_T114) || \
+ (t->device_id == XUSB_DEVICE_ID_T124))
+#define XUSB_IS_T210(t) (t->device_id == XUSB_DEVICE_ID_T114)
/* TODO: Do not have the definitions of below
* registers.
#define ARU_ULPI_REGACCESS_CMD_MASK 0x1
#define ARU_ULPI_REGACCESS_DATA_MASK 0xff0000
+#define GET_SS_PORTMAP(map, p) (((map) >> 4*(p)) & 0xF)
+
/*
* FIXME: looks like no any .c requires below structure types
* revisit and decide whether we can delete or not
u32 vbus_en1;
};
+struct xusb_save_regs {
+ u32 msi_bar_sz;
+ u32 msi_axi_barst;
+ u32 msi_fpci_barst;
+ u32 msi_vec0;
+ u32 msi_en_vec0;
+ u32 fpci_error_masks;
+ u32 intr_mask;
+ u32 ipfs_intr_enable;
+ u32 ufpci_config;
+ u32 clkgate_hysteresis;
+ u32 xusb_host_mccif_fifo_cntrl;
+
+ /* PG does not mention below */
+ u32 hs_pls;
+ u32 fs_pls;
+ u32 hs_fs_speed;
+ u32 hs_fs_pp;
+ u32 cfg_aru;
+ u32 cfg_order;
+ u32 cfg_fladj;
+ u32 cfg_sid;
+ /* DFE and CTLE */
+ u32 tap1_val[XUSB_SS_PORT_COUNT];
+ u32 amp_val[XUSB_SS_PORT_COUNT];
+ u32 ctle_z_val[XUSB_SS_PORT_COUNT];
+ u32 ctle_g_val[XUSB_SS_PORT_COUNT];
+};
+
+struct tegra_xhci_firmware {
+ void *data; /* kernel virtual address */
+ size_t size; /* firmware size */
+ dma_addr_t dma; /* dma address for controller */
+};
+
+struct tegra_xhci_firmware_log {
+ dma_addr_t phys_addr; /* dma-able address */
+ void *virt_addr; /* kernel va of the shared log buffer */
+ struct log_entry *dequeue; /* current dequeue pointer (va) */
+ struct circ_buf circ; /* big circular buffer */
+ u32 seq; /* log sequence number */
+
+ struct task_struct *thread; /* a thread to consume log */
+ struct mutex mutex;
+ wait_queue_head_t read_wait;
+ wait_queue_head_t write_wait;
+ wait_queue_head_t intr_wait;
+ struct dentry *path;
+ struct dentry *log_file;
+ unsigned long flags;
+};
+
+struct tegra_xhci_hcd {
+ struct platform_device *pdev;
+ struct xhci_hcd *xhci;
+ u16 device_id;
+
+ spinlock_t lock;
+ struct mutex sync_lock;
+
+ int smi_irq;
+ int padctl_irq;
+ int usb3_irq;
+ int usb2_irq;
+
+ bool ss_wake_event;
+ bool ss_pwr_gated;
+ bool host_pwr_gated;
+ bool hs_wake_event;
+ bool host_resume_req;
+ bool lp0_exit;
+ u32 dfe_ctx_saved;
+ u32 ctle_ctx_saved;
+ unsigned long last_jiffies;
+ unsigned long host_phy_base;
+ unsigned long host_phy_size;
+ void __iomem *host_phy_virt_base;
+
+ void __iomem *padctl_base;
+ void __iomem *fpci_base;
+ void __iomem *ipfs_base;
+
+ struct tegra_xusb_platform_data *pdata;
+ struct tegra_xusb_board_data *bdata;
+ struct tegra_xusb_chip_calib *cdata;
+ struct tegra_xusb_padctl_regs *padregs;
+ const struct tegra_xusb_soc_config *soc_config;
+ u64 tegra_xusb_dmamask;
+
+ /* mailbox variables */
+ struct mutex mbox_lock;
+ u32 mbox_owner;
+ u32 cmd_type;
+ u32 cmd_data;
+
+ struct regulator **xusb_utmi_vbus_regs;
+
+ struct regulator *xusb_s1p05v_reg;
+ struct regulator *xusb_s3p3v_reg;
+ struct regulator *xusb_s1p8v_reg;
+ struct regulator *vddio_hsic_reg;
+ int vddio_hsic_refcnt;
+
+ struct work_struct mbox_work;
+ struct work_struct ss_elpg_exit_work;
+ struct work_struct host_elpg_exit_work;
+
+ struct clk *host_clk;
+ struct clk *ss_clk;
+
+ /* XUSB Falcon SuperSpeed Clock */
+ struct clk *falc_clk;
+
+ /* EMC Clock */
+ struct clk *emc_clk;
+ /* XUSB SS PI Clock */
+ struct clk *ss_src_clk;
+ /* PLLE Clock */
+ struct clk *plle_clk;
+ struct clk *pll_u_480M;
+ struct clk *clk_m;
+ /* refPLLE clk */
+ struct clk *pll_re_vco_clk;
+ /*
+ * XUSB/IPFS specific registers these need to be saved/restored in
+ * addition to spec defined registers
+ */
+ struct xusb_save_regs sregs;
+ bool usb2_rh_suspend;
+ bool usb3_rh_suspend;
+ bool hc_in_elpg;
+
+ /* otg transceiver */
+ struct usb_phy *transceiver;
+ struct notifier_block otgnb;
+
+ unsigned long usb2_rh_remote_wakeup_ports; /* one bit per port */
+ unsigned long usb3_rh_remote_wakeup_ports; /* one bit per port */
+ /* firmware loading related */
+ struct tegra_xhci_firmware firmware;
+
+ struct tegra_xhci_firmware_log log;
+ struct device_attribute hsic_power_attr[XUSB_HSIC_COUNT];
+
+ bool init_done;
+};
+
+#define NOT_SUPPORTED 0xFFFFFFFF
+#define PADCTL_REG_NONE 0xffff
+static inline u32 padctl_readl(struct tegra_xhci_hcd *tegra, u32 reg)
+{
+ if (reg == PADCTL_REG_NONE)
+ return PADCTL_REG_NONE;
+ return readl(tegra->padctl_base + reg);
+}
+
+static inline void padctl_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 reg)
+{
+ if (reg == PADCTL_REG_NONE)
+ return;
+ writel(val, tegra->padctl_base + reg);
+}
+
/**
* port_to_hsic_pad - given "port number", return with hsic pad number
* @_port: (zero-based) index to portsc registers array.