diff options
Diffstat (limited to 'drivers/usb/host/ehci-fsl.c')
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 99 |
1 files changed, 71 insertions, 28 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 8600317bd60b..86e42892016d 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -116,13 +116,33 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, | |||
116 | goto err3; | 116 | goto err3; |
117 | } | 117 | } |
118 | 118 | ||
119 | /* Enable USB controller */ | 119 | pdata->regs = hcd->regs; |
120 | temp = in_be32(hcd->regs + 0x500); | ||
121 | out_be32(hcd->regs + 0x500, temp | 0x4); | ||
122 | 120 | ||
123 | /* Set to Host mode */ | 121 | /* |
124 | temp = in_le32(hcd->regs + 0x1a8); | 122 | * do platform specific init: check the clock, grab/config pins, etc. |
125 | out_le32(hcd->regs + 0x1a8, temp | 0x3); | 123 | */ |
124 | if (pdata->init && pdata->init(pdev)) { | ||
125 | retval = -ENODEV; | ||
126 | goto err3; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs | ||
131 | * flag for 83xx or 8536 system interface registers. | ||
132 | */ | ||
133 | if (pdata->big_endian_mmio) | ||
134 | temp = in_be32(hcd->regs + FSL_SOC_USB_ID); | ||
135 | else | ||
136 | temp = in_le32(hcd->regs + FSL_SOC_USB_ID); | ||
137 | |||
138 | if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK)) | ||
139 | pdata->have_sysif_regs = 1; | ||
140 | |||
141 | /* Enable USB controller, 83xx or 8536 */ | ||
142 | if (pdata->have_sysif_regs) | ||
143 | setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); | ||
144 | |||
145 | /* Don't need to set host mode here. It will be done by tdi_reset() */ | ||
126 | 146 | ||
127 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | 147 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); |
128 | if (retval != 0) | 148 | if (retval != 0) |
@@ -137,6 +157,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, | |||
137 | usb_put_hcd(hcd); | 157 | usb_put_hcd(hcd); |
138 | err1: | 158 | err1: |
139 | dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); | 159 | dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); |
160 | if (pdata->exit) | ||
161 | pdata->exit(pdev); | ||
140 | return retval; | 162 | return retval; |
141 | } | 163 | } |
142 | 164 | ||
@@ -154,17 +176,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, | |||
154 | static void usb_hcd_fsl_remove(struct usb_hcd *hcd, | 176 | static void usb_hcd_fsl_remove(struct usb_hcd *hcd, |
155 | struct platform_device *pdev) | 177 | struct platform_device *pdev) |
156 | { | 178 | { |
179 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | ||
180 | |||
157 | usb_remove_hcd(hcd); | 181 | usb_remove_hcd(hcd); |
182 | |||
183 | /* | ||
184 | * do platform specific un-initialization: | ||
185 | * release iomux pins, disable clock, etc. | ||
186 | */ | ||
187 | if (pdata->exit) | ||
188 | pdata->exit(pdev); | ||
158 | iounmap(hcd->regs); | 189 | iounmap(hcd->regs); |
159 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 190 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
160 | usb_put_hcd(hcd); | 191 | usb_put_hcd(hcd); |
161 | } | 192 | } |
162 | 193 | ||
163 | static void mpc83xx_setup_phy(struct ehci_hcd *ehci, | 194 | static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, |
164 | enum fsl_usb2_phy_modes phy_mode, | 195 | enum fsl_usb2_phy_modes phy_mode, |
165 | unsigned int port_offset) | 196 | unsigned int port_offset) |
166 | { | 197 | { |
167 | u32 portsc = 0; | 198 | u32 portsc; |
199 | |||
200 | portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); | ||
201 | portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); | ||
202 | |||
168 | switch (phy_mode) { | 203 | switch (phy_mode) { |
169 | case FSL_USB2_PHY_ULPI: | 204 | case FSL_USB2_PHY_ULPI: |
170 | portsc |= PORT_PTS_ULPI; | 205 | portsc |= PORT_PTS_ULPI; |
@@ -184,20 +219,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci, | |||
184 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); | 219 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); |
185 | } | 220 | } |
186 | 221 | ||
187 | static void mpc83xx_usb_setup(struct usb_hcd *hcd) | 222 | static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) |
188 | { | 223 | { |
189 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 224 | struct usb_hcd *hcd = ehci_to_hcd(ehci); |
190 | struct fsl_usb2_platform_data *pdata; | 225 | struct fsl_usb2_platform_data *pdata; |
191 | void __iomem *non_ehci = hcd->regs; | 226 | void __iomem *non_ehci = hcd->regs; |
192 | u32 temp; | 227 | u32 temp; |
193 | 228 | ||
194 | pdata = | 229 | pdata = hcd->self.controller->platform_data; |
195 | (struct fsl_usb2_platform_data *)hcd->self.controller-> | 230 | |
196 | platform_data; | ||
197 | /* Enable PHY interface in the control reg. */ | 231 | /* Enable PHY interface in the control reg. */ |
198 | temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); | 232 | if (pdata->have_sysif_regs) { |
199 | out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); | 233 | temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); |
200 | out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); | 234 | out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); |
235 | out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); | ||
236 | } | ||
201 | 237 | ||
202 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | 238 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) |
203 | /* | 239 | /* |
@@ -214,7 +250,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) | |||
214 | 250 | ||
215 | if ((pdata->operating_mode == FSL_USB2_DR_HOST) || | 251 | if ((pdata->operating_mode == FSL_USB2_DR_HOST) || |
216 | (pdata->operating_mode == FSL_USB2_DR_OTG)) | 252 | (pdata->operating_mode == FSL_USB2_DR_OTG)) |
217 | mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); | 253 | ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); |
218 | 254 | ||
219 | if (pdata->operating_mode == FSL_USB2_MPH_HOST) { | 255 | if (pdata->operating_mode == FSL_USB2_MPH_HOST) { |
220 | unsigned int chip, rev, svr; | 256 | unsigned int chip, rev, svr; |
@@ -228,25 +264,27 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) | |||
228 | ehci->has_fsl_port_bug = 1; | 264 | ehci->has_fsl_port_bug = 1; |
229 | 265 | ||
230 | if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) | 266 | if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) |
231 | mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); | 267 | ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); |
232 | if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) | 268 | if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) |
233 | mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); | 269 | ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); |
234 | } | 270 | } |
235 | 271 | ||
272 | if (pdata->have_sysif_regs) { | ||
236 | #ifdef CONFIG_PPC_85xx | 273 | #ifdef CONFIG_PPC_85xx |
237 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); | 274 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); |
238 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); | 275 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); |
239 | #else | 276 | #else |
240 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); | 277 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); |
241 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); | 278 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); |
242 | #endif | 279 | #endif |
243 | out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); | 280 | out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); |
281 | } | ||
244 | } | 282 | } |
245 | 283 | ||
246 | /* called after powerup, by probe or system-pm "wakeup" */ | 284 | /* called after powerup, by probe or system-pm "wakeup" */ |
247 | static int ehci_fsl_reinit(struct ehci_hcd *ehci) | 285 | static int ehci_fsl_reinit(struct ehci_hcd *ehci) |
248 | { | 286 | { |
249 | mpc83xx_usb_setup(ehci_to_hcd(ehci)); | 287 | ehci_fsl_usb_setup(ehci); |
250 | ehci_port_power(ehci, 0); | 288 | ehci_port_power(ehci, 0); |
251 | 289 | ||
252 | return 0; | 290 | return 0; |
@@ -257,6 +295,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) | |||
257 | { | 295 | { |
258 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 296 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
259 | int retval; | 297 | int retval; |
298 | struct fsl_usb2_platform_data *pdata; | ||
299 | |||
300 | pdata = hcd->self.controller->platform_data; | ||
301 | ehci->big_endian_desc = pdata->big_endian_desc; | ||
302 | ehci->big_endian_mmio = pdata->big_endian_mmio; | ||
260 | 303 | ||
261 | /* EHCI registers start at offset 0x100 */ | 304 | /* EHCI registers start at offset 0x100 */ |
262 | ehci->caps = hcd->regs + 0x100; | 305 | ehci->caps = hcd->regs + 0x100; |
@@ -370,7 +413,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { | |||
370 | * generic hardware linkage | 413 | * generic hardware linkage |
371 | */ | 414 | */ |
372 | .irq = ehci_irq, | 415 | .irq = ehci_irq, |
373 | .flags = HCD_USB2, | 416 | .flags = HCD_USB2 | HCD_MEMORY, |
374 | 417 | ||
375 | /* | 418 | /* |
376 | * basic lifecycle operations | 419 | * basic lifecycle operations |