Commit 9badec2f authored by Matthijs Kooijman's avatar Matthijs Kooijman Committed by Greg Kroah-Hartman

staging: dwc2: interpret all hwcfg and related register at init time

Before, the hwcfg registers were read at device init time, but
interpreted at various parts in the code. This commit unpacks the hwcfg
register values into a struct with properly labeled variables at init
time, which makes all the other code using these values more consise and
easier to read. Some values that were previously stored in the hsotg
struct are now moved into this new struct as well.

In addition to the hwcfg registers, the contents of some fifo size
registers are also unpacked. The hwcfg registers are read-only, so they
can be safely stored. The fifo size registers are read-write registers,
but their power-on values are significant: they give the maximum depth
of the fifo they describe.

This commit mostly moves code, but also attempts to simplify some
expressions from (val >> shift) & (mask >> shift) to
(val & mask) >> shift.

Finally, all of the parameters read from the hardware are debug printed
after unpacking them, so a bunch of debug prints can be removed from
other places.
Signed-off-by: default avatarMatthijs Kooijman <matthijs@stdin.nl>
Acked-by: default avatarPaul Zimmerman <paulz@synopsys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a1fc5243
This diff is collapsed.
...@@ -193,6 +193,79 @@ struct dwc2_core_params { ...@@ -193,6 +193,79 @@ struct dwc2_core_params {
int ahbcfg; int ahbcfg;
}; };
/**
* struct dwc2_hw_params - Autodetected parameters.
*
* These parameters are the various parameters read from hardware
* registers during initialization. They typically contain the best
* supported or maximum value that can be configured in the
* corresponding dwc2_core_params value.
*
* The values that are not in dwc2_core_params are documented below.
*
* @op_mode Mode of Operation
* 0 - HNP- and SRP-Capable OTG (Host & Device)
* 1 - SRP-Capable OTG (Host & Device)
* 2 - Non-HNP and Non-SRP Capable OTG (Host & Device)
* 3 - SRP-Capable Device
* 4 - Non-OTG Device
* 5 - SRP-Capable Host
* 6 - Non-OTG Host
* @arch Architecture
* 0 - Slave only
* 1 - External DMA
* 2 - Internal DMA
* @power_optimized Are power optimizations enabled?
* @num_dev_ep Number of device endpoints available
* @num_dev_perio_in_ep Number of device periodic IN endpoints
* avaialable
* @dev_token_q_depth Device Mode IN Token Sequence Learning Queue
* Depth
* 0 to 30
* @host_perio_tx_q_depth
* Host Mode Periodic Request Queue Depth
* 2, 4 or 8
* @nperio_tx_q_depth
* Non-Periodic Request Queue Depth
* 2, 4 or 8
* @hs_phy_type High-speed PHY interface type
* 0 - High-speed interface not supported
* 1 - UTMI+
* 2 - ULPI
* 3 - UTMI+ and ULPI
* @fs_phy_type Full-speed PHY interface type
* 0 - Full speed interface not supported
* 1 - Dedicated full speed interface
* 2 - FS pins shared with UTMI+ pins
* 3 - FS pins shared with ULPI pins
* @total_fifo_size: Total internal RAM for FIFOs (bytes)
* @snpsid: Value from SNPSID register
*/
struct dwc2_hw_params {
unsigned op_mode:3;
unsigned arch:2;
unsigned dma_desc_enable:1;
unsigned enable_dynamic_fifo:1;
unsigned en_multiple_tx_fifo:1;
unsigned host_rx_fifo_size:16;
unsigned host_nperio_tx_fifo_size:16;
unsigned host_perio_tx_fifo_size:16;
unsigned nperio_tx_q_depth:3;
unsigned host_perio_tx_q_depth:3;
unsigned dev_token_q_depth:5;
unsigned max_transfer_size:26;
unsigned max_packet_count:11;
unsigned host_channels:4;
unsigned hs_phy_type:2;
unsigned fs_phy_type:2;
unsigned i2c_enable:1;
unsigned num_dev_ep:4;
unsigned num_dev_perio_in_ep:4;
unsigned total_fifo_size:16;
unsigned power_optimized:1;
u32 snpsid;
};
/** /**
* struct dwc2_hsotg - Holds the state of the driver, including the non-periodic * struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
* and periodic schedules * and periodic schedules
...@@ -200,15 +273,8 @@ struct dwc2_core_params { ...@@ -200,15 +273,8 @@ struct dwc2_core_params {
* @dev: The struct device pointer * @dev: The struct device pointer
* @regs: Pointer to controller regs * @regs: Pointer to controller regs
* @core_params: Parameters that define how the core should be configured * @core_params: Parameters that define how the core should be configured
* @hwcfg1: Hardware Configuration - stored here for convenience * @hw_params: Parameters that were autodetected from the
* @hwcfg2: Hardware Configuration - stored here for convenience * hardware registers
* @hwcfg3: Hardware Configuration - stored here for convenience
* @hwcfg4: Hardware Configuration - stored here for convenience
* @hptxfsiz: Hardware Configuration - stored here for convenience
* @snpsid: Value from SNPSID register
* @total_fifo_size: Total internal RAM for FIFOs (bytes)
* @rx_fifo_size: Size of Rx FIFO (bytes)
* @nperio_tx_fifo_size: Size of Non-periodic Tx FIFO (Bytes)
* @op_state: The operational State, during transitions (a_host=> * @op_state: The operational State, during transitions (a_host=>
* a_peripheral and b_device=>b_host) this may not match * a_peripheral and b_device=>b_host) this may not match
* the core, but allows the software to determine * the core, but allows the software to determine
...@@ -296,16 +362,10 @@ struct dwc2_core_params { ...@@ -296,16 +362,10 @@ struct dwc2_core_params {
struct dwc2_hsotg { struct dwc2_hsotg {
struct device *dev; struct device *dev;
void __iomem *regs; void __iomem *regs;
/** Params detected from hardware */
struct dwc2_hw_params hw_params;
/** Params to actually use */
struct dwc2_core_params *core_params; struct dwc2_core_params *core_params;
u32 hwcfg1;
u32 hwcfg2;
u32 hwcfg3;
u32 hwcfg4;
u32 hptxfsiz;
u32 snpsid;
u16 total_fifo_size;
u16 rx_fifo_size;
u16 nperio_tx_fifo_size;
enum usb_otg_state op_state; enum usb_otg_state op_state;
unsigned int queuing_high_bandwidth:1; unsigned int queuing_high_bandwidth:1;
......
...@@ -166,7 +166,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) ...@@ -166,7 +166,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
* WA for 3.00a- HW is not setting cur_mode, even sometimes * WA for 3.00a- HW is not setting cur_mode, even sometimes
* this does not help * this does not help
*/ */
if (hsotg->snpsid >= DWC2_CORE_REV_3_00a) if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)
udelay(100); udelay(100);
if (gotgctl & GOTGCTL_HSTNEGSCS) { if (gotgctl & GOTGCTL_HSTNEGSCS) {
if (dwc2_is_host_mode(hsotg)) { if (dwc2_is_host_mode(hsotg)) {
...@@ -380,7 +380,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) ...@@ -380,7 +380,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, dev_dbg(hsotg->dev,
"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n", "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
!!(dsts & DSTS_SUSPSTS), !!(dsts & DSTS_SUSPSTS),
!!(hsotg->hwcfg4 & GHWCFG4_POWER_OPTIMIZ)); hsotg->hw_params.power_optimized);
} else { } else {
if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) { if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
dev_dbg(hsotg->dev, "a_peripheral->a_host\n"); dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
......
...@@ -2678,7 +2678,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) ...@@ -2678,7 +2678,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
writel(ahbcfg, hsotg->regs + GAHBCFG); writel(ahbcfg, hsotg->regs + GAHBCFG);
writel(0, hsotg->regs + GINTMSK); writel(0, hsotg->regs + GINTMSK);
if (hsotg->snpsid >= DWC2_CORE_REV_3_00a) { if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) {
dctl = readl(hsotg->regs + DCTL); dctl = readl(hsotg->regs + DCTL);
dctl |= DCTL_SFTDISCON; dctl |= DCTL_SFTDISCON;
writel(dctl, hsotg->regs + DCTL); writel(dctl, hsotg->regs + DCTL);
...@@ -2730,80 +2730,22 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, ...@@ -2730,80 +2730,22 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct dwc2_host_chan *channel; struct dwc2_host_chan *channel;
u32 gusbcfg, hcfg; u32 hcfg;
int i, num_channels; int i, num_channels;
int retval = -ENOMEM; int retval;
dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n"); dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n");
/* /* Detect config values from hardware */
* Attempt to ensure this device is really a DWC_otg Controller. retval = dwc2_get_hwparams(hsotg);
* Read and verify the GSNPSID register contents. The value should be
* 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3",
* as in "OTG version 2.xx" or "OTG version 3.xx".
*/
hsotg->snpsid = readl(hsotg->regs + GSNPSID);
if ((hsotg->snpsid & 0xfffff000) != 0x4f542000 &&
(hsotg->snpsid & 0xfffff000) != 0x4f543000) {
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
hsotg->snpsid);
retval = -ENODEV;
goto error1;
}
/* if (retval)
* Store the contents of the hardware configuration registers here for return retval;
* easy access later
*/
hsotg->hwcfg1 = readl(hsotg->regs + GHWCFG1);
hsotg->hwcfg2 = readl(hsotg->regs + GHWCFG2);
hsotg->hwcfg3 = readl(hsotg->regs + GHWCFG3);
hsotg->hwcfg4 = readl(hsotg->regs + GHWCFG4);
dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hsotg->hwcfg1);
dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hsotg->hwcfg2);
dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hsotg->hwcfg3);
dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hsotg->hwcfg4);
/* Force host mode to get HPTXFSIZ exact power on value */
gusbcfg = readl(hsotg->regs + GUSBCFG);
gusbcfg |= GUSBCFG_FORCEHOSTMODE;
writel(gusbcfg, hsotg->regs + GUSBCFG);
usleep_range(100000, 150000);
hsotg->hptxfsiz = readl(hsotg->regs + HPTXFSIZ); retval = -ENOMEM;
dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hsotg->hptxfsiz);
gusbcfg = readl(hsotg->regs + GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
writel(gusbcfg, hsotg->regs + GUSBCFG);
usleep_range(100000, 150000);
hcfg = readl(hsotg->regs + HCFG); hcfg = readl(hsotg->regs + HCFG);
dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);
dev_dbg(hsotg->dev, "op_mode=%0x\n",
hsotg->hwcfg2 >> GHWCFG2_OP_MODE_SHIFT &
GHWCFG2_OP_MODE_MASK >> GHWCFG2_OP_MODE_SHIFT);
dev_dbg(hsotg->dev, "arch=%0x\n",
hsotg->hwcfg2 >> GHWCFG2_ARCHITECTURE_SHIFT &
GHWCFG2_ARCHITECTURE_MASK >> GHWCFG2_ARCHITECTURE_SHIFT);
dev_dbg(hsotg->dev, "num_dev_ep=%d\n",
hsotg->hwcfg2 >> GHWCFG2_NUM_DEV_EP_SHIFT &
GHWCFG2_NUM_DEV_EP_MASK >> GHWCFG2_NUM_DEV_EP_SHIFT);
dev_dbg(hsotg->dev, "max_host_chan=%d\n",
hsotg->hwcfg2 >> GHWCFG2_NUM_HOST_CHAN_SHIFT &
GHWCFG2_NUM_HOST_CHAN_MASK >> GHWCFG2_NUM_HOST_CHAN_SHIFT);
dev_dbg(hsotg->dev, "nonperio_tx_q_depth=0x%0x\n",
hsotg->hwcfg2 >> GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT &
GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK >>
GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT);
dev_dbg(hsotg->dev, "host_perio_tx_q_depth=0x%0x\n",
hsotg->hwcfg2 >> GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT &
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK >>
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT);
dev_dbg(hsotg->dev, "dev_token_q_depth=0x%0x\n",
hsotg->hwcfg2 >> GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT &
GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT);
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) * hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) *
...@@ -2877,10 +2819,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, ...@@ -2877,10 +2819,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
} }
INIT_WORK(&hsotg->wf_otg, dwc2_conn_id_status_change); INIT_WORK(&hsotg->wf_otg, dwc2_conn_id_status_change);
dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x\n",
hsotg->snpsid >> 12 & 0xf, hsotg->snpsid >> 8 & 0xf,
hsotg->snpsid >> 4 & 0xf, hsotg->snpsid & 0xf);
setup_timer(&hsotg->wkp_timer, dwc2_wakeup_detected, setup_timer(&hsotg->wkp_timer, dwc2_wakeup_detected,
(unsigned long)hsotg); (unsigned long)hsotg);
......
...@@ -453,6 +453,7 @@ extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); ...@@ -453,6 +453,7 @@ extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
extern int dwc2_set_parameters(struct dwc2_hsotg *hsotg, extern int dwc2_set_parameters(struct dwc2_hsotg *hsotg,
const struct dwc2_core_params *params); const struct dwc2_core_params *params);
extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
/* Transaction Execution Functions */ /* Transaction Execution Functions */
extern enum dwc2_transaction_type dwc2_hcd_select_transactions( extern enum dwc2_transaction_type dwc2_hcd_select_transactions(
......
...@@ -1759,7 +1759,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, ...@@ -1759,7 +1759,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
* For core with OUT NAK enhancement, the flow for high-speed * For core with OUT NAK enhancement, the flow for high-speed
* CONTROL/BULK OUT is handled a little differently * CONTROL/BULK OUT is handled a little differently
*/ */
if (hsotg->snpsid >= DWC2_CORE_REV_2_71a) { if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_71a) {
if (chan->speed == USB_SPEED_HIGH && !chan->ep_is_in && if (chan->speed == USB_SPEED_HIGH && !chan->ep_is_in &&
(chan->ep_type == USB_ENDPOINT_XFER_CONTROL || (chan->ep_type == USB_ENDPOINT_XFER_CONTROL ||
chan->ep_type == USB_ENDPOINT_XFER_BULK)) { chan->ep_type == USB_ENDPOINT_XFER_BULK)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment