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
...@@ -90,14 +90,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) ...@@ -90,14 +90,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
*/ */
static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
{ {
u32 hs_phy_type = (hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >>
GHWCFG2_HS_PHY_TYPE_SHIFT;
u32 fs_phy_type = (hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
u32 hcfg, val; u32 hcfg, val;
if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->core_params->ulpi_fs_ls > 0) || hsotg->core_params->ulpi_fs_ls > 0) ||
hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* Full speed PHY */ /* Full speed PHY */
...@@ -247,7 +243,7 @@ static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) ...@@ -247,7 +243,7 @@ static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
{ {
u32 usbcfg, hs_phy_type, fs_phy_type; u32 usbcfg;
if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL && if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL &&
hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
...@@ -258,13 +254,8 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) ...@@ -258,13 +254,8 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
dwc2_hs_phy_init(hsotg, select_phy); dwc2_hs_phy_init(hsotg, select_phy);
} }
hs_phy_type = (hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >> if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
GHWCFG2_HS_PHY_TYPE_SHIFT; hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
fs_phy_type = (hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->core_params->ulpi_fs_ls > 0) { hsotg->core_params->ulpi_fs_ls > 0) {
dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
usbcfg = readl(hsotg->regs + GUSBCFG); usbcfg = readl(hsotg->regs + GUSBCFG);
...@@ -283,8 +274,7 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) ...@@ -283,8 +274,7 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
{ {
u32 ahbcfg = readl(hsotg->regs + GAHBCFG); u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
switch ((hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >> switch (hsotg->hw_params.arch) {
GHWCFG2_ARCHITECTURE_SHIFT) {
case GHWCFG2_EXT_DMA_ARCH: case GHWCFG2_EXT_DMA_ARCH:
dev_err(hsotg->dev, "External DMA Mode not supported\n"); dev_err(hsotg->dev, "External DMA Mode not supported\n");
return -EINVAL; return -EINVAL;
...@@ -333,8 +323,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) ...@@ -333,8 +323,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
usbcfg = readl(hsotg->regs + GUSBCFG); usbcfg = readl(hsotg->regs + GUSBCFG);
usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP); usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP);
switch ((hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK) >> switch (hsotg->hw_params.op_mode) {
GHWCFG2_OP_MODE_SHIFT) {
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
if (hsotg->core_params->otg_cap == if (hsotg->core_params->otg_cap ==
DWC2_CAP_PARAM_HNP_SRP_CAPABLE) DWC2_CAP_PARAM_HNP_SRP_CAPABLE)
...@@ -395,23 +384,6 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) ...@@ -395,23 +384,6 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
/* Reset the Controller */ /* Reset the Controller */
dwc2_core_reset(hsotg); dwc2_core_reset(hsotg);
dev_dbg(hsotg->dev, "num_dev_perio_in_ep=%d\n",
hsotg->hwcfg4 >> GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT &
GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK >>
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT);
hsotg->total_fifo_size = hsotg->hwcfg3 >> GHWCFG3_DFIFO_DEPTH_SHIFT &
GHWCFG3_DFIFO_DEPTH_MASK >> GHWCFG3_DFIFO_DEPTH_SHIFT;
hsotg->rx_fifo_size = (readl(hsotg->regs + GRXFSIZ) &
GRXFSIZ_DEPTH_MASK) >>
GRXFSIZ_DEPTH_SHIFT;
hsotg->nperio_tx_fifo_size =
readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff;
dev_dbg(hsotg->dev, "Total FIFO SZ=%d\n", hsotg->total_fifo_size);
dev_dbg(hsotg->dev, "RxFIFO SZ=%d\n", hsotg->rx_fifo_size);
dev_dbg(hsotg->dev, "NP TxFIFO SZ=%d\n", hsotg->nperio_tx_fifo_size);
/* /*
* This needs to happen in FS mode before any other programming occurs * This needs to happen in FS mode before any other programming occurs
*/ */
...@@ -514,13 +486,6 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) ...@@ -514,13 +486,6 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
if (!params->enable_dynamic_fifo) if (!params->enable_dynamic_fifo)
return; return;
dev_dbg(hsotg->dev, "Total FIFO Size=%d\n", hsotg->total_fifo_size);
dev_dbg(hsotg->dev, "Rx FIFO Size=%d\n", params->host_rx_fifo_size);
dev_dbg(hsotg->dev, "NP Tx FIFO Size=%d\n",
params->host_nperio_tx_fifo_size);
dev_dbg(hsotg->dev, "P Tx FIFO Size=%d\n",
params->host_perio_tx_fifo_size);
/* Rx FIFO */ /* Rx FIFO */
grxfsiz = readl(hsotg->regs + GRXFSIZ); grxfsiz = readl(hsotg->regs + GRXFSIZ);
dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz); dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz);
...@@ -554,7 +519,7 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) ...@@ -554,7 +519,7 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
readl(hsotg->regs + HPTXFSIZ)); readl(hsotg->regs + HPTXFSIZ));
if (hsotg->core_params->en_multiple_tx_fifo > 0 && if (hsotg->core_params->en_multiple_tx_fifo > 0 &&
hsotg->snpsid <= DWC2_CORE_REV_2_94a) { hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) {
/* /*
* Global DFIFOCFG calculation for Host mode - * Global DFIFOCFG calculation for Host mode -
* include RxFIFO, NPTXFIFO and HPTXFIFO * include RxFIFO, NPTXFIFO and HPTXFIFO
...@@ -609,11 +574,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) ...@@ -609,11 +574,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
} }
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->core_params->dma_desc_enable > 0) {
u32 op_mode = (hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK) >> u32 op_mode = hsotg->hw_params.op_mode;
GHWCFG2_OP_MODE_SHIFT; if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a ||
!hsotg->hw_params.dma_desc_enable ||
if (hsotg->snpsid < DWC2_CORE_REV_2_90a ||
!(hsotg->hwcfg4 & GHWCFG4_DESC_DMA) ||
op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE || op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE ||
op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE || op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE ||
op_mode == GHWCFG2_OP_MODE_UNDEFINED) { op_mode == GHWCFG2_OP_MODE_UNDEFINED) {
...@@ -1659,19 +1622,16 @@ void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) ...@@ -1659,19 +1622,16 @@ void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg)
{ {
u32 usbcfg; u32 usbcfg;
u32 hwcfg2;
u32 hprt0; u32 hprt0;
int clock = 60; /* default value */ int clock = 60; /* default value */
usbcfg = readl(hsotg->regs + GUSBCFG); usbcfg = readl(hsotg->regs + GUSBCFG);
hwcfg2 = readl(hsotg->regs + GHWCFG2);
hprt0 = readl(hsotg->regs + HPRT0); hprt0 = readl(hsotg->regs + HPRT0);
if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) && if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) &&
!(usbcfg & GUSBCFG_PHYIF16)) !(usbcfg & GUSBCFG_PHYIF16))
clock = 60; clock = 60;
if ((usbcfg & GUSBCFG_PHYSEL) && if ((usbcfg & GUSBCFG_PHYSEL) && hsotg->hw_params.fs_phy_type ==
(hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >> GHWCFG2_FS_PHY_TYPE_SHIFT ==
GHWCFG2_FS_PHY_TYPE_SHARED_ULPI) GHWCFG2_FS_PHY_TYPE_SHARED_ULPI)
clock = 48; clock = 48;
if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) && if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) &&
...@@ -1684,12 +1644,10 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) ...@@ -1684,12 +1644,10 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg)
!(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16)) !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16))
clock = 48; clock = 48;
if ((usbcfg & GUSBCFG_PHYSEL) && !(usbcfg & GUSBCFG_PHYIF16) && if ((usbcfg & GUSBCFG_PHYSEL) && !(usbcfg & GUSBCFG_PHYIF16) &&
(hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >> GHWCFG2_FS_PHY_TYPE_SHIFT == hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_SHARED_UTMI)
GHWCFG2_FS_PHY_TYPE_SHARED_UTMI)
clock = 48; clock = 48;
if ((usbcfg & GUSBCFG_PHYSEL) && if ((usbcfg & GUSBCFG_PHYSEL) &&
(hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >> GHWCFG2_FS_PHY_TYPE_SHIFT == hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED)
GHWCFG2_FS_PHY_TYPE_DEDICATED)
clock = 48; clock = 48;
if ((hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT == HPRT0_SPD_HIGH_SPEED) if ((hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT == HPRT0_SPD_HIGH_SPEED)
...@@ -1961,18 +1919,14 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) ...@@ -1961,18 +1919,14 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val)
{ {
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
u32 op_mode;
op_mode = (hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK) >>
GHWCFG2_OP_MODE_SHIFT;
switch (val) { switch (val) {
case DWC2_CAP_PARAM_HNP_SRP_CAPABLE: case DWC2_CAP_PARAM_HNP_SRP_CAPABLE:
if (op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE)
valid = 0; valid = 0;
break; break;
case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE: case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE:
switch (op_mode) { switch (hsotg->hw_params.op_mode) {
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
...@@ -1996,7 +1950,7 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) ...@@ -1996,7 +1950,7 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for otg_cap parameter. Check HW configuration.\n", "%d invalid for otg_cap parameter. Check HW configuration.\n",
val); val);
switch (op_mode) { switch (hsotg->hw_params.op_mode) {
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE; val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE;
break; break;
...@@ -2022,8 +1976,7 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2022,8 +1976,7 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val)
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
if (val > 0 && (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >> if (val > 0 && hsotg->hw_params.arch == GHWCFG2_SLAVE_ONLY_ARCH)
GHWCFG2_ARCHITECTURE_SHIFT == GHWCFG2_SLAVE_ONLY_ARCH)
valid = 0; valid = 0;
if (val < 0) if (val < 0)
valid = 0; valid = 0;
...@@ -2033,8 +1986,7 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2033,8 +1986,7 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for dma_enable parameter. Check HW configuration.\n", "%d invalid for dma_enable parameter. Check HW configuration.\n",
val); val);
val = (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >> val = hsotg->hw_params.arch != GHWCFG2_SLAVE_ONLY_ARCH;
GHWCFG2_ARCHITECTURE_SHIFT != GHWCFG2_SLAVE_ONLY_ARCH;
dev_dbg(hsotg->dev, "Setting dma_enable to %d\n", val); dev_dbg(hsotg->dev, "Setting dma_enable to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2049,7 +2001,7 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2049,7 +2001,7 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val)
int retval = 0; int retval = 0;
if (val > 0 && (hsotg->core_params->dma_enable <= 0 || if (val > 0 && (hsotg->core_params->dma_enable <= 0 ||
!(hsotg->hwcfg4 & GHWCFG4_DESC_DMA))) !hsotg->hw_params.dma_desc_enable))
valid = 0; valid = 0;
if (val < 0) if (val < 0)
valid = 0; valid = 0;
...@@ -2060,7 +2012,7 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2060,7 +2012,7 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val)
"%d invalid for dma_desc_enable parameter. Check HW configuration.\n", "%d invalid for dma_desc_enable parameter. Check HW configuration.\n",
val); val);
val = (hsotg->core_params->dma_enable > 0 && val = (hsotg->core_params->dma_enable > 0 &&
(hsotg->hwcfg4 & GHWCFG4_DESC_DMA)); hsotg->hw_params.dma_desc_enable);
dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val); dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2096,7 +2048,7 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) ...@@ -2096,7 +2048,7 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val)
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
if (val > 0 && !(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO)) if (val > 0 && !hsotg->hw_params.enable_dynamic_fifo)
valid = 0; valid = 0;
if (val < 0) if (val < 0)
valid = 0; valid = 0;
...@@ -2106,7 +2058,7 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) ...@@ -2106,7 +2058,7 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for enable_dynamic_fifo parameter. Check HW configuration.\n", "%d invalid for enable_dynamic_fifo parameter. Check HW configuration.\n",
val); val);
val = !!(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO); val = hsotg->hw_params.enable_dynamic_fifo;
dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val); dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2120,9 +2072,7 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2120,9 +2072,7 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val)
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
if (val < 16 || val > (readl(hsotg->regs + GRXFSIZ) & if (val < 16 || val > hsotg->hw_params.host_rx_fifo_size)
GRXFSIZ_DEPTH_MASK) >>
GRXFSIZ_DEPTH_SHIFT)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2130,9 +2080,7 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2130,9 +2080,7 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for host_rx_fifo_size. Check HW configuration.\n", "%d invalid for host_rx_fifo_size. Check HW configuration.\n",
val); val);
val = (readl(hsotg->regs + GRXFSIZ) & val = hsotg->hw_params.host_rx_fifo_size;
GRXFSIZ_DEPTH_MASK) >>
GRXFSIZ_DEPTH_SHIFT;
dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val); dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2146,7 +2094,7 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2146,7 +2094,7 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
if (val < 16 || val > (readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff)) if (val < 16 || val > hsotg->hw_params.host_nperio_tx_fifo_size)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2154,7 +2102,7 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2154,7 +2102,7 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n", "%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
val); val);
val = readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff; val = hsotg->hw_params.host_nperio_tx_fifo_size;
dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n", dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n",
val); val);
retval = -EINVAL; retval = -EINVAL;
...@@ -2169,7 +2117,7 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2169,7 +2117,7 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
if (val < 16 || val > (hsotg->hptxfsiz >> 16)) if (val < 16 || val > hsotg->hw_params.host_perio_tx_fifo_size)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2177,7 +2125,7 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2177,7 +2125,7 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", "%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
val); val);
val = hsotg->hptxfsiz >> 16; val = hsotg->hw_params.host_perio_tx_fifo_size;
dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n", dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n",
val); val);
retval = -EINVAL; retval = -EINVAL;
...@@ -2191,11 +2139,8 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2191,11 +2139,8 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val)
{ {
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
int width = hsotg->hwcfg3 >> GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT &
GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
if (val < 2047 || val >= (1 << (width + 11))) if (val < 2047 || val > hsotg->hw_params.max_transfer_size)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2203,7 +2148,7 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) ...@@ -2203,7 +2148,7 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for max_transfer_size. Check HW configuration.\n", "%d invalid for max_transfer_size. Check HW configuration.\n",
val); val);
val = (1 << (width + 11)) - 1; val = hsotg->hw_params.max_transfer_size;
dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val); dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2216,11 +2161,8 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) ...@@ -2216,11 +2161,8 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val)
{ {
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
int width = hsotg->hwcfg3 >> GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT &
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK >>
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
if (val < 15 || val >= (1 << (width + 4))) if (val < 15 || val > hsotg->hw_params.max_packet_count)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2228,7 +2170,7 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) ...@@ -2228,7 +2170,7 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for max_packet_count. Check HW configuration.\n", "%d invalid for max_packet_count. Check HW configuration.\n",
val); val);
val = (1 << (width + 4)) - 1; val = hsotg->hw_params.max_packet_count;
dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val); dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2241,10 +2183,8 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) ...@@ -2241,10 +2183,8 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val)
{ {
int valid = 1; int valid = 1;
int retval = 0; int retval = 0;
int num_chan = hsotg->hwcfg2 >> GHWCFG2_NUM_HOST_CHAN_SHIFT &
GHWCFG2_NUM_HOST_CHAN_MASK >> GHWCFG2_NUM_HOST_CHAN_SHIFT;
if (val < 1 || val > num_chan + 1) if (val < 1 || val > hsotg->hw_params.host_channels)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2252,7 +2192,7 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) ...@@ -2252,7 +2192,7 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for host_channels. Check HW configuration.\n", "%d invalid for host_channels. Check HW configuration.\n",
val); val);
val = num_chan + 1; val = hsotg->hw_params.host_channels;
dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val); dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2265,8 +2205,7 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) ...@@ -2265,8 +2205,7 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val)
{ {
#ifndef NO_FS_PHY_HW_CHECKS #ifndef NO_FS_PHY_HW_CHECKS
int valid = 0; int valid = 0;
u32 hs_phy_type; u32 hs_phy_type, fs_phy_type;
u32 fs_phy_type;
#endif #endif
int retval = 0; int retval = 0;
...@@ -2287,11 +2226,8 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) ...@@ -2287,11 +2226,8 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val)
} }
#ifndef NO_FS_PHY_HW_CHECKS #ifndef NO_FS_PHY_HW_CHECKS
hs_phy_type = (hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >> hs_phy_type = hsotg->hw_params.hs_phy_type;
GHWCFG2_HS_PHY_TYPE_SHIFT; fs_phy_type = hsotg->hw_params.fs_phy_type;
fs_phy_type = (hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
if (val == DWC2_PHY_TYPE_PARAM_UTMI && if (val == DWC2_PHY_TYPE_PARAM_UTMI &&
(hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI || (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI ||
hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)) hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
...@@ -2515,7 +2451,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2515,7 +2451,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val)
} }
#ifndef NO_FS_PHY_HW_CHECKS #ifndef NO_FS_PHY_HW_CHECKS
if (val == 1 && !(hsotg->hwcfg3 & GHWCFG3_I2C)) if (val == 1 && !(hsotg->hw_params.i2c_enable))
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2523,7 +2459,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) ...@@ -2523,7 +2459,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for i2c_enable. Check HW configuration.\n", "%d invalid for i2c_enable. Check HW configuration.\n",
val); val);
val = !!(hsotg->hwcfg3 & GHWCFG3_I2C); val = hsotg->hw_params.i2c_enable;
dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2548,7 +2484,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) ...@@ -2548,7 +2484,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val)
valid = 0; valid = 0;
} }
if (val == 1 && !(hsotg->hwcfg4 & GHWCFG4_DED_FIFO_EN)) if (val == 1 && !hsotg->hw_params.en_multiple_tx_fifo)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2556,7 +2492,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) ...@@ -2556,7 +2492,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", "%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
val); val);
val = !!(hsotg->hwcfg4 & GHWCFG4_DED_FIFO_EN); val = hsotg->hw_params.en_multiple_tx_fifo;
dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val); dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2579,7 +2515,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) ...@@ -2579,7 +2515,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val)
valid = 0; valid = 0;
} }
if (val == 1 && hsotg->snpsid < DWC2_CORE_REV_2_92a) if (val == 1 && hsotg->hw_params.snpsid < DWC2_CORE_REV_2_92a)
valid = 0; valid = 0;
if (!valid) { if (!valid) {
...@@ -2587,7 +2523,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) ...@@ -2587,7 +2523,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"%d invalid for parameter reload_ctl. Check HW configuration.\n", "%d invalid for parameter reload_ctl. Check HW configuration.\n",
val); val);
val = hsotg->snpsid >= DWC2_CORE_REV_2_92a; val = hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_92a;
dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val); dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val);
retval = -EINVAL; retval = -EINVAL;
} }
...@@ -2626,6 +2562,161 @@ int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) ...@@ -2626,6 +2562,161 @@ int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val)
return retval; return retval;
} }
/**
* During device initialization, read various hardware configuration
* registers and interpret the contents.
*/
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
{
struct dwc2_hw_params *hw = &hsotg->hw_params;
unsigned width;
u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4;
u32 hptxfsiz, grxfsiz, gnptxfsiz;
u32 gusbcfg;
/*
* Attempt to ensure this device is really a DWC_otg Controller.
* 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".
*/
hw->snpsid = readl(hsotg->regs + GSNPSID);
if ((hw->snpsid & 0xfffff000) != 0x4f542000 &&
(hw->snpsid & 0xfffff000) != 0x4f543000) {
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
hw->snpsid);
return -ENODEV;
}
dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x (snpsid=%x)\n",
hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
hwcfg1 = readl(hsotg->regs + GHWCFG1);
hwcfg2 = readl(hsotg->regs + GHWCFG2);
hwcfg3 = readl(hsotg->regs + GHWCFG3);
hwcfg4 = readl(hsotg->regs + GHWCFG4);
gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ);
grxfsiz = readl(hsotg->regs + GRXFSIZ);
dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1);
dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2);
dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hwcfg3);
dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hwcfg4);
dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz);
/* 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);
hptxfsiz = readl(hsotg->regs + HPTXFSIZ);
dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz);
gusbcfg = readl(hsotg->regs + GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
writel(gusbcfg, hsotg->regs + GUSBCFG);
usleep_range(100000, 150000);
/* hwcfg2 */
hw->op_mode = (hwcfg2 & GHWCFG2_OP_MODE_MASK) >>
GHWCFG2_OP_MODE_SHIFT;
hw->arch = (hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >>
GHWCFG2_ARCHITECTURE_SHIFT;
hw->enable_dynamic_fifo = !!(hwcfg2 & GHWCFG2_DYNAMIC_FIFO);
hw->host_channels = 1 + ((hwcfg2 & GHWCFG2_NUM_HOST_CHAN_MASK) >>
GHWCFG2_NUM_HOST_CHAN_SHIFT);
hw->hs_phy_type = (hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >>
GHWCFG2_HS_PHY_TYPE_SHIFT;
hw->fs_phy_type = (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
hw->num_dev_ep = (hwcfg2 & GHWCFG2_NUM_DEV_EP_MASK) >>
GHWCFG2_NUM_DEV_EP_SHIFT;
hw->nperio_tx_q_depth =
(hwcfg2 & GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT << 1;
hw->host_perio_tx_q_depth =
(hwcfg2 & GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT << 1;
hw->dev_token_q_depth =
(hwcfg2 & GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK) >>
GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT;
/* hwcfg3 */
width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
hw->max_transfer_size = (1 << (width + 11)) - 1;
width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
hw->max_packet_count = (1 << (width + 4)) - 1;
hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C);
hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >>
GHWCFG3_DFIFO_DEPTH_SHIFT;
/* hwcfg4 */
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA);
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
/* fifo sizes */
hw->host_rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
GRXFSIZ_DEPTH_SHIFT;
hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT;
hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT;
dev_dbg(hsotg->dev, "Detected values from hardware:\n");
dev_dbg(hsotg->dev, " op_mode=%d\n",
hw->op_mode);
dev_dbg(hsotg->dev, " arch=%d\n",
hw->arch);
dev_dbg(hsotg->dev, " dma_desc_enable=%d\n",
hw->dma_desc_enable);
dev_dbg(hsotg->dev, " power_optimized=%d\n",
hw->power_optimized);
dev_dbg(hsotg->dev, " i2c_enable=%d\n",
hw->i2c_enable);
dev_dbg(hsotg->dev, " hs_phy_type=%d\n",
hw->hs_phy_type);
dev_dbg(hsotg->dev, " fs_phy_type=%d\n",
hw->fs_phy_type);
dev_dbg(hsotg->dev, " num_dev_ep=%d\n",
hw->num_dev_ep);
dev_dbg(hsotg->dev, " num_dev_perio_in_ep=%d\n",
hw->num_dev_perio_in_ep);
dev_dbg(hsotg->dev, " host_channels=%d\n",
hw->host_channels);
dev_dbg(hsotg->dev, " max_transfer_size=%d\n",
hw->max_transfer_size);
dev_dbg(hsotg->dev, " max_packet_count=%d\n",
hw->max_packet_count);
dev_dbg(hsotg->dev, " nperio_tx_q_depth=0x%0x\n",
hw->nperio_tx_q_depth);
dev_dbg(hsotg->dev, " host_perio_tx_q_depth=0x%0x\n",
hw->host_perio_tx_q_depth);
dev_dbg(hsotg->dev, " dev_token_q_depth=0x%0x\n",
hw->dev_token_q_depth);
dev_dbg(hsotg->dev, " enable_dynamic_fifo=%d\n",
hw->enable_dynamic_fifo);
dev_dbg(hsotg->dev, " en_multiple_tx_fifo=%d\n",
hw->en_multiple_tx_fifo);
dev_dbg(hsotg->dev, " total_fifo_size=%d\n",
hw->total_fifo_size);
dev_dbg(hsotg->dev, " host_rx_fifo_size=%d\n",
hw->host_rx_fifo_size);
dev_dbg(hsotg->dev, " host_nperio_tx_fifo_size=%d\n",
hw->host_nperio_tx_fifo_size);
dev_dbg(hsotg->dev, " host_perio_tx_fifo_size=%d\n",
hw->host_perio_tx_fifo_size);
dev_dbg(hsotg->dev, "\n");
return 0;
}
/* /*
* This function is called during module intialization to pass module parameters * This function is called during module intialization to pass module parameters
* for the DWC_otg core. It returns non-0 if any parameters are invalid. * for the DWC_otg core. It returns non-0 if any parameters are invalid.
......
...@@ -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