diff options
| author | Dinh Nguyen <Dinh.Nguyen@freescale.com> | 2010-04-30 16:48:26 -0400 |
|---|---|---|
| committer | Sascha Hauer <s.hauer@pengutronix.de> | 2010-05-03 09:18:13 -0400 |
| commit | 5a25ad84e01173bb225285eb50f9af48ed1a7598 (patch) | |
| tree | 183e0c375ee5364cae0b693f945c16925dfe3723 | |
| parent | 231637f5f2c7f3795d1b0c9b59fda27a23ffdc3e (diff) | |
mxc: Add generic USB HW initialization for MX51
This patch adds USB HW initializiation code to /plat-mxc/ehci.c.
-Sets some specific PHY settings
Renames mxc_set_usbcontrol to mxc_initialize_usb_hw.
Adds new register bit defines for the USB HW on Freescale
SoCs.
This patch applies to 2.6.34-rc6.
Signed-off-by: Dinh Nguyen <Dinh.Nguyen@freescale.com>
Reviewed-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
| -rw-r--r-- | arch/arm/plat-mxc/ehci.c | 100 | ||||
| -rw-r--r-- | arch/arm/plat-mxc/include/mach/mxc_ehci.h | 14 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-mxc.c | 4 |
3 files changed, 113 insertions, 5 deletions
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c index cb0b63874482..2a8646173c2f 100644 --- a/arch/arm/plat-mxc/ehci.c +++ b/arch/arm/plat-mxc/ehci.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | 2 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> |
| 3 | * Copyright (C) 2010 Freescale Semiconductor, Inc. | ||
| 3 | * | 4 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the | 6 | * under the terms of the GNU General Public License as published by the |
| @@ -50,7 +51,26 @@ | |||
| 50 | #define MX35_H1_TLL_BIT (1 << 5) | 51 | #define MX35_H1_TLL_BIT (1 << 5) |
| 51 | #define MX35_H1_USBTE_BIT (1 << 4) | 52 | #define MX35_H1_USBTE_BIT (1 << 4) |
| 52 | 53 | ||
| 53 | int mxc_set_usbcontrol(int port, unsigned int flags) | 54 | #define MXC_OTG_OFFSET 0 |
| 55 | #define MXC_H1_OFFSET 0x200 | ||
| 56 | |||
| 57 | /* USB_CTRL */ | ||
| 58 | #define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */ | ||
| 59 | #define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */ | ||
| 60 | #define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */ | ||
| 61 | #define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */ | ||
| 62 | #define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */ | ||
| 63 | |||
| 64 | /* USB_PHY_CTRL_FUNC */ | ||
| 65 | #define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */ | ||
| 66 | #define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */ | ||
| 67 | |||
| 68 | #define MXC_USBCMD_OFFSET 0x140 | ||
| 69 | |||
| 70 | /* USBCMD */ | ||
| 71 | #define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */ | ||
| 72 | |||
| 73 | int mxc_initialize_usb_hw(int port, unsigned int flags) | ||
| 54 | { | 74 | { |
| 55 | unsigned int v; | 75 | unsigned int v; |
| 56 | #ifdef CONFIG_ARCH_MX3 | 76 | #ifdef CONFIG_ARCH_MX3 |
| @@ -186,9 +206,85 @@ int mxc_set_usbcontrol(int port, unsigned int flags) | |||
| 186 | return 0; | 206 | return 0; |
| 187 | } | 207 | } |
| 188 | #endif /* CONFIG_MACH_MX27 */ | 208 | #endif /* CONFIG_MACH_MX27 */ |
| 209 | #ifdef CONFIG_ARCH_MX51 | ||
| 210 | if (cpu_is_mx51()) { | ||
| 211 | void __iomem *usb_base; | ||
| 212 | u32 usbotg_base; | ||
| 213 | u32 usbother_base; | ||
| 214 | int ret = 0; | ||
| 215 | |||
| 216 | usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K); | ||
| 217 | |||
| 218 | switch (port) { | ||
| 219 | case 0: /* OTG port */ | ||
| 220 | usbotg_base = usb_base + MXC_OTG_OFFSET; | ||
| 221 | break; | ||
| 222 | case 1: /* Host 1 port */ | ||
| 223 | usbotg_base = usb_base + MXC_H1_OFFSET; | ||
| 224 | break; | ||
| 225 | default: | ||
| 226 | printk(KERN_ERR"%s no such port %d\n", __func__, port); | ||
| 227 | ret = -ENOENT; | ||
| 228 | goto error; | ||
| 229 | } | ||
| 230 | usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; | ||
| 231 | |||
| 232 | switch (port) { | ||
| 233 | case 0: /*OTG port */ | ||
| 234 | if (flags & MXC_EHCI_INTERNAL_PHY) { | ||
| 235 | v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); | ||
| 236 | |||
| 237 | if (flags & MXC_EHCI_POWER_PINS_ENABLED) | ||
| 238 | v |= (MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is not used */ | ||
| 239 | else | ||
| 240 | v &= ~(MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is used */ | ||
| 241 | __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); | ||
| 242 | |||
| 243 | v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); | ||
| 244 | if (flags & MXC_EHCI_WAKEUP_ENABLED) | ||
| 245 | v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */ | ||
| 246 | else | ||
| 247 | v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */ | ||
| 248 | __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); | ||
| 249 | } | ||
| 250 | break; | ||
| 251 | case 1: /* Host 1 */ | ||
| 252 | /*Host ULPI */ | ||
| 253 | v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); | ||
| 254 | if (flags & MXC_EHCI_WAKEUP_ENABLED) | ||
| 255 | v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */ | ||
| 256 | else | ||
| 257 | v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */ | ||
| 258 | |||
| 259 | if (flags & MXC_EHCI_POWER_PINS_ENABLED) | ||
| 260 | v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ | ||
| 261 | else | ||
| 262 | v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ | ||
| 263 | __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); | ||
| 264 | |||
| 265 | v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); | ||
| 266 | if (flags & MXC_EHCI_POWER_PINS_ENABLED) | ||
| 267 | v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ | ||
| 268 | else | ||
| 269 | v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ | ||
| 270 | __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); | ||
| 271 | |||
| 272 | v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET); | ||
| 273 | if (flags & MXC_EHCI_ITC_NO_THRESHOLD) | ||
| 274 | /* Interrupt Threshold Control:Immediate (no threshold) */ | ||
| 275 | v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK; | ||
| 276 | __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET); | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | error: | ||
| 281 | iounmap(usb_base); | ||
| 282 | return ret; | ||
| 283 | } | ||
| 284 | #endif | ||
| 189 | printk(KERN_WARNING | 285 | printk(KERN_WARNING |
| 190 | "%s() unable to setup USBCONTROL for this CPU\n", __func__); | 286 | "%s() unable to setup USBCONTROL for this CPU\n", __func__); |
| 191 | return -EINVAL; | 287 | return -EINVAL; |
| 192 | } | 288 | } |
| 193 | EXPORT_SYMBOL(mxc_set_usbcontrol); | 289 | EXPORT_SYMBOL(mxc_initialize_usb_hw); |
| 194 | 290 | ||
diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h index 4b9b8368c0c0..7fc5f9946199 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h +++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h | |||
| @@ -25,6 +25,18 @@ | |||
| 25 | #define MXC_EHCI_INTERNAL_PHY (1 << 7) | 25 | #define MXC_EHCI_INTERNAL_PHY (1 << 7) |
| 26 | #define MXC_EHCI_IPPUE_DOWN (1 << 8) | 26 | #define MXC_EHCI_IPPUE_DOWN (1 << 8) |
| 27 | #define MXC_EHCI_IPPUE_UP (1 << 9) | 27 | #define MXC_EHCI_IPPUE_UP (1 << 9) |
| 28 | #define MXC_EHCI_WAKEUP_ENABLED (1 << 10) | ||
| 29 | #define MXC_EHCI_ITC_NO_THRESHOLD (1 << 11) | ||
| 30 | |||
| 31 | #define MXC_USBCTRL_OFFSET 0 | ||
| 32 | #define MXC_USB_PHY_CTR_FUNC_OFFSET 0x8 | ||
| 33 | #define MXC_USB_PHY_CTR_FUNC2_OFFSET 0xc | ||
| 34 | |||
| 35 | #define MX5_USBOTHER_REGS_OFFSET 0x800 | ||
| 36 | |||
| 37 | /* USB_PHY_CTRL_FUNC2*/ | ||
| 38 | #define MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK 0x3 | ||
| 39 | #define MX5_USB_UTMI_PHYCTRL1_PLLDIV_SHIFT 0 | ||
| 28 | 40 | ||
| 29 | struct mxc_usbh_platform_data { | 41 | struct mxc_usbh_platform_data { |
| 30 | int (*init)(struct platform_device *pdev); | 42 | int (*init)(struct platform_device *pdev); |
| @@ -35,7 +47,7 @@ struct mxc_usbh_platform_data { | |||
| 35 | struct otg_transceiver *otg; | 47 | struct otg_transceiver *otg; |
| 36 | }; | 48 | }; |
| 37 | 49 | ||
| 38 | int mxc_set_usbcontrol(int port, unsigned int flags); | 50 | int mxc_initialize_usb_hw(int port, unsigned int flags); |
| 39 | 51 | ||
| 40 | #endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */ | 52 | #endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */ |
| 41 | 53 | ||
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ead59f42e69b..544ccfd7056e 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
| @@ -199,8 +199,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
| 199 | writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); | 199 | writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); |
| 200 | mdelay(10); | 200 | mdelay(10); |
| 201 | 201 | ||
| 202 | /* setup USBCONTROL. */ | 202 | /* setup specific usb hw */ |
| 203 | ret = mxc_set_usbcontrol(pdev->id, pdata->flags); | 203 | ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); |
| 204 | if (ret < 0) | 204 | if (ret < 0) |
| 205 | goto err_init; | 205 | goto err_init; |
| 206 | 206 | ||
