summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/usb/dwc2/core.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/usb/dwc2/core.h')
-rw-r--r--kernel/drivers/usb/dwc2/core.h224
1 files changed, 177 insertions, 47 deletions
diff --git a/kernel/drivers/usb/dwc2/core.h b/kernel/drivers/usb/dwc2/core.h
index 836c012c7..a66d3cb62 100644
--- a/kernel/drivers/usb/dwc2/core.h
+++ b/kernel/drivers/usb/dwc2/core.h
@@ -44,22 +44,38 @@
#include <linux/usb/phy.h>
#include "hw.h"
-#ifdef DWC2_LOG_WRITES
-static inline void do_write(u32 value, void *addr)
+static inline u32 dwc2_readl(const void __iomem *addr)
{
- writel(value, addr);
- pr_info("INFO:: wrote %08x to %p\n", value, addr);
+ u32 value = __raw_readl(addr);
+
+ /* In order to preserve endianness __raw_* operation is used. Therefore
+ * a barrier is needed to ensure IO access is not re-ordered across
+ * reads or writes
+ */
+ mb();
+ return value;
}
-#undef writel
-#define writel(v, a) do_write(v, a)
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+ __raw_writel(value, addr);
+
+ /*
+ * In order to preserve endianness __raw_* operation is used. Therefore
+ * a barrier is needed to ensure IO access is not re-ordered across
+ * reads or writes
+ */
+ mb();
+#ifdef DWC2_LOG_WRITES
+ pr_info("INFO:: wrote %08x to %p\n", value, addr);
#endif
+}
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
-/* s3c-hsotg declarations */
-static const char * const s3c_hsotg_supply_names[] = {
+/* dwc2-hsotg declarations */
+static const char * const dwc2_hsotg_supply_names[] = {
"vusb_d", /* digital USB supply, 1.2V */
"vusb_a", /* analog USB supply, 1.1V */
};
@@ -85,10 +101,10 @@ static const char * const s3c_hsotg_supply_names[] = {
#define EP0_MPS_LIMIT 64
struct dwc2_hsotg;
-struct s3c_hsotg_req;
+struct dwc2_hsotg_req;
/**
- * struct s3c_hsotg_ep - driver endpoint definition.
+ * struct dwc2_hsotg_ep - driver endpoint definition.
* @ep: The gadget layer representation of the endpoint.
* @name: The driver generated name for the endpoint.
* @queue: Queue of requests for this endpoint.
@@ -127,11 +143,11 @@ struct s3c_hsotg_req;
* as in shared-fifo mode periodic in acts like a single-frame packet
* buffer than a fifo)
*/
-struct s3c_hsotg_ep {
+struct dwc2_hsotg_ep {
struct usb_ep ep;
struct list_head queue;
struct dwc2_hsotg *parent;
- struct s3c_hsotg_req *req;
+ struct dwc2_hsotg_req *req;
struct dentry *debugfs;
unsigned long total_data;
@@ -150,17 +166,18 @@ struct s3c_hsotg_ep {
unsigned int periodic:1;
unsigned int isochronous:1;
unsigned int send_zlp:1;
+ unsigned int has_correct_parity:1;
char name[10];
};
/**
- * struct s3c_hsotg_req - data transfer request
+ * struct dwc2_hsotg_req - data transfer request
* @req: The USB gadget request
* @queue: The list of requests for the endpoint this is queued for.
* @saved_req_buf: variable to save req.buf when bounce buffers are used.
*/
-struct s3c_hsotg_req {
+struct dwc2_hsotg_req {
struct usb_request req;
struct list_head queue;
void *saved_req_buf;
@@ -331,6 +348,17 @@ enum dwc2_ep0_state {
* by the driver and are ignored in this
* configuration value.
* @uframe_sched: True to enable the microframe scheduler
+ * @external_id_pin_ctl: Specifies whether ID pin is handled externally.
+ * Disable CONIDSTSCHNG controller interrupt in such
+ * case.
+ * 0 - No (default)
+ * 1 - Yes
+ * @hibernation: Specifies whether the controller support hibernation.
+ * If hibernation is enabled, the controller will enter
+ * hibernation in both peripheral and host mode when
+ * needed.
+ * 0 - No (default)
+ * 1 - Yes
*
* The following parameters may be specified when starting the module. These
* parameters define how the DWC_otg controller should be configured. A
@@ -368,6 +396,8 @@ struct dwc2_core_params {
int reload_ctl;
int ahbcfg;
int uframe_sched;
+ int external_id_pin_ctl;
+ int hibernation;
};
/**
@@ -452,6 +482,85 @@ struct dwc2_hw_params {
#define DWC2_CTRL_BUFF_SIZE 8
/**
+ * struct dwc2_gregs_backup - Holds global registers state before entering partial
+ * power down
+ * @gotgctl: Backup of GOTGCTL register
+ * @gintmsk: Backup of GINTMSK register
+ * @gahbcfg: Backup of GAHBCFG register
+ * @gusbcfg: Backup of GUSBCFG register
+ * @grxfsiz: Backup of GRXFSIZ register
+ * @gnptxfsiz: Backup of GNPTXFSIZ register
+ * @gi2cctl: Backup of GI2CCTL register
+ * @hptxfsiz: Backup of HPTXFSIZ register
+ * @gdfifocfg: Backup of GDFIFOCFG register
+ * @dtxfsiz: Backup of DTXFSIZ registers for each endpoint
+ * @gpwrdn: Backup of GPWRDN register
+ */
+struct dwc2_gregs_backup {
+ u32 gotgctl;
+ u32 gintmsk;
+ u32 gahbcfg;
+ u32 gusbcfg;
+ u32 grxfsiz;
+ u32 gnptxfsiz;
+ u32 gi2cctl;
+ u32 hptxfsiz;
+ u32 pcgcctl;
+ u32 gdfifocfg;
+ u32 dtxfsiz[MAX_EPS_CHANNELS];
+ u32 gpwrdn;
+ bool valid;
+};
+
+/**
+ * struct dwc2_dregs_backup - Holds device registers state before entering partial
+ * power down
+ * @dcfg: Backup of DCFG register
+ * @dctl: Backup of DCTL register
+ * @daintmsk: Backup of DAINTMSK register
+ * @diepmsk: Backup of DIEPMSK register
+ * @doepmsk: Backup of DOEPMSK register
+ * @diepctl: Backup of DIEPCTL register
+ * @dieptsiz: Backup of DIEPTSIZ register
+ * @diepdma: Backup of DIEPDMA register
+ * @doepctl: Backup of DOEPCTL register
+ * @doeptsiz: Backup of DOEPTSIZ register
+ * @doepdma: Backup of DOEPDMA register
+ */
+struct dwc2_dregs_backup {
+ u32 dcfg;
+ u32 dctl;
+ u32 daintmsk;
+ u32 diepmsk;
+ u32 doepmsk;
+ u32 diepctl[MAX_EPS_CHANNELS];
+ u32 dieptsiz[MAX_EPS_CHANNELS];
+ u32 diepdma[MAX_EPS_CHANNELS];
+ u32 doepctl[MAX_EPS_CHANNELS];
+ u32 doeptsiz[MAX_EPS_CHANNELS];
+ u32 doepdma[MAX_EPS_CHANNELS];
+ bool valid;
+};
+
+/**
+ * struct dwc2_hregs_backup - Holds host registers state before entering partial
+ * power down
+ * @hcfg: Backup of HCFG register
+ * @haintmsk: Backup of HAINTMSK register
+ * @hcintmsk: Backup of HCINTMSK register
+ * @hptr0: Backup of HPTR0 register
+ * @hfir: Backup of HFIR register
+ */
+struct dwc2_hregs_backup {
+ u32 hcfg;
+ u32 haintmsk;
+ u32 hcintmsk[MAX_EPS_CHANNELS];
+ u32 hprt0;
+ u32 hfir;
+ bool valid;
+};
+
+/**
* struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
* and periodic schedules
*
@@ -470,6 +579,15 @@ struct dwc2_hw_params {
* - USB_DR_MODE_PERIPHERAL
* - USB_DR_MODE_HOST
* - USB_DR_MODE_OTG
+ * @hcd_enabled Host mode sub-driver initialization indicator.
+ * @gadget_enabled Peripheral mode sub-driver initialization indicator.
+ * @ll_hw_enabled Status of low-level hardware resources.
+ * @phy: The otg phy transceiver structure for phy control.
+ * @uphy: The otg phy transceiver structure for old USB phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
+ * @supplies: Definition of USB power supplies
+ * @phyif: PHY interface width
* @lock: Spinlock that protects all the driver data structures
* @priv: Stores a pointer to the struct usb_hcd
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
@@ -481,6 +599,9 @@ struct dwc2_hw_params {
* interrupt
* @wkp_timer: Timer object for handling Wakeup Detected interrupt
* @lx_state: Lx state of connected device
+ * @gregs_backup: Backup of global registers during suspend
+ * @dregs_backup: Backup of device registers during suspend
+ * @hregs_backup: Backup of host registers during suspend
*
* These are for host mode:
*
@@ -559,12 +680,6 @@ struct dwc2_hw_params {
* These are for peripheral mode:
*
* @driver: USB gadget driver
- * @phy: The otg phy transceiver structure for phy control.
- * @uphy: The otg phy transceiver structure for old USB phy control.
- * @plat: The platform specific configuration data. This can be removed once
- * all SoCs support usb transceiver.
- * @supplies: Definition of USB power supplies
- * @phyif: PHY interface width
* @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
* @num_of_eps: Number of available EPs (excluding EP0)
* @debug_root: Root directrory for debugfs.
@@ -577,7 +692,6 @@ struct dwc2_hw_params {
* @ctrl_req: Request for EP0 control packets.
* @ep0_state: EP0 control transfers state
* @test_mode: USB test mode requested by the host
- * @last_rst: Time of last reset
* @eps: The endpoints being supplied to the gadget framework
* @g_using_dma: Indicate if dma usage is enabled
* @g_rx_fifo_sz: Contains rx fifo size value
@@ -595,13 +709,15 @@ struct dwc2_hsotg {
enum usb_dr_mode dr_mode;
unsigned int hcd_enabled:1;
unsigned int gadget_enabled:1;
+ unsigned int ll_hw_enabled:1;
struct phy *phy;
struct usb_phy *uphy;
- struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+ struct dwc2_hsotg_plat *plat;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)];
+ u32 phyif;
spinlock_t lock;
- struct mutex init_mutex;
void *priv;
int irq;
struct clk *clk;
@@ -613,11 +729,12 @@ struct dwc2_hsotg {
struct work_struct wf_otg;
struct timer_list wkp_timer;
enum dwc2_lx_state lx_state;
+ struct dwc2_gregs_backup gr_backup;
+ struct dwc2_dregs_backup dr_backup;
+ struct dwc2_hregs_backup hr_backup;
struct dentry *debug_root;
- struct dentry *debug_file;
- struct dentry *debug_testmode;
- struct dentry *debug_fifo;
+ struct debugfs_regset32 *regset;
/* DWC OTG HW Release versions */
#define DWC2_CORE_REV_2_71a 0x4f54271a
@@ -652,6 +769,7 @@ struct dwc2_hsotg {
u16 frame_usecs[8];
u16 frame_number;
u16 periodic_qh_count;
+ bool bus_suspended;
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
#define FRAME_NUM_ARRAY_SIZE 1000
@@ -700,9 +818,6 @@ struct dwc2_hsotg {
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
/* Gadget structures */
struct usb_gadget_driver *driver;
- struct s3c_hsotg_plat *plat;
-
- u32 phyif;
int fifo_mem;
unsigned int dedicated_fifos:1;
unsigned char num_of_eps;
@@ -718,9 +833,8 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
- unsigned long last_rst;
- struct s3c_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
- struct s3c_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
+ struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
+ struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
u32 g_rx_fifo_sz;
u32 g_np_g_tx_fifo_sz;
@@ -751,6 +865,8 @@ enum dwc2_halt_status {
* and the DWC_otg controller
*/
extern void dwc2_core_host_init(struct dwc2_hsotg *hsotg);
+extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
+extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
/*
* Host core Functions.
@@ -983,6 +1099,16 @@ extern void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val);
extern void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val);
+extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
+ const struct dwc2_core_params *params);
+
+extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
+
+extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
+
+extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg);
+extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg);
+
/*
* Dump core registers and SPRAM
*/
@@ -997,27 +1123,33 @@ extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
/* Gadget defines */
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
-extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
-extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
-extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg);
+extern int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2);
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
-extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+extern void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset);
-extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
-extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2);
+extern void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg);
+extern void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
+#define dwc2_is_device_connected(hsotg) (hsotg->connected)
#else
-static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
-static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2)
{ return 0; }
-static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
-static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
bool reset) {}
-static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
-static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
+static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
+static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
+ int testmode)
+{ return 0; }
+#define dwc2_is_device_connected(hsotg) (0)
#endif
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
@@ -1025,14 +1157,12 @@ extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
#else
-static inline void dwc2_set_all_params(struct dwc2_core_params *params, int value) {}
static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
-static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
- const struct dwc2_core_params *params)
+static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
#endif