Commit 9d6623f13fe58edb5c773c8915ec610b37bb8774
Committed by
Ji Luo
1 parent
dfdf60c69c
Exists in
smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga
and in
4 other branches
MA-14379 [coverity] Resource leak (RESOURCE_LEAK)
Fix coverity issue: CID 2970630: Resource leak (RESOURCE_LEAK) leaked_storage: Variable cdns going out of scope leaks the storage it points to. Memory allocated by devm_kzalloc() won't be freed automatically in u-boot, free the memory manually here. Test: Coverity scan pass. Change-Id: I3000a2385941cef3b8b7e01611cfdc999971a4ca Signed-off-by: Luo Ji <ji.luo@nxp.com>
Showing 1 changed file with 5 additions and 0 deletions Inline Diff
drivers/usb/cdns3/core.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2016 Cadence Design Systems - https://www.cadence.com/ | 2 | * Copyright (C) 2016 Cadence Design Systems - https://www.cadence.com/ |
3 | * Copyright 2018 NXP | 3 | * Copyright 2018 NXP |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0 | 5 | * SPDX-License-Identifier: GPL-2.0 |
6 | */ | 6 | */ |
7 | #include <common.h> | 7 | #include <common.h> |
8 | #include <malloc.h> | 8 | #include <malloc.h> |
9 | #include <asm/dma-mapping.h> | 9 | #include <asm/dma-mapping.h> |
10 | #include <asm/io.h> | 10 | #include <asm/io.h> |
11 | #include <linux/bug.h> | 11 | #include <linux/bug.h> |
12 | #include <linux/list.h> | 12 | #include <linux/list.h> |
13 | #include <linux/compat.h> | 13 | #include <linux/compat.h> |
14 | #include <cdns3-uboot.h> | 14 | #include <cdns3-uboot.h> |
15 | 15 | ||
16 | #include "linux-compat.h" | 16 | #include "linux-compat.h" |
17 | #include "cdns3-nxp-reg-def.h" | 17 | #include "cdns3-nxp-reg-def.h" |
18 | #include "core.h" | 18 | #include "core.h" |
19 | #include "gadget-export.h" | 19 | #include "gadget-export.h" |
20 | 20 | ||
21 | static LIST_HEAD(cdns3_list); | 21 | static LIST_HEAD(cdns3_list); |
22 | 22 | ||
23 | /* Need SoC level to implement the clock */ | 23 | /* Need SoC level to implement the clock */ |
24 | __weak int cdns3_enable_clks(int index) | 24 | __weak int cdns3_enable_clks(int index) |
25 | { | 25 | { |
26 | return 0; | 26 | return 0; |
27 | } | 27 | } |
28 | 28 | ||
29 | __weak int cdns3_disable_clks(int index) | 29 | __weak int cdns3_disable_clks(int index) |
30 | { | 30 | { |
31 | return 0; | 31 | return 0; |
32 | } | 32 | } |
33 | 33 | ||
34 | static void cdns3_usb_phy_init(void __iomem *regs) | 34 | static void cdns3_usb_phy_init(void __iomem *regs) |
35 | { | 35 | { |
36 | u32 value; | 36 | u32 value; |
37 | 37 | ||
38 | pr_debug("begin of %s\n", __func__); | 38 | pr_debug("begin of %s\n", __func__); |
39 | 39 | ||
40 | writel(0x0830, regs + PHY_PMA_CMN_CTRL1); | 40 | writel(0x0830, regs + PHY_PMA_CMN_CTRL1); |
41 | writel(0x10, regs + TB_ADDR_CMN_DIAG_HSCLK_SEL); | 41 | writel(0x10, regs + TB_ADDR_CMN_DIAG_HSCLK_SEL); |
42 | writel(0x00F0, regs + TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR); | 42 | writel(0x00F0, regs + TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR); |
43 | writel(0x0018, regs + TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR); | 43 | writel(0x0018, regs + TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR); |
44 | writel(0x00D0, regs + TB_ADDR_CMN_PLL0_INTDIV); | 44 | writel(0x00D0, regs + TB_ADDR_CMN_PLL0_INTDIV); |
45 | writel(0x4aaa, regs + TB_ADDR_CMN_PLL0_FRACDIV); | 45 | writel(0x4aaa, regs + TB_ADDR_CMN_PLL0_FRACDIV); |
46 | writel(0x0034, regs + TB_ADDR_CMN_PLL0_HIGH_THR); | 46 | writel(0x0034, regs + TB_ADDR_CMN_PLL0_HIGH_THR); |
47 | writel(0x1ee, regs + TB_ADDR_CMN_PLL0_SS_CTRL1); | 47 | writel(0x1ee, regs + TB_ADDR_CMN_PLL0_SS_CTRL1); |
48 | writel(0x7F03, regs + TB_ADDR_CMN_PLL0_SS_CTRL2); | 48 | writel(0x7F03, regs + TB_ADDR_CMN_PLL0_SS_CTRL2); |
49 | writel(0x0020, regs + TB_ADDR_CMN_PLL0_DSM_DIAG); | 49 | writel(0x0020, regs + TB_ADDR_CMN_PLL0_DSM_DIAG); |
50 | writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_OVRD); | 50 | writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_OVRD); |
51 | writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD); | 51 | writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD); |
52 | writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD); | 52 | writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD); |
53 | writel(0x0007, regs + TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE); | 53 | writel(0x0007, regs + TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE); |
54 | writel(0x0027, regs + TB_ADDR_CMN_DIAG_PLL0_CP_TUNE); | 54 | writel(0x0027, regs + TB_ADDR_CMN_DIAG_PLL0_CP_TUNE); |
55 | writel(0x0008, regs + TB_ADDR_CMN_DIAG_PLL0_LF_PROG); | 55 | writel(0x0008, regs + TB_ADDR_CMN_DIAG_PLL0_LF_PROG); |
56 | writel(0x0022, regs + TB_ADDR_CMN_DIAG_PLL0_TEST_MODE); | 56 | writel(0x0022, regs + TB_ADDR_CMN_DIAG_PLL0_TEST_MODE); |
57 | writel(0x000a, regs + TB_ADDR_CMN_PSM_CLK_CTRL); | 57 | writel(0x000a, regs + TB_ADDR_CMN_PSM_CLK_CTRL); |
58 | writel(0x139, regs + TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR); | 58 | writel(0x139, regs + TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR); |
59 | writel(0xbefc, regs + TB_ADDR_XCVR_PSM_RCTRL); | 59 | writel(0xbefc, regs + TB_ADDR_XCVR_PSM_RCTRL); |
60 | 60 | ||
61 | writel(0x7799, regs + TB_ADDR_TX_PSC_A0); | 61 | writel(0x7799, regs + TB_ADDR_TX_PSC_A0); |
62 | writel(0x7798, regs + TB_ADDR_TX_PSC_A1); | 62 | writel(0x7798, regs + TB_ADDR_TX_PSC_A1); |
63 | writel(0x509b, regs + TB_ADDR_TX_PSC_A2); | 63 | writel(0x509b, regs + TB_ADDR_TX_PSC_A2); |
64 | writel(0x3, regs + TB_ADDR_TX_DIAG_ECTRL_OVRD); | 64 | writel(0x3, regs + TB_ADDR_TX_DIAG_ECTRL_OVRD); |
65 | writel(0x509b, regs + TB_ADDR_TX_PSC_A3); | 65 | writel(0x509b, regs + TB_ADDR_TX_PSC_A3); |
66 | writel(0x2090, regs + TB_ADDR_TX_PSC_CAL); | 66 | writel(0x2090, regs + TB_ADDR_TX_PSC_CAL); |
67 | writel(0x2090, regs + TB_ADDR_TX_PSC_RDY); | 67 | writel(0x2090, regs + TB_ADDR_TX_PSC_RDY); |
68 | 68 | ||
69 | writel(0xA6FD, regs + TB_ADDR_RX_PSC_A0); | 69 | writel(0xA6FD, regs + TB_ADDR_RX_PSC_A0); |
70 | writel(0xA6FD, regs + TB_ADDR_RX_PSC_A1); | 70 | writel(0xA6FD, regs + TB_ADDR_RX_PSC_A1); |
71 | writel(0xA410, regs + TB_ADDR_RX_PSC_A2); | 71 | writel(0xA410, regs + TB_ADDR_RX_PSC_A2); |
72 | writel(0x2410, regs + TB_ADDR_RX_PSC_A3); | 72 | writel(0x2410, regs + TB_ADDR_RX_PSC_A3); |
73 | 73 | ||
74 | writel(0x23FF, regs + TB_ADDR_RX_PSC_CAL); | 74 | writel(0x23FF, regs + TB_ADDR_RX_PSC_CAL); |
75 | writel(0x2010, regs + TB_ADDR_RX_PSC_RDY); | 75 | writel(0x2010, regs + TB_ADDR_RX_PSC_RDY); |
76 | 76 | ||
77 | writel(0x0020, regs + TB_ADDR_TX_TXCC_MGNLS_MULT_000); | 77 | writel(0x0020, regs + TB_ADDR_TX_TXCC_MGNLS_MULT_000); |
78 | writel(0x00ff, regs + TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY); | 78 | writel(0x00ff, regs + TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY); |
79 | writel(0x0002, regs + TB_ADDR_RX_SLC_CU_ITER_TMR); | 79 | writel(0x0002, regs + TB_ADDR_RX_SLC_CU_ITER_TMR); |
80 | writel(0x0013, regs + TB_ADDR_RX_SIGDET_HL_FILT_TMR); | 80 | writel(0x0013, regs + TB_ADDR_RX_SIGDET_HL_FILT_TMR); |
81 | writel(0x0000, regs + TB_ADDR_RX_SAMP_DAC_CTRL); | 81 | writel(0x0000, regs + TB_ADDR_RX_SAMP_DAC_CTRL); |
82 | writel(0x1004, regs + TB_ADDR_RX_DIAG_SIGDET_TUNE); | 82 | writel(0x1004, regs + TB_ADDR_RX_DIAG_SIGDET_TUNE); |
83 | writel(0x4041, regs + TB_ADDR_RX_DIAG_LFPSDET_TUNE2); | 83 | writel(0x4041, regs + TB_ADDR_RX_DIAG_LFPSDET_TUNE2); |
84 | writel(0x0480, regs + TB_ADDR_RX_DIAG_BS_TM); | 84 | writel(0x0480, regs + TB_ADDR_RX_DIAG_BS_TM); |
85 | writel(0x8006, regs + TB_ADDR_RX_DIAG_DFE_CTRL1); | 85 | writel(0x8006, regs + TB_ADDR_RX_DIAG_DFE_CTRL1); |
86 | writel(0x003f, regs + TB_ADDR_RX_DIAG_ILL_IQE_TRIM4); | 86 | writel(0x003f, regs + TB_ADDR_RX_DIAG_ILL_IQE_TRIM4); |
87 | writel(0x543f, regs + TB_ADDR_RX_DIAG_ILL_E_TRIM0); | 87 | writel(0x543f, regs + TB_ADDR_RX_DIAG_ILL_E_TRIM0); |
88 | writel(0x543f, regs + TB_ADDR_RX_DIAG_ILL_IQ_TRIM0); | 88 | writel(0x543f, regs + TB_ADDR_RX_DIAG_ILL_IQ_TRIM0); |
89 | writel(0x0000, regs + TB_ADDR_RX_DIAG_ILL_IQE_TRIM6); | 89 | writel(0x0000, regs + TB_ADDR_RX_DIAG_ILL_IQE_TRIM6); |
90 | writel(0x8000, regs + TB_ADDR_RX_DIAG_RXFE_TM3); | 90 | writel(0x8000, regs + TB_ADDR_RX_DIAG_RXFE_TM3); |
91 | writel(0x0003, regs + TB_ADDR_RX_DIAG_RXFE_TM4); | 91 | writel(0x0003, regs + TB_ADDR_RX_DIAG_RXFE_TM4); |
92 | writel(0x2408, regs + TB_ADDR_RX_DIAG_LFPSDET_TUNE); | 92 | writel(0x2408, regs + TB_ADDR_RX_DIAG_LFPSDET_TUNE); |
93 | writel(0x05ca, regs + TB_ADDR_RX_DIAG_DFE_CTRL3); | 93 | writel(0x05ca, regs + TB_ADDR_RX_DIAG_DFE_CTRL3); |
94 | writel(0x0258, regs + TB_ADDR_RX_DIAG_SC2C_DELAY); | 94 | writel(0x0258, regs + TB_ADDR_RX_DIAG_SC2C_DELAY); |
95 | writel(0x1fff, regs + TB_ADDR_RX_REE_VGA_GAIN_NODFE); | 95 | writel(0x1fff, regs + TB_ADDR_RX_REE_VGA_GAIN_NODFE); |
96 | 96 | ||
97 | writel(0x02c6, regs + TB_ADDR_XCVR_PSM_CAL_TMR); | 97 | writel(0x02c6, regs + TB_ADDR_XCVR_PSM_CAL_TMR); |
98 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A0BYP_TMR); | 98 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A0BYP_TMR); |
99 | writel(0x02c6, regs + TB_ADDR_XCVR_PSM_A0IN_TMR); | 99 | writel(0x02c6, regs + TB_ADDR_XCVR_PSM_A0IN_TMR); |
100 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A1IN_TMR); | 100 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A1IN_TMR); |
101 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A2IN_TMR); | 101 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A2IN_TMR); |
102 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A3IN_TMR); | 102 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A3IN_TMR); |
103 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A4IN_TMR); | 103 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A4IN_TMR); |
104 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A5IN_TMR); | 104 | writel(0x0010, regs + TB_ADDR_XCVR_PSM_A5IN_TMR); |
105 | 105 | ||
106 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A0OUT_TMR); | 106 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A0OUT_TMR); |
107 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A1OUT_TMR); | 107 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A1OUT_TMR); |
108 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A2OUT_TMR); | 108 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A2OUT_TMR); |
109 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A3OUT_TMR); | 109 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A3OUT_TMR); |
110 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A4OUT_TMR); | 110 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A4OUT_TMR); |
111 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A5OUT_TMR); | 111 | writel(0x0002, regs + TB_ADDR_XCVR_PSM_A5OUT_TMR); |
112 | 112 | ||
113 | /* Change rx detect parameter */ | 113 | /* Change rx detect parameter */ |
114 | writel(0x960, regs + TB_ADDR_TX_RCVDET_EN_TMR); | 114 | writel(0x960, regs + TB_ADDR_TX_RCVDET_EN_TMR); |
115 | writel(0x01e0, regs + TB_ADDR_TX_RCVDET_ST_TMR); | 115 | writel(0x01e0, regs + TB_ADDR_TX_RCVDET_ST_TMR); |
116 | writel(0x0090, regs + TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR); | 116 | writel(0x0090, regs + TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR); |
117 | 117 | ||
118 | /* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */ | 118 | /* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */ |
119 | value = readl(regs + TB_ADDR_TX_RCVDETSC_CTRL); | 119 | value = readl(regs + TB_ADDR_TX_RCVDETSC_CTRL); |
120 | value |= RXDET_IN_P3_32KHZ; | 120 | value |= RXDET_IN_P3_32KHZ; |
121 | writel(value, regs + TB_ADDR_TX_RCVDETSC_CTRL); | 121 | writel(value, regs + TB_ADDR_TX_RCVDETSC_CTRL); |
122 | 122 | ||
123 | udelay(10); | 123 | udelay(10); |
124 | 124 | ||
125 | pr_debug("end of %s\n", __func__); | 125 | pr_debug("end of %s\n", __func__); |
126 | } | 126 | } |
127 | 127 | ||
128 | static void cdns3_reset_core(struct cdns3 *cdns) | 128 | static void cdns3_reset_core(struct cdns3 *cdns) |
129 | { | 129 | { |
130 | u32 value; | 130 | u32 value; |
131 | 131 | ||
132 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); | 132 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); |
133 | value |= ALL_SW_RESET; | 133 | value |= ALL_SW_RESET; |
134 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 134 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
135 | udelay(1); | 135 | udelay(1); |
136 | } | 136 | } |
137 | 137 | ||
138 | static void cdns3_set_role(struct cdns3 *cdns, enum cdns3_roles role) | 138 | static void cdns3_set_role(struct cdns3 *cdns, enum cdns3_roles role) |
139 | { | 139 | { |
140 | u32 value; | 140 | u32 value; |
141 | int timeout_us = 100000; | 141 | int timeout_us = 100000; |
142 | 142 | ||
143 | if (role == CDNS3_ROLE_END) | 143 | if (role == CDNS3_ROLE_END) |
144 | return; | 144 | return; |
145 | 145 | ||
146 | /* Wait clk value */ | 146 | /* Wait clk value */ |
147 | value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS); | 147 | value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS); |
148 | writel(value, cdns->none_core_regs + USB3_SSPHY_STATUS); | 148 | writel(value, cdns->none_core_regs + USB3_SSPHY_STATUS); |
149 | udelay(1); | 149 | udelay(1); |
150 | value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS); | 150 | value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS); |
151 | while ((value & 0xf0000000) != 0xf0000000 && timeout_us-- > 0) { | 151 | while ((value & 0xf0000000) != 0xf0000000 && timeout_us-- > 0) { |
152 | value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS); | 152 | value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS); |
153 | dev_dbg(cdns->dev, "clkvld:0x%x\n", value); | 153 | dev_dbg(cdns->dev, "clkvld:0x%x\n", value); |
154 | udelay(1); | 154 | udelay(1); |
155 | } | 155 | } |
156 | 156 | ||
157 | if (timeout_us <= 0) | 157 | if (timeout_us <= 0) |
158 | dev_err(cdns->dev, "wait clkvld timeout\n"); | 158 | dev_err(cdns->dev, "wait clkvld timeout\n"); |
159 | 159 | ||
160 | /* Set all Reset bits */ | 160 | /* Set all Reset bits */ |
161 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); | 161 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); |
162 | value |= ALL_SW_RESET; | 162 | value |= ALL_SW_RESET; |
163 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 163 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
164 | udelay(1); | 164 | udelay(1); |
165 | 165 | ||
166 | if (role == CDNS3_ROLE_HOST) { | 166 | if (role == CDNS3_ROLE_HOST) { |
167 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); | 167 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); |
168 | value = (value & ~MODE_STRAP_MASK) | HOST_MODE | OC_DISABLE; | 168 | value = (value & ~MODE_STRAP_MASK) | HOST_MODE | OC_DISABLE; |
169 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 169 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
170 | value &= ~PHYAHB_SW_RESET; | 170 | value &= ~PHYAHB_SW_RESET; |
171 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 171 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
172 | mdelay(1); | 172 | mdelay(1); |
173 | cdns3_usb_phy_init(cdns->phy_regs); | 173 | cdns3_usb_phy_init(cdns->phy_regs); |
174 | /* Force B Session Valid as 1 */ | 174 | /* Force B Session Valid as 1 */ |
175 | writel(0x0060, cdns->phy_regs + 0x380a4); | 175 | writel(0x0060, cdns->phy_regs + 0x380a4); |
176 | mdelay(1); | 176 | mdelay(1); |
177 | 177 | ||
178 | value = readl(cdns->none_core_regs + USB3_INT_REG); | 178 | value = readl(cdns->none_core_regs + USB3_INT_REG); |
179 | value |= HOST_INT1_EN; | 179 | value |= HOST_INT1_EN; |
180 | writel(value, cdns->none_core_regs + USB3_INT_REG); | 180 | writel(value, cdns->none_core_regs + USB3_INT_REG); |
181 | 181 | ||
182 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); | 182 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); |
183 | value &= ~ALL_SW_RESET; | 183 | value &= ~ALL_SW_RESET; |
184 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 184 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
185 | 185 | ||
186 | dev_dbg(cdns->dev, "wait xhci_power_on_ready\n"); | 186 | dev_dbg(cdns->dev, "wait xhci_power_on_ready\n"); |
187 | 187 | ||
188 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); | 188 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); |
189 | timeout_us = 100000; | 189 | timeout_us = 100000; |
190 | while (!(value & HOST_POWER_ON_READY) && timeout_us-- > 0) { | 190 | while (!(value & HOST_POWER_ON_READY) && timeout_us-- > 0) { |
191 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); | 191 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); |
192 | udelay(1); | 192 | udelay(1); |
193 | } | 193 | } |
194 | 194 | ||
195 | if (timeout_us <= 0) | 195 | if (timeout_us <= 0) |
196 | dev_err(cdns->dev, "wait xhci_power_on_ready timeout\n"); | 196 | dev_err(cdns->dev, "wait xhci_power_on_ready timeout\n"); |
197 | 197 | ||
198 | mdelay(1); | 198 | mdelay(1); |
199 | 199 | ||
200 | dev_dbg(cdns->dev, "switch to host role successfully\n"); | 200 | dev_dbg(cdns->dev, "switch to host role successfully\n"); |
201 | } else { /* gadget mode */ | 201 | } else { /* gadget mode */ |
202 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); | 202 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); |
203 | value = (value & ~MODE_STRAP_MASK) | DEV_MODE; | 203 | value = (value & ~MODE_STRAP_MASK) | DEV_MODE; |
204 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 204 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
205 | value &= ~PHYAHB_SW_RESET; | 205 | value &= ~PHYAHB_SW_RESET; |
206 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 206 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
207 | 207 | ||
208 | cdns3_usb_phy_init(cdns->phy_regs); | 208 | cdns3_usb_phy_init(cdns->phy_regs); |
209 | /* Force B Session Valid as 1 */ | 209 | /* Force B Session Valid as 1 */ |
210 | writel(0x0060, cdns->phy_regs + 0x380a4); | 210 | writel(0x0060, cdns->phy_regs + 0x380a4); |
211 | value = readl(cdns->none_core_regs + USB3_INT_REG); | 211 | value = readl(cdns->none_core_regs + USB3_INT_REG); |
212 | value |= DEV_INT_EN; | 212 | value |= DEV_INT_EN; |
213 | writel(value, cdns->none_core_regs + USB3_INT_REG); | 213 | writel(value, cdns->none_core_regs + USB3_INT_REG); |
214 | 214 | ||
215 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); | 215 | value = readl(cdns->none_core_regs + USB3_CORE_CTRL1); |
216 | value &= ~ALL_SW_RESET; | 216 | value &= ~ALL_SW_RESET; |
217 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); | 217 | writel(value, cdns->none_core_regs + USB3_CORE_CTRL1); |
218 | 218 | ||
219 | dev_dbg(cdns->dev, "wait gadget_power_on_ready\n"); | 219 | dev_dbg(cdns->dev, "wait gadget_power_on_ready\n"); |
220 | 220 | ||
221 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); | 221 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); |
222 | timeout_us = 100000; | 222 | timeout_us = 100000; |
223 | while (!(value & DEV_POWER_ON_READY) && timeout_us-- > 0) { | 223 | while (!(value & DEV_POWER_ON_READY) && timeout_us-- > 0) { |
224 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); | 224 | value = readl(cdns->none_core_regs + USB3_CORE_STATUS); |
225 | udelay(1); | 225 | udelay(1); |
226 | } | 226 | } |
227 | 227 | ||
228 | if (timeout_us <= 0) | 228 | if (timeout_us <= 0) |
229 | dev_err(cdns->dev, | 229 | dev_err(cdns->dev, |
230 | "wait gadget_power_on_ready timeout\n"); | 230 | "wait gadget_power_on_ready timeout\n"); |
231 | 231 | ||
232 | mdelay(1); | 232 | mdelay(1); |
233 | 233 | ||
234 | dev_dbg(cdns->dev, "switch to gadget role successfully\n"); | 234 | dev_dbg(cdns->dev, "switch to gadget role successfully\n"); |
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | static enum cdns3_roles cdns3_get_role(struct cdns3 *cdns) | 238 | static enum cdns3_roles cdns3_get_role(struct cdns3 *cdns) |
239 | { | 239 | { |
240 | return cdns->roles[CDNS3_ROLE_HOST] | 240 | return cdns->roles[CDNS3_ROLE_HOST] |
241 | ? CDNS3_ROLE_HOST | 241 | ? CDNS3_ROLE_HOST |
242 | : CDNS3_ROLE_GADGET; | 242 | : CDNS3_ROLE_GADGET; |
243 | } | 243 | } |
244 | 244 | ||
245 | /** | 245 | /** |
246 | * cdns3_core_init_role - initialize role of operation | 246 | * cdns3_core_init_role - initialize role of operation |
247 | * @cdns: Pointer to cdns3 structure | 247 | * @cdns: Pointer to cdns3 structure |
248 | * | 248 | * |
249 | * Returns 0 on success otherwise negative errno | 249 | * Returns 0 on success otherwise negative errno |
250 | */ | 250 | */ |
251 | static int cdns3_core_init_role(struct cdns3 *cdns, enum usb_dr_mode dr_mode) | 251 | static int cdns3_core_init_role(struct cdns3 *cdns, enum usb_dr_mode dr_mode) |
252 | { | 252 | { |
253 | cdns->role = CDNS3_ROLE_END; | 253 | cdns->role = CDNS3_ROLE_END; |
254 | if (dr_mode == USB_DR_MODE_UNKNOWN) | 254 | if (dr_mode == USB_DR_MODE_UNKNOWN) |
255 | dr_mode = USB_DR_MODE_OTG; | 255 | dr_mode = USB_DR_MODE_OTG; |
256 | 256 | ||
257 | /* Currently, only support gadget mode */ | 257 | /* Currently, only support gadget mode */ |
258 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { | 258 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { |
259 | dev_err(cdns->dev, "doesn't support host and OTG, only for gadget\n"); | 259 | dev_err(cdns->dev, "doesn't support host and OTG, only for gadget\n"); |
260 | return -EPERM; | 260 | return -EPERM; |
261 | } | 261 | } |
262 | 262 | ||
263 | if (dr_mode == USB_DR_MODE_PERIPHERAL) { | 263 | if (dr_mode == USB_DR_MODE_PERIPHERAL) { |
264 | if (cdns3_gadget_init(cdns)) | 264 | if (cdns3_gadget_init(cdns)) |
265 | dev_info(cdns->dev, "doesn't support gadget\n"); | 265 | dev_info(cdns->dev, "doesn't support gadget\n"); |
266 | } | 266 | } |
267 | 267 | ||
268 | if (!cdns->roles[CDNS3_ROLE_HOST] && !cdns->roles[CDNS3_ROLE_GADGET]) { | 268 | if (!cdns->roles[CDNS3_ROLE_HOST] && !cdns->roles[CDNS3_ROLE_GADGET]) { |
269 | dev_err(cdns->dev, "no supported roles\n"); | 269 | dev_err(cdns->dev, "no supported roles\n"); |
270 | return -ENODEV; | 270 | return -ENODEV; |
271 | } | 271 | } |
272 | 272 | ||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | static void cdns3_remove_roles(struct cdns3 *cdns) | 276 | static void cdns3_remove_roles(struct cdns3 *cdns) |
277 | { | 277 | { |
278 | /* Only support gadget */ | 278 | /* Only support gadget */ |
279 | cdns3_gadget_remove(cdns); | 279 | cdns3_gadget_remove(cdns); |
280 | } | 280 | } |
281 | 281 | ||
282 | int cdns3_uboot_init(struct cdns3_device *cdns3_dev) | 282 | int cdns3_uboot_init(struct cdns3_device *cdns3_dev) |
283 | { | 283 | { |
284 | struct device *dev = NULL; | 284 | struct device *dev = NULL; |
285 | struct cdns3 *cdns; | 285 | struct cdns3 *cdns; |
286 | int ret; | 286 | int ret; |
287 | 287 | ||
288 | cdns = devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); | 288 | cdns = devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); |
289 | if (!cdns) | 289 | if (!cdns) |
290 | return -ENOMEM; | 290 | return -ENOMEM; |
291 | 291 | ||
292 | cdns->dev = dev; | 292 | cdns->dev = dev; |
293 | 293 | ||
294 | /* | 294 | /* |
295 | * Request memory region | 295 | * Request memory region |
296 | * region-0: nxp wrap registers | 296 | * region-0: nxp wrap registers |
297 | * region-1: xHCI | 297 | * region-1: xHCI |
298 | * region-2: Peripheral | 298 | * region-2: Peripheral |
299 | * region-3: PHY registers | 299 | * region-3: PHY registers |
300 | * region-4: OTG registers | 300 | * region-4: OTG registers |
301 | */ | 301 | */ |
302 | cdns->none_core_regs = (void __iomem *)cdns3_dev->none_core_base; | 302 | cdns->none_core_regs = (void __iomem *)cdns3_dev->none_core_base; |
303 | cdns->xhci_regs = (void __iomem *)cdns3_dev->xhci_base; | 303 | cdns->xhci_regs = (void __iomem *)cdns3_dev->xhci_base; |
304 | cdns->dev_regs = (void __iomem *)cdns3_dev->dev_base; | 304 | cdns->dev_regs = (void __iomem *)cdns3_dev->dev_base; |
305 | cdns->phy_regs = (void __iomem *)cdns3_dev->phy_base; | 305 | cdns->phy_regs = (void __iomem *)cdns3_dev->phy_base; |
306 | cdns->otg_regs = (void __iomem *)cdns3_dev->otg_base; | 306 | cdns->otg_regs = (void __iomem *)cdns3_dev->otg_base; |
307 | cdns->index = cdns3_dev->index; | 307 | cdns->index = cdns3_dev->index; |
308 | 308 | ||
309 | ret = cdns3_enable_clks(cdns->index); | 309 | ret = cdns3_enable_clks(cdns->index); |
310 | if (ret) | 310 | if (ret) |
311 | return ret; | 311 | return ret; |
312 | 312 | ||
313 | ret = cdns3_core_init_role(cdns, cdns3_dev->dr_mode); | 313 | ret = cdns3_core_init_role(cdns, cdns3_dev->dr_mode); |
314 | if (ret) | 314 | if (ret) |
315 | goto err1; | 315 | goto err1; |
316 | 316 | ||
317 | cdns->role = cdns3_get_role(cdns); | 317 | cdns->role = cdns3_get_role(cdns); |
318 | dev_dbg(dev, "the init role is %d\n", cdns->role); | 318 | dev_dbg(dev, "the init role is %d\n", cdns->role); |
319 | cdns3_set_role(cdns, cdns->role); | 319 | cdns3_set_role(cdns, cdns->role); |
320 | ret = cdns3_role_start(cdns, cdns->role); | 320 | ret = cdns3_role_start(cdns, cdns->role); |
321 | if (ret) { | 321 | if (ret) { |
322 | dev_err(dev, "can't start %s role\n", cdns3_role(cdns)->name); | 322 | dev_err(dev, "can't start %s role\n", cdns3_role(cdns)->name); |
323 | goto err2; | 323 | goto err2; |
324 | } | 324 | } |
325 | 325 | ||
326 | dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); | 326 | dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); |
327 | 327 | ||
328 | list_add_tail(&cdns->list, &cdns3_list); | 328 | list_add_tail(&cdns->list, &cdns3_list); |
329 | 329 | ||
330 | return 0; | 330 | return 0; |
331 | 331 | ||
332 | err2: | 332 | err2: |
333 | cdns3_remove_roles(cdns); | 333 | cdns3_remove_roles(cdns); |
334 | err1: | 334 | err1: |
335 | cdns3_disable_clks(cdns->index); | 335 | cdns3_disable_clks(cdns->index); |
336 | |||
337 | /* For u-boot, need to free the memory manually here. */ | ||
338 | if (cdns != NULL) | ||
339 | free(cdns); | ||
340 | |||
336 | return ret; | 341 | return ret; |
337 | } | 342 | } |
338 | 343 | ||
339 | void cdns3_uboot_exit(int index) | 344 | void cdns3_uboot_exit(int index) |
340 | { | 345 | { |
341 | struct cdns3 *cdns; | 346 | struct cdns3 *cdns; |
342 | 347 | ||
343 | list_for_each_entry(cdns, &cdns3_list, list) { | 348 | list_for_each_entry(cdns, &cdns3_list, list) { |
344 | if (cdns->index != index) | 349 | if (cdns->index != index) |
345 | continue; | 350 | continue; |
346 | 351 | ||
347 | cdns3_role_stop(cdns); | 352 | cdns3_role_stop(cdns); |
348 | cdns3_remove_roles(cdns); | 353 | cdns3_remove_roles(cdns); |
349 | cdns3_reset_core(cdns); | 354 | cdns3_reset_core(cdns); |
350 | cdns3_disable_clks(index); | 355 | cdns3_disable_clks(index); |
351 | 356 | ||
352 | list_del(&cdns->list); | 357 | list_del(&cdns->list); |
353 | kfree(cdns); | 358 | kfree(cdns); |
354 | break; | 359 | break; |
355 | } | 360 | } |
356 | } | 361 | } |
357 | 362 | ||
358 | void cdns3_uboot_handle_interrupt(int index) | 363 | void cdns3_uboot_handle_interrupt(int index) |
359 | { | 364 | { |
360 | struct cdns3 *cdns = NULL; | 365 | struct cdns3 *cdns = NULL; |
361 | 366 | ||
362 | list_for_each_entry(cdns, &cdns3_list, list) { | 367 | list_for_each_entry(cdns, &cdns3_list, list) { |
363 | if (cdns->index != index) | 368 | if (cdns->index != index) |
364 | continue; | 369 | continue; |
365 | 370 | ||
366 | cdns3_role_irq_handler(cdns); | 371 | cdns3_role_irq_handler(cdns); |
367 | break; | 372 | break; |
368 | } | 373 | } |
369 | } | 374 | } |
370 | 375 |