aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/host/Kconfig6
-rw-r--r--drivers/usb/host/ehci-fsl.c99
-rw-r--r--drivers/usb/host/ehci-fsl.h13
-rw-r--r--drivers/usb/host/ehci-mem.c2
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c89
6 files changed, 178 insertions, 32 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4aa00e6e57ad..67eb3770868f 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -59,6 +59,7 @@ config USB_ARCH_HAS_OHCI
59config USB_ARCH_HAS_EHCI 59config USB_ARCH_HAS_EHCI
60 boolean 60 boolean
61 default y if PPC_83xx 61 default y if PPC_83xx
62 default y if PPC_MPC512x
62 default y if SOC_AU1200 63 default y if SOC_AU1200
63 default y if ARCH_IXP4XX 64 default y if ARCH_IXP4XX
64 default y if ARCH_W90X900 65 default y if ARCH_W90X900
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f3a90b0fc422..bf2e7d234533 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED
93 93
94config USB_EHCI_BIG_ENDIAN_MMIO 94config USB_EHCI_BIG_ENDIAN_MMIO
95 bool 95 bool
96 depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) 96 depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \
97 XPS_USB_HCD_XILINX || PPC_MPC512x)
97 default y 98 default y
98 99
99config USB_EHCI_BIG_ENDIAN_DESC 100config USB_EHCI_BIG_ENDIAN_DESC
100 bool 101 bool
101 depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) 102 depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
103 PPC_MPC512x)
102 default y 104 default y
103 105
104config XPS_USB_HCD_XILINX 106config XPS_USB_HCD_XILINX
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,
154static void usb_hcd_fsl_remove(struct usb_hcd *hcd, 176static 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
163static void mpc83xx_setup_phy(struct ehci_hcd *ehci, 194static 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
187static void mpc83xx_usb_setup(struct usb_hcd *hcd) 222static 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" */
247static int ehci_fsl_reinit(struct ehci_hcd *ehci) 285static 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
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index eb537aa54610..2c8353795226 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
1/* Copyright (c) 2005 freescale semiconductor 1/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
2 * Copyright (c) 2005 MontaVista Software 2 * Copyright (c) 2005 MontaVista Software
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
@@ -19,6 +19,9 @@
19#define _EHCI_FSL_H 19#define _EHCI_FSL_H
20 20
21/* offsets for the non-ehci registers in the FSL SOC USB controller */ 21/* offsets for the non-ehci registers in the FSL SOC USB controller */
22#define FSL_SOC_USB_ID 0x0
23#define ID_MSK 0x3f
24#define NID_MSK 0x3f00
22#define FSL_SOC_USB_ULPIVP 0x170 25#define FSL_SOC_USB_ULPIVP 0x170
23#define FSL_SOC_USB_PORTSC1 0x184 26#define FSL_SOC_USB_PORTSC1 0x184
24#define PORT_PTS_MSK (3<<30) 27#define PORT_PTS_MSK (3<<30)
@@ -27,6 +30,14 @@
27#define PORT_PTS_SERIAL (3<<30) 30#define PORT_PTS_SERIAL (3<<30)
28#define PORT_PTS_PTW (1<<28) 31#define PORT_PTS_PTW (1<<28)
29#define FSL_SOC_USB_PORTSC2 0x188 32#define FSL_SOC_USB_PORTSC2 0x188
33
34#define FSL_SOC_USB_USBGENCTRL 0x200
35#define USBGENCTRL_PPP (1 << 3)
36#define USBGENCTRL_PFP (1 << 2)
37#define FSL_SOC_USB_ISIPHYCTRL 0x204
38#define ISIPHYCTRL_PXE (1)
39#define ISIPHYCTRL_PHYE (1 << 4)
40
30#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ 41#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */
31#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ 42#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */
32#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ 43#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 1f3f01eacaf0..d36e4e75e08d 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
40{ 40{
41 memset (qtd, 0, sizeof *qtd); 41 memset (qtd, 0, sizeof *qtd);
42 qtd->qtd_dma = dma; 42 qtd->qtd_dma = dma;
43 qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); 43 qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
44 qtd->hw_next = EHCI_LIST_END(ehci); 44 qtd->hw_next = EHCI_LIST_END(ehci);
45 qtd->hw_alt_next = EHCI_LIST_END(ehci); 45 qtd->hw_alt_next = EHCI_LIST_END(ehci);
46 INIT_LIST_HEAD (&qtd->qtd_list); 46 INIT_LIST_HEAD (&qtd->qtd_list);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 12db5d5cb0bc..574b99ea0700 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -15,6 +15,7 @@
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/of_platform.h> 17#include <linux/of_platform.h>
18#include <linux/clk.h>
18 19
19struct fsl_usb2_dev_data { 20struct fsl_usb2_dev_data {
20 char *dr_mode; /* controller mode */ 21 char *dr_mode; /* controller mode */
@@ -153,6 +154,12 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
153 154
154 pdata->operating_mode = FSL_USB2_MPH_HOST; 155 pdata->operating_mode = FSL_USB2_MPH_HOST;
155 } else { 156 } else {
157 if (of_get_property(np, "fsl,invert-drvvbus", NULL))
158 pdata->invert_drvvbus = 1;
159
160 if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
161 pdata->invert_pwr_fault = 1;
162
156 /* setup mode selected in the device tree */ 163 /* setup mode selected in the device tree */
157 pdata->operating_mode = dev_data->op_mode; 164 pdata->operating_mode = dev_data->op_mode;
158 } 165 }
@@ -186,9 +193,91 @@ static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
186 return 0; 193 return 0;
187} 194}
188 195
196#ifdef CONFIG_PPC_MPC512x
197
198#define USBGENCTRL 0x200 /* NOTE: big endian */
199#define GC_WU_INT_CLR (1 << 5) /* Wakeup int clear */
200#define GC_ULPI_SEL (1 << 4) /* ULPI i/f select (usb0 only)*/
201#define GC_PPP (1 << 3) /* Inv. Port Power Polarity */
202#define GC_PFP (1 << 2) /* Inv. Power Fault Polarity */
203#define GC_WU_ULPI_EN (1 << 1) /* Wakeup on ULPI event */
204#define GC_WU_IE (1 << 1) /* Wakeup interrupt enable */
205
206#define ISIPHYCTRL 0x204 /* NOTE: big endian */
207#define PHYCTRL_PHYE (1 << 4) /* On-chip UTMI PHY enable */
208#define PHYCTRL_BSENH (1 << 3) /* Bit Stuff Enable High */
209#define PHYCTRL_BSEN (1 << 2) /* Bit Stuff Enable */
210#define PHYCTRL_LSFE (1 << 1) /* Line State Filter Enable */
211#define PHYCTRL_PXE (1 << 0) /* PHY oscillator enable */
212
213int fsl_usb2_mpc5121_init(struct platform_device *pdev)
214{
215 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
216 struct clk *clk;
217 char clk_name[10];
218 int base, clk_num;
219
220 base = pdev->resource->start & 0xf000;
221 if (base == 0x3000)
222 clk_num = 1;
223 else if (base == 0x4000)
224 clk_num = 2;
225 else
226 return -ENODEV;
227
228 snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
229 clk = clk_get(&pdev->dev, clk_name);
230 if (IS_ERR(clk)) {
231 dev_err(&pdev->dev, "failed to get clk\n");
232 return PTR_ERR(clk);
233 }
234
235 clk_enable(clk);
236 pdata->clk = clk;
237
238 if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
239 u32 reg = 0;
240
241 if (pdata->invert_drvvbus)
242 reg |= GC_PPP;
243
244 if (pdata->invert_pwr_fault)
245 reg |= GC_PFP;
246
247 out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
248 out_be32(pdata->regs + USBGENCTRL, reg);
249 }
250 return 0;
251}
252
253static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
254{
255 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
256
257 pdata->regs = NULL;
258
259 if (pdata->clk) {
260 clk_disable(pdata->clk);
261 clk_put(pdata->clk);
262 }
263}
264
265struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
266 .big_endian_desc = 1,
267 .big_endian_mmio = 1,
268 .es = 1,
269 .le_setup_buf = 1,
270 .init = fsl_usb2_mpc5121_init,
271 .exit = fsl_usb2_mpc5121_exit,
272};
273#endif /* CONFIG_PPC_MPC512x */
274
189static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { 275static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
190 { .compatible = "fsl-usb2-mph", }, 276 { .compatible = "fsl-usb2-mph", },
191 { .compatible = "fsl-usb2-dr", }, 277 { .compatible = "fsl-usb2-dr", },
278#ifdef CONFIG_PPC_MPC512x
279 { .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
280#endif
192 {}, 281 {},
193}; 282};
194 283