aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/fsl-mph-dr-of.c
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2010-09-28 14:55:21 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:21:58 -0400
commit230f7ede6c2f0e403f29e03e0251a470aa9350dd (patch)
tree6f1c14f10696c12fd4461cc48289b3cb7a342060 /drivers/usb/host/fsl-mph-dr-of.c
parent126512e3f274802ca65ebeca8660237f0361ad48 (diff)
USB: add USB EHCI support for MPC5121 SoC
Extends FSL EHCI platform driver glue layer to support MPC5121 USB controllers. MPC5121 Rev 2.0 silicon EHCI registers are in big endian format. The appropriate flags are set using the information in the platform data structure. MPC83xx system interface registers are not available on MPC512x, so the access to these registers is isolated in MPC512x case. Furthermore the USB controller clocks must be enabled before 512x register accesses which is done by providing platform specific init callback. The MPC512x internal USB PHY doesn't provide supply voltage. For boards using different power switches allow specifying DRVVBUS and PWR_FAULT signal polarity of the MPC5121 internal PHY using "fsl,invert-drvvbus" and "fsl,invert-pwr-fault" properties in the device tree USB nodes. Adds documentation for this new device tree bindings. Signed-off-by: Anatolij Gustschin <agust@denx.de> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/fsl-mph-dr-of.c')
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c89
1 files changed, 89 insertions, 0 deletions
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