aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/otg.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc3/otg.h')
-rw-r--r--drivers/usb/dwc3/otg.h443
1 files changed, 443 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/otg.h b/drivers/usb/dwc3/otg.h
new file mode 100644
index 00000000000..feac6f59b76
--- /dev/null
+++ b/drivers/usb/dwc3/otg.h
@@ -0,0 +1,443 @@
+/*
+ * Intel Penwell USB OTG transceiver driver
+ * Copyright (C) 2009 - 2010, Intel Corporation.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __DWC3_OTG_H
+#define __DWC3_OTG_H
+
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/compiler.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ulpi.h>
+
+
+struct dwc_device_par {
+ void __iomem *io_addr;
+ int len;
+};
+
+#define DWC3_DEVICE_NAME "dwc3-device"
+#define DWC3_HOST_NAME "dwc3-host"
+#define GADGET_DEVID 1
+#define HOST_DEVID 2
+#define DRIVER_VERSION "0.1"
+
+#ifdef CONFIG_USB_DWC3_OTG_DEBUG
+#define DWC_OTG_DEBUG 1
+#else
+#define DWC_OTG_DEBUG 0
+#endif
+
+#define otg_dbg(d, fmt, args...) \
+ do { if (DWC_OTG_DEBUG) dev_dbg((d)->dev, \
+ "%s(): " fmt , __func__, ## args); } while (0)
+#define otg_vdbg(d, fmt, args...) \
+ do { if (DWC_OTG_DEBUG) dev_dbg((d)->dev, \
+ "%s(): " fmt , __func__, ## args); } while (0)
+#define otg_err(d, fmt, args...) \
+ do { if (DWC_OTG_DEBUG) dev_err((d)->dev, \
+ "%s(): " fmt , __func__, ## args); } while (0)
+#define otg_warn(d, fmt, args...) \
+ do { if (DWC_OTG_DEBUG) dev_warn((d)->dev, \
+ "%s(): " fmt , __func__, ## args); } while (0)
+#define otg_info(d, fmt, args...) \
+ do { if (DWC_OTG_DEBUG) dev_info((d)->dev, \
+ "%s(): " fmt , __func__, ## args); } while (0)
+
+#ifdef DEBUG
+#define otg_write(o, reg, val) do { \
+ otg_dbg(o, "OTG_WRITE: reg=0x%05x, val=0x%08x\n", reg, val); \
+ writel(val, ((void *)((o)->usb2_phy.io_priv)) + reg); \
+ } while (0)
+
+#define otg_read(o, reg) ({ \
+ u32 __r; \
+ __r = readl(((void *)((o)->usb2_phy.io_priv)) + reg); \
+ otg_dbg(o, "OTG_READ: reg=0x%05x, val=0x%08x\n", reg, __r); \
+ __r; \
+ })
+#else
+#define otg_write(o, reg, val) \
+ writel(val, ((void *)((o)->usb2_phy.io_priv)) + reg);
+
+#define otg_read(o, reg) ({ \
+ readl(((void *)((o)->usb2_phy.io_priv)) + reg); \
+ })
+#endif
+
+#define GUSB2PHYCFG0 0xc200
+#define GUSB2PHYCFG_SUS_PHY 0x40
+#define GUSB2PHYCFG_PHYSOFTRST (1 << 31)
+
+#define EXTEND_ULPI_REGISTER_ACCESS_MASK 0xC0
+#define GUSB2PHYACC0 0xc280
+#define GUSB2PHYACC0_DISULPIDRVR (1 << 26)
+#define GUSB2PHYACC0_NEWREGREQ (1 << 25)
+#define GUSB2PHYACC0_VSTSDONE (1 << 24)
+#define GUSB2PHYACC0_VSTSBSY (1 << 23)
+#define GUSB2PHYACC0_REGWR (1 << 22)
+#define GUSB2PHYACC0_REGADDR(v) ((v & 0x3F) << 16)
+#define GUSB2PHYACC0_EXTREGADDR(v) ((v & 0x3F) << 8)
+#define GUSB2PHYACC0_VCTRL(v) ((v & 0xFF) << 8)
+#define GUSB2PHYACC0_REGDATA(v) (v & 0xFF)
+#define GUSB2PHYACC0_REGDATA_MASK 0xFF
+
+#define GUSB3PIPECTL0 0xc2c0
+#define GUSB3PIPECTL_SUS_EN 0x20000
+#define GUSB3PIPE_DISRXDETP3 (1 << 28)
+#define GUSB3PIPECTL_PHYSOFTRST (1 << 31)
+
+#define GHWPARAMS6 0xc158
+#define GHWPARAMS6_SRP_SUPPORT_ENABLED 0x0400
+#define GHWPARAMS6_HNP_SUPPORT_ENABLED 0x0800
+#define GHWPARAMS6_ADP_SUPPORT_ENABLED 0x1000
+
+#define GUCTL 0xC12C
+#define GUCTL_CMDEVADDR (1 << 15)
+
+#define GCTL 0xc110
+#define GCTL_PRT_CAP_DIR 0x3000
+#define GCTL_PRT_CAP_DIR_SHIFT 12
+#define GCTL_PRT_CAP_DIR_HOST 1
+#define GCTL_PRT_CAP_DIR_DEV 2
+#define GCTL_PRT_CAP_DIR_OTG 3
+#define GCTL_GBL_HIBERNATION_EN 0x2
+#define GCTL_CORESOFTRESET (1 << 11)
+
+#define OCFG 0xcc00
+#define OCFG_SRP_CAP 0x01
+#define OCFG_SRP_CAP_SHIFT 0
+#define OCFG_HNP_CAP 0x02
+#define OCFG_HNP_CAP_SHIFT 1
+#define OCFG_OTG_VERSION 0x04
+#define OCFG_OTG_VERSION_SHIFT 2
+
+#define GCTL 0xc110
+#define OCTL 0xcc04
+#define OCTL_HST_SET_HNP_EN 0x01
+#define OCTL_HST_SET_HNP_EN_SHIFT 0
+#define OCTL_DEV_SET_HNP_EN 0x02
+#define OCTL_DEV_SET_HNP_EN_SHIFT 1
+#define OCTL_TERM_SEL_DL_PULSE 0x04
+#define OCTL_TERM_SEL_DL_PULSE_SHIFT 2
+#define OCTL_SES_REQ 0x08
+#define OCTL_SES_REQ_SHIFT 3
+#define OCTL_HNP_REQ 0x10
+#define OCTL_HNP_REQ_SHIFT 4
+#define OCTL_PRT_PWR_CTL 0x20
+#define OCTL_PRT_PWR_CTL_SHIFT 5
+#define OCTL_PERI_MODE 0x40
+#define OCTL_PERI_MODE_SHIFT 6
+
+#define OEVT 0xcc08
+#define OEVT_ERR 0x00000001
+#define OEVT_ERR_SHIFT 0
+#define OEVT_SES_REQ_SCS 0x00000002
+#define OEVT_SES_REQ_SCS_SHIFT 1
+#define OEVT_HST_NEG_SCS 0x00000004
+#define OEVT_HST_NEG_SCS_SHIFT 2
+#define OEVT_B_SES_VLD_EVT 0x00000008
+#define OEVT_B_SES_VLD_EVT_SHIFT 3
+#define OEVT_B_DEV_VBUS_CHNG_EVNT 0x00000100
+#define OEVT_B_DEV_VBUS_CHNG_EVNT_SHIFT 8
+#define OEVT_B_DEV_SES_VLD_DET_EVNT 0x00000200
+#define OEVT_B_DEV_SES_VLD_DET_EVNT_SHIFT 9
+#define OEVT_B_DEV_HNP_CHNG_EVNT 0x00000400
+#define OEVT_B_DEV_HNP_CHNG_EVNT_SHIFT 10
+#define OEVT_B_DEV_B_HOST_END_EVNT 0x00000800
+#define OEVT_B_DEV_B_HOST_END_EVNT_SHIFT 11
+#define OEVT_A_DEV_SESS_END_DET_EVNT 0x00010000
+#define OEVT_A_DEV_SESS_END_DET_EVNT_SHIFT 16
+#define OEVT_A_DEV_SRP_DET_EVNT 0x00020000
+#define OEVT_A_DEV_SRP_DET_EVNT_SHIFT 17
+#define OEVT_A_DEV_HNP_CHNG_EVNT 0x00040000
+#define OEVT_A_DEV_HNP_CHNG_EVNT_SHIFT 18
+#define OEVT_A_DEV_HOST_EVNT 0x00080000
+#define OEVT_A_DEV_HOST_EVNT_SHIFT 19
+#define OEVT_A_DEV_B_DEV_HOST_END_EVNT 0x00100000
+#define OEVT_A_DEV_B_DEV_HOST_END_EVNT_SHIFT 20
+#define OEVT_HOST_ROLE_REQ_INIT_EVNT 0x00400000
+#define OEVT_HOST_ROLE_REQ_INIT_EVNT_SHIFT 22
+#define OEVT_HOST_ROLE_REQ_CONFIRM_EVNT 0x00800000
+#define OEVT_HOST_ROLE_REQ_CONFIRM_EVNT_SHIFT 23
+#define OEVT_CONN_ID_STS_CHNG_EVNT 0x01000000
+#define OEVT_CONN_ID_STS_CHNG_EVNT_SHIFT 24
+#define OEVT_DEV_MOD_EVNT 0x80000000
+#define OEVT_DEV_MOD_EVNT_SHIFT 31
+
+#define OEVTEN 0xcc0c
+
+#define OEVT_ALL (OEVT_CONN_ID_STS_CHNG_EVNT | \
+ OEVT_HOST_ROLE_REQ_INIT_EVNT | \
+ OEVT_HOST_ROLE_REQ_CONFIRM_EVNT | \
+ OEVT_A_DEV_B_DEV_HOST_END_EVNT | \
+ OEVT_A_DEV_HOST_EVNT | \
+ OEVT_A_DEV_HNP_CHNG_EVNT | \
+ OEVT_A_DEV_SRP_DET_EVNT | \
+ OEVT_A_DEV_SESS_END_DET_EVNT | \
+ OEVT_B_DEV_B_HOST_END_EVNT | \
+ OEVT_B_DEV_HNP_CHNG_EVNT | \
+ OEVT_B_DEV_SES_VLD_DET_EVNT | \
+ OEVT_B_DEV_VBUS_CHNG_EVNT)
+
+#define OSTS 0xcc10
+#define OSTS_CONN_ID_STS 0x0001
+#define OSTS_CONN_ID_STS_SHIFT 0
+#define OSTS_A_SES_VLD 0x0002
+#define OSTS_A_SES_VLD_SHIFT 1
+#define OSTS_B_SES_VLD 0x0004
+#define OSTS_B_SES_VLD_SHIFT 2
+#define OSTS_XHCI_PRT_PWR 0x0008
+#define OSTS_XHCI_PRT_PWR_SHIFT 3
+#define OSTS_PERIP_MODE 0x0010
+#define OSTS_PERIP_MODE_SHIFT 4
+#define OSTS_OTG_STATES 0x0f00
+#define OSTS_OTG_STATE_SHIFT 8
+
+#define ADPCFG 0xcc20
+#define ADPCFG_PRB_DSCHGS 0x0c000000
+#define ADPCFG_PRB_DSCHG_SHIFT 26
+#define ADPCFG_PRB_DELTAS 0x30000000
+#define ADPCFG_PRB_DELTA_SHIFT 28
+#define ADPCFG_PRB_PERS 0xc0000000
+#define ADPCFG_PRB_PER_SHIFT 30
+
+#define ADPCTL 0xcc24
+#define ADPCTL_WB 0x01000000
+#define ADPCTL_WB_SHIFT 24
+#define ADPCTL_ADP_RES 0x02000000
+#define ADPCTL_ADP_RES_SHIFT 25
+#define ADPCTL_ADP_EN 0x04000000
+#define ADPCTL_ADP_EN_SHIFT 26
+#define ADPCTL_ENA_SNS 0x08000000
+#define ADPCTL_ENA_SNS_SHIFT 27
+#define ADPCTL_ENA_PRB 0x10000000
+#define ADPCTL_ENA_PRB_SHIFT 28
+
+#define ADPEVT 0xcc28
+#define ADPEVT_RTIM_EVNTS 0x000007ff
+#define ADPEVT_RTIM_EVNT_SHIFT 0
+#define ADPEVT_ADP_RST_CMPLT_EVNT 0x02000000
+#define ADPEVT_ADP_RST_CMPLT_EVNT_SHIFT 25
+#define ADPEVT_ADP_TMOUT_EVNT 0x04000000
+#define ADPEVT_ADP_TMOUT_EVNT_SHIFT 26
+#define ADPEVT_ADP_SNS_EVNT 0x08000000
+#define ADPEVT_ADP_SNS_EVNT_SHIFT 27
+#define ADPEVT_ADP_PRB_EVNT 0x10000000
+#define ADPEVT_ADP_PRB_EVNT_SHIFT 28
+
+#define ADPEVTEN 0xcc2c
+#define ADPEVTEN_ACC_DONE_EN 0x01000000
+#define ADPEVTEN_ACC_DONE_EN_SHIFT 24
+#define ADPEVTEN_ADP_RST_CMPLT_EVNT_EN 0x02000000
+#define ADPEVTEN_ADP_RST_CMPLT_EVNT_EN_SHIFT 25
+#define ADPEVTEN_ADP_TMOUT_EVNT_EN 0x04000000
+#define ADPEVTEN_ADP_TMOUT_EVNT_EN_SHIFT 26
+#define ADPEVTEN_ADP_SNS_EVNT_EN 0x08000000
+#define ADPEVTEN_ADP_SNS_EVNT_EN_SHIFT 27
+#define ADPEVTEN_ADP_PRB_EVNT_EN 0x10000000
+#define ADPEVTEN_ADP_PRB_EVNT_EN_SHIFT 28
+
+
+/* charger defined in BC 1.2 */
+enum usb_charger_type {
+ CHRG_UNKNOWN,
+ CHRG_SDP, /* Standard Downstream Port */
+ CHRG_CDP, /* Charging Downstream Port */
+ CHRG_DCP, /* Dedicated Charging Port */
+ CHRG_ACA, /* Accessory Charger Adapter */
+ CHRG_ACA_DOCK, /* Accessory Charger Adapter - Dock */
+ CHRG_ACA_A, /* Accessory Charger Adapter - RID_A */
+ CHRG_ACA_B, /* Accessory Charger Adapter - RID_B */
+ CHRG_ACA_C, /* Accessory Charger Adapter - RID_C */
+ CHRG_SE1, /* SE1 (Apple)*/
+ CHRG_MHL, /* Moblie High-Definition Link */
+ B_DEVICE /* Normal B Device */
+};
+
+#define RID_A 0x01
+#define RID_B 0x02
+#define RID_C 0x03
+#define RID_FLOAT 0x04
+#define RID_GND 0x05
+#define RID_UNKNOWN 0x00
+
+enum usb_charger_state {
+ OTG_CHR_STATE_CONNECTED, /* charger is connected */
+ OTG_CHR_STATE_DISCONNECTED, /* USB port is disconnected */
+ OTG_CHR_STATE_SUSPENDED, /* PORT goes to suspend */
+ OTG_CHR_STATE_HOST, /* USB in host mode */
+};
+
+struct otg_bc_cap {
+ enum usb_charger_type chrg_type;
+ enum usb_charger_state chrg_state;
+ unsigned int ma;
+};
+
+/** The states for the OTG driver */
+enum dwc_otg_state {
+ DWC_STATE_INVALID = -1,
+
+ /** The initial state, check the connector
+ * id status and determine what mode
+ * (A-device or B-device) to operate in. */
+ DWC_STATE_B_IDLE = 0,
+
+ /* A-Host states */
+ DWC_STATE_A_PROBE,
+ DWC_STATE_A_HOST,
+ DWC_STATE_A_HNP_INIT,
+
+ /* A-Peripheral states */
+ DWC_STATE_A_PERIPHERAL,
+
+ /* B-Peripheral states */
+ DWC_STATE_B_SENSE,
+ DWC_STATE_B_PROBE,
+ DWC_STATE_B_PERIPHERAL,
+ DWC_STATE_B_HNP_INIT,
+
+ /* B-Host states */
+ DWC_STATE_B_HOST,
+
+ /* RSP */
+ DWC_STATE_B_RSP_INIT,
+
+ /* USB charger detection */
+ DWC_STATE_CHARGER_DETECTION,
+
+ /* VBUS */
+ DWC_STATE_WAIT_VBUS_RAISE,
+ DWC_STATE_WAIT_VBUS_FALL,
+
+ /* Charging*/
+ DWC_STATE_CHARGING,
+
+ /* Exit */
+ DWC_STATE_EXIT,
+ DWC_STATE_TERMINATED
+};
+
+/** The main structure to keep track of OTG driver state. */
+struct dwc_otg2 {
+ /** OTG transceiver */
+ struct usb_otg otg;
+ struct usb_phy usb2_phy;
+ struct usb_phy usb3_phy;
+ struct device *dev;
+ int irqnum;
+
+ int main_wakeup_needed;
+ struct task_struct *main_thread;
+ wait_queue_head_t main_wq;
+
+ spinlock_t lock;
+
+ /* Events */
+ u32 otg_events;
+ u32 user_events;
+
+ /** User space ID switch event */
+#define USER_ID_A_CHANGE_EVENT 0x01
+#define USER_ID_B_CHANGE_EVENT 0x02
+
+ /* States */
+ enum dwc_otg_state prev;
+ enum dwc_otg_state state;
+ struct platform_device *host;
+ struct platform_device *gadget;
+
+ /* Charger detection */
+ struct otg_bc_cap charging_cap;
+ struct notifier_block nb;
+
+ /* Interfaces between host/device driver */
+ int (*start_host) (struct usb_hcd *hcd);
+ int (*stop_host) (struct usb_hcd *hcd);
+ int (*start_device)(struct usb_gadget *);
+ int (*stop_device)(struct usb_gadget *);
+ int (*vbus_draw) (struct usb_gadget *, unsigned ma);
+
+ /* Vendor driver private date */
+ void *otg_data;
+};
+
+#define sleep_main_thread_until_condition_timeout(otg, condition, msecs) ({ \
+ int __timeout = msecs; \
+ while (!(condition)) { \
+ otg_dbg(otg, " ... sleeping for %d\n", __timeout); \
+ __timeout = sleep_main_thread_timeout(otg, __timeout); \
+ if (__timeout <= 0) { \
+ break; \
+ } \
+ } \
+ __timeout; \
+ })
+
+#define sleep_main_thread_until_condition(otg, condition) ({ \
+ int __rc = 0; \
+ do { \
+ __rc = sleep_main_thread_until_condition_timeout(otg, \
+ condition, 50000); \
+ } while (__rc == 0); \
+ __rc; \
+ })
+
+#define VBUS_TIMEOUT 300
+#define PCI_DEVICE_ID_DWC 0x119E
+
+enum dwc3_otg_mode {
+ DWC3_DEVICE_ONLY,
+ DWC3_HOST_ONLY,
+ DWC3_DRD,
+};
+
+enum driver_bus_type {
+ DWC3_PLAT,
+ DWC3_PCI,
+};
+
+struct dwc3_otg_hw_ops {
+ enum dwc3_otg_mode mode;
+ enum driver_bus_type bus;
+
+ int (*set_power)(struct usb_phy *_otg, unsigned ma);
+ int (*platform_init)(struct dwc_otg2 *otg);
+ int (*otg_notifier_handler)(struct notifier_block *nb,
+ unsigned long event, void *data);
+ int (*prepare_start_peripheral)(struct dwc_otg2 *otg);
+ int (*prepare_start_host)(struct dwc_otg2 *otg);
+ int (*after_stop_peripheral)(struct dwc_otg2 *otg);
+ int (*after_stop_host)(struct dwc_otg2 *otg);
+ int (*b_idle)(struct dwc_otg2 *otg);
+ int (*do_charging)(struct dwc_otg2 *otg);
+ int (*notify_charger_type)(struct dwc_otg2 *otg,
+ enum usb_charger_state state);
+ enum usb_charger_type (*get_charger_type)(struct dwc_otg2 *otg);
+ int (*enable_vbus)(struct dwc_otg2 *otg, int enable);
+ int (*get_id)(struct dwc_otg2 *otg);
+};
+
+void dwc3_wakeup_otg_thread(struct dwc_otg2 *otg);
+struct dwc_otg2 *dwc3_get_otg(void);
+int dwc3_otg_register(struct dwc3_otg_hw_ops *pdata);
+int dwc3_otg_unregister(struct dwc3_otg_hw_ops *pdata);
+#endif /* __DWC3_OTG_H */