| 1 | From 632dc9e46a9ff032138f81fd420c0f01fd6c3cbc Mon Sep 17 00:00:00 2001 |
| 2 | From: Jason Jin <Jason.jin@freescale.com> |
| 3 | Date: Thu, 4 Aug 2011 14:21:29 +0800 |
| 4 | Subject: [PATCH 40/52] Add USB support for MCF5445x and MCF54418 |
| 5 | |
| 6 | The OTG module function with external ULPI of USB3300 |
| 7 | on M5445xEVB and Modelo TWR-SER2, while the Max3353 charge |
| 8 | pump on Modelo TWR-SER1 with version-B CPU board only |
| 9 | function FS/LS tranceiver. |
| 10 | It also support USB host module on Modelo TWR-SER2. |
| 11 | And the host mode on M54455EVB with FS/LS only tranceiver |
| 12 | is supported by p4 interface on the board. |
| 13 | |
| 14 | Signed-off-by: Jingchang Lu <b35083@freescale.com> |
| 15 | --- |
| 16 | arch/m68k/Kconfig | 2 + |
| 17 | arch/m68k/coldfire/m5441x/Makefile | 4 +- |
| 18 | arch/m68k/coldfire/m5441x/max3353.h | 96 +++ |
| 19 | arch/m68k/coldfire/m5441x/max3353_otg.c | 508 +++++++++++++ |
| 20 | arch/m68k/coldfire/m5441x/max3353_xc.c | 310 ++++++++ |
| 21 | arch/m68k/coldfire/m5441x/usb.c | 276 +++++++ |
| 22 | arch/m68k/coldfire/m5441x/usb.h | 76 ++ |
| 23 | arch/m68k/coldfire/m5441x/usb_dr.c | 179 +++++ |
| 24 | arch/m68k/coldfire/m5441x/usb_host.c | 115 +++ |
| 25 | arch/m68k/coldfire/m5441x/xcvr.c | 198 +++++ |
| 26 | arch/m68k/coldfire/m5441x/xcvr_host.c | 53 ++ |
| 27 | arch/m68k/coldfire/m5445x/usb.c | 220 ++++++ |
| 28 | arch/m68k/coldfire/m5445x/usb.h | 107 +++ |
| 29 | arch/m68k/coldfire/m5445x/usb_dr.c | 152 ++++ |
| 30 | arch/m68k/coldfire/m5445x/xcvr.c | 127 ++++ |
| 31 | arch/m68k/include/asm/fsl_usb_gadget.h | 45 ++ |
| 32 | arch/m68k/include/asm/fsl_usb_io.h | 43 ++ |
| 33 | arch/m68k/include/asm/fsl_usb_platform.h | 78 ++ |
| 34 | drivers/Makefile | 1 + |
| 35 | drivers/usb/Kconfig | 2 + |
| 36 | drivers/usb/core/Kconfig | 2 +- |
| 37 | drivers/usb/gadget/Kconfig | 2 +- |
| 38 | drivers/usb/gadget/fsl_udc_core.c | 360 ++++++++- |
| 39 | drivers/usb/gadget/fsl_usb2_udc.h | 16 + |
| 40 | drivers/usb/gadget/serial.c | 40 +- |
| 41 | drivers/usb/host/Kconfig | 72 ++- |
| 42 | drivers/usb/host/ehci-fsl.c | 257 ++++++- |
| 43 | drivers/usb/host/ehci-fsl.h | 7 + |
| 44 | drivers/usb/host/ehci-hub.c | 34 + |
| 45 | drivers/usb/host/ehci.h | 55 ++- |
| 46 | drivers/usb/otg/Makefile | 7 + |
| 47 | drivers/usb/otg/fsl_otg.c | 1212 ++++++++++++++++++++++++++++++ |
| 48 | drivers/usb/otg/fsl_otg.h | 423 +++++++++++ |
| 49 | drivers/usb/otg/otg_fsm.c | 371 +++++++++ |
| 50 | drivers/usb/otg/otg_fsm.h | 151 ++++ |
| 51 | drivers/usb/otg/usb.c | 76 ++ |
| 52 | include/linux/fsl_devices.h | 26 + |
| 53 | include/linux/usb/fsl_usb2.h | 410 ++++++++++ |
| 54 | include/linux/usb/fsl_xcvr.h | 36 + |
| 55 | include/linux/usb/otg.h | 2 +- |
| 56 | 40 files changed, 6087 insertions(+), 64 deletions(-) |
| 57 | create mode 100644 arch/m68k/coldfire/m5441x/max3353.h |
| 58 | create mode 100644 arch/m68k/coldfire/m5441x/max3353_otg.c |
| 59 | create mode 100644 arch/m68k/coldfire/m5441x/max3353_xc.c |
| 60 | create mode 100644 arch/m68k/coldfire/m5441x/usb.c |
| 61 | create mode 100644 arch/m68k/coldfire/m5441x/usb.h |
| 62 | create mode 100644 arch/m68k/coldfire/m5441x/usb_dr.c |
| 63 | create mode 100644 arch/m68k/coldfire/m5441x/usb_host.c |
| 64 | create mode 100644 arch/m68k/coldfire/m5441x/xcvr.c |
| 65 | create mode 100644 arch/m68k/coldfire/m5441x/xcvr_host.c |
| 66 | create mode 100644 arch/m68k/coldfire/m5445x/usb.c |
| 67 | create mode 100644 arch/m68k/coldfire/m5445x/usb.h |
| 68 | create mode 100644 arch/m68k/coldfire/m5445x/usb_dr.c |
| 69 | create mode 100644 arch/m68k/coldfire/m5445x/xcvr.c |
| 70 | create mode 100644 arch/m68k/include/asm/fsl_usb_gadget.h |
| 71 | create mode 100644 arch/m68k/include/asm/fsl_usb_io.h |
| 72 | create mode 100644 arch/m68k/include/asm/fsl_usb_platform.h |
| 73 | create mode 100644 drivers/usb/otg/fsl_otg.c |
| 74 | create mode 100644 drivers/usb/otg/fsl_otg.h |
| 75 | create mode 100644 drivers/usb/otg/otg_fsm.c |
| 76 | create mode 100644 drivers/usb/otg/otg_fsm.h |
| 77 | create mode 100644 drivers/usb/otg/usb.c |
| 78 | create mode 100644 include/linux/usb/fsl_usb2.h |
| 79 | create mode 100644 include/linux/usb/fsl_xcvr.h |
| 80 | |
| 81 | --- a/arch/m68k/Kconfig |
| 82 | +++ b/arch/m68k/Kconfig |
| 83 | @@ -327,6 +327,7 @@ config M5445X |
| 84 | bool "MCF5445x support" |
| 85 | depends on COLDFIRE |
| 86 | select GENERIC_TIME |
| 87 | + select USB_ARCH_HAS_EHCI |
| 88 | select USB_EHCI_FSL |
| 89 | select HAVE_FSL_USB_DR |
| 90 | help |
| 91 | @@ -430,6 +431,7 @@ config M5441X |
| 92 | depends on COLDFIRE |
| 93 | select GENERIC_TIME |
| 94 | select USB_EHCI_FSL |
| 95 | + select USB_ARCH_HAS_EHCI |
| 96 | select HAVE_FSL_USB_DR |
| 97 | select HAVE_CAN_FLEXCAN |
| 98 | help |
| 99 | --- a/arch/m68k/coldfire/m5441x/Makefile |
| 100 | +++ b/arch/m68k/coldfire/m5441x/Makefile |
| 101 | @@ -14,9 +14,11 @@ endif |
| 102 | endif |
| 103 | |
| 104 | #ifneq ($(strip $(CONFIG_USB) $(CONFIG_USB_GADGET_FSL_USB2)),) |
| 105 | -ifneq ($(strip $(CONFIG_USB_OTG) $(CONFIG_USB_M5441X_MAX3353_FSLS)),) |
| 106 | +ifneq ($(strip $(CONFIG_USB_OTG)),) |
| 107 | +ifeq ($(strip $(CONFIG_USB_M5441X_MAX3353_FSLS)),) |
| 108 | obj-y += xcvr.o |
| 109 | endif |
| 110 | +endif |
| 111 | ifneq ($(strip $(CONFIG_USB_M5441X_MAX3353_FSLS)), ) |
| 112 | obj-y += max3353_xc.o |
| 113 | ifneq ($(strip $(CONFIG_USB_OTG)),) |
| 114 | --- /dev/null |
| 115 | +++ b/arch/m68k/coldfire/m5441x/max3353.h |
| 116 | @@ -0,0 +1,96 @@ |
| 117 | +/* |
| 118 | + * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. |
| 119 | + * |
| 120 | + * This program is free software; you can redistribute it and/or modify it |
| 121 | + * under the terms of the GNU General Public License as published by the |
| 122 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 123 | + * option) any later version. |
| 124 | + * |
| 125 | + * This program is distributed in the hope that it will be useful, but |
| 126 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 127 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 128 | + * General Public License for more details. |
| 129 | + * |
| 130 | + * You should have received a copy of the GNU General Public License along |
| 131 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 132 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 133 | + */ |
| 134 | + |
| 135 | +#ifndef _MAX3353_H_ |
| 136 | +#define _MAX3353_H_ |
| 137 | +/* registers */ |
| 138 | + |
| 139 | +/* Manufacturer registers */ |
| 140 | +#define MAX3353_MAN0 0x00 |
| 141 | +#define MAX3353_MAN1 0x01 |
| 142 | +#define MAX3353_MAN2 0x02 |
| 143 | +#define MAX3353_MAN3 0x03 |
| 144 | + |
| 145 | +/* Product ID registers */ |
| 146 | +#define MAX3353_PID0 0x04 |
| 147 | +#define MAX3353_PID1 0x05 |
| 148 | +#define MAX3353_PID2 0x06 |
| 149 | +#define MAX3353_PID3 0x07 |
| 150 | + |
| 151 | +/* Control register 1 */ |
| 152 | +#define MAX3353_CR1 0x10 |
| 153 | +#define CR1_DM_PULLDOWN (1 << 7) |
| 154 | +#define CR1_DP_PULLDOWN (1 << 6) |
| 155 | +#define CR1_DM_PULLUP (1 << 5) |
| 156 | +#define CR1_DP_PULLUP (1 << 4) |
| 157 | +#define CR1_BDISC_ACONN (1 << 2) |
| 158 | +#define CR1_IRQ_PUSH_PULL (1 << 1) |
| 159 | + |
| 160 | +/* Control register 2 */ |
| 161 | +#define MAX3353_CR2 0x11 |
| 162 | +#define CR2_VBUS_DISCHRG (1 << 4) |
| 163 | +#define CR2_VBUS_DRV (1 << 3) |
| 164 | +#define CR2_VBUS_CHG2 (1 << 2) |
| 165 | +#define CR2_VBUS_CHG1 (1 << 1) |
| 166 | +#define CR2_SHUTDOWN (1 << 0) |
| 167 | + |
| 168 | +/* Status register */ |
| 169 | +#define MAX3353_STATUS 0x13 |
| 170 | +#define STATUS_B_HNP (1 << 6) |
| 171 | +#define STATUS_A_HNP (1 << 5) |
| 172 | +#define STATUS_ID_FLOAT (1 << 4) |
| 173 | +#define STATUS_ID_GND (1 << 3) |
| 174 | +#define STATUS_SESSION_END (1 << 2) |
| 175 | +#define STATUS_SESSION_VALID (1 << 1) |
| 176 | +#define STATUS_VBUS_VALID (1 << 0) |
| 177 | + |
| 178 | +/* Interrupt mask register */ |
| 179 | +#define MAX3353_INTR_MASK 0x14 |
| 180 | +#define IM_A_HNP_EN (1 << 5) |
| 181 | +#define IM_ID_FLOAT_EN (1 << 4) |
| 182 | +#define IM_ID_GND_EN (1 << 3) |
| 183 | +#define IM_SESSION_END_EN (1 << 2) |
| 184 | +#define IM_SESSION_VLD_EN (1 << 1) |
| 185 | +#define IM_VBUS_VLD_EN (1 << 0) |
| 186 | + |
| 187 | +/* Interrupt edge register */ |
| 188 | +#define MAX3353_INTR_EDGE 0x15 |
| 189 | +#define IE_SESSION_VALID_ED (1 << 1) |
| 190 | +#define IE_VBUS_VLD_ED (1 << 0) |
| 191 | + |
| 192 | +/* Interrupt latch register (read-only) */ |
| 193 | +#define MAX3353_INTR_LATCH 0x16 |
| 194 | +#define IL_A_HNP_RQ (1 << 7) |
| 195 | +#define IL_ID_FLOAT_RQ (1 << 6) |
| 196 | +#define IL_ID_GND_RQ (1 << 5) |
| 197 | +#define IL_SESSION_END_RQ (1 << 4) |
| 198 | +#define IL_SESSION_VALID_RN (1 << 3) |
| 199 | +#define IL_VBUS_VALID_RN (1 << 2) |
| 200 | +#define IL_SESSION_VALID_RP (1 << 1) |
| 201 | +#define IL_VBUS_VALID_RP (1 << 0) |
| 202 | + |
| 203 | + |
| 204 | +#define MAX3353_DEV_ADDR 0x2c |
| 205 | +#define MAX3353_IRQ (64 + 4) /* IRQ4 */ |
| 206 | + |
| 207 | +extern u8 max3353_read_reg(u8 reg); |
| 208 | +extern void max3353_write_reg(u8 reg, u8 data); |
| 209 | +extern int max3353_read_id_pin(void); |
| 210 | +extern int otg_set_resources(struct resource *resources); |
| 211 | + |
| 212 | +#endif /* _MAX3353_H_ */ |
| 213 | --- /dev/null |
| 214 | +++ b/arch/m68k/coldfire/m5441x/max3353_otg.c |
| 215 | @@ -0,0 +1,508 @@ |
| 216 | +/* |
| 217 | + * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. |
| 218 | + * |
| 219 | + * This program is free software; you can redistribute it and/or modify it |
| 220 | + * under the terms of the GNU General Public License as published by the |
| 221 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 222 | + * option) any later version. |
| 223 | + * |
| 224 | + * This program is distributed in the hope that it will be useful, but |
| 225 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 226 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 227 | + * General Public License for more details. |
| 228 | + * |
| 229 | + * You should have received a copy of the GNU General Public License along |
| 230 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 231 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 232 | + */ |
| 233 | + |
| 234 | +#include <linux/module.h> |
| 235 | +#include <linux/kernel.h> |
| 236 | +#include <linux/types.h> |
| 237 | +#include <linux/err.h> |
| 238 | +#include <linux/errno.h> |
| 239 | +#include <linux/init.h> |
| 240 | +#include <linux/io.h> |
| 241 | +#include <linux/moduleparam.h> |
| 242 | +#include <linux/delay.h> |
| 243 | +#include <linux/sched.h> |
| 244 | +#include <linux/usb.h> |
| 245 | +#include <linux/usb/gadget.h> |
| 246 | +#include <linux/usb/otg.h> |
| 247 | +#include <linux/workqueue.h> |
| 248 | +#include <linux/time.h> |
| 249 | +#include <linux/platform_device.h> |
| 250 | +#include <linux/fsl_devices.h> |
| 251 | +#include <linux/usb/fsl_usb2.h> |
| 252 | +#include <linux/usb/otg.h> |
| 253 | + |
| 254 | +#include <asm/fsl_usb_io.h> |
| 255 | +#include "max3353.h" |
| 256 | + |
| 257 | +#define DRIVER_VERSION "1.0" |
| 258 | +#define DRIVER_AUTHOR "Freescale Semiconductor Inc." |
| 259 | +#define DRIVER_DESC "Freescale MAX3353 USBOTG Driver" |
| 260 | +#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC |
| 261 | + |
| 262 | +MODULE_DESCRIPTION("Freescale MAX3353 USBOTG Driver"); |
| 263 | + |
| 264 | +#if 0 |
| 265 | +#undef pr_debug |
| 266 | +#define pr_debug(x...) printk(x) |
| 267 | +#endif |
| 268 | + |
| 269 | +static const char driver_name[] = "max3353-otg"; |
| 270 | + |
| 271 | +const pm_message_t otg_suspend_state = { |
| 272 | + .event = 1, |
| 273 | +}; |
| 274 | + |
| 275 | +static volatile struct fsl_usb_device_regs *usb_dr_regs; |
| 276 | + |
| 277 | +struct otg_fsm { |
| 278 | + int id; /* 0=host 1=gadget */ |
| 279 | + struct otg_fsm_ops *ops; |
| 280 | + struct otg_transceiver *transceiver; |
| 281 | +}; |
| 282 | + |
| 283 | +struct otg_fsm_ops { |
| 284 | + int (*start_host)(struct otg_fsm *fsm, int on); |
| 285 | + int (*start_gadget)(struct otg_fsm *fsm, int on); |
| 286 | +}; |
| 287 | + |
| 288 | +struct max_otg { |
| 289 | + struct otg_transceiver otg; |
| 290 | + struct otg_fsm fsm; |
| 291 | + struct delayed_work otg_event; |
| 292 | + struct work_struct work_wq; |
| 293 | + u8 host_working; |
| 294 | + int irq; |
| 295 | +}; |
| 296 | + |
| 297 | +static struct max_otg *max_otg_dev; |
| 298 | + |
| 299 | +#define SET_OTG_STATE(otg_ptr, newstate) ((otg_ptr)->state = newstate) |
| 300 | + |
| 301 | + |
| 302 | +/* Reset controller, not reset the bus */ |
| 303 | +void otg_reset_controller(void) |
| 304 | +{ |
| 305 | + u32 command; |
| 306 | + |
| 307 | + command = fsl_readl(&usb_dr_regs->usbcmd); |
| 308 | + command |= (1 << 1); |
| 309 | + fsl_writel(command, &usb_dr_regs->usbcmd); |
| 310 | + while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1)) |
| 311 | + ; |
| 312 | +} |
| 313 | + |
| 314 | + |
| 315 | +/* Call suspend/resume routines in host driver */ |
| 316 | +static int maxotg_start_host(struct otg_fsm *fsm, int on) |
| 317 | +{ |
| 318 | + struct otg_transceiver *xceiv = fsm->transceiver; |
| 319 | + struct device *dev; |
| 320 | + struct max_otg *otg_dev = container_of(xceiv, struct max_otg, otg); |
| 321 | + u32 retval = 0; |
| 322 | + |
| 323 | + pr_debug("%s: host %s\n", __func__, on ? "on" : "off"); |
| 324 | + |
| 325 | + if (!xceiv->host) |
| 326 | + return -ENODEV; |
| 327 | + dev = xceiv->host->controller; |
| 328 | + |
| 329 | + if (on) { |
| 330 | + /* start fsl usb host controller */ |
| 331 | + if (otg_dev->host_working) |
| 332 | + goto end; |
| 333 | + else { |
| 334 | + otg_reset_controller(); |
| 335 | + pr_debug("host on......\n"); |
| 336 | + if (dev->driver->resume) |
| 337 | + retval = dev->driver->resume(dev); |
| 338 | + |
| 339 | + otg_dev->host_working = 1; |
| 340 | + } |
| 341 | + } else { |
| 342 | + /* stop fsl usb host controller */ |
| 343 | + if (!otg_dev->host_working) |
| 344 | + goto end; |
| 345 | + else { |
| 346 | + pr_debug("host off......\n"); |
| 347 | + if (dev && dev->driver) |
| 348 | + retval = dev->driver->suspend(dev, |
| 349 | + otg_suspend_state); |
| 350 | + otg_dev->host_working = 0; |
| 351 | + } |
| 352 | + } |
| 353 | +end: |
| 354 | + return retval; |
| 355 | +} |
| 356 | + |
| 357 | +/* Call suspend and resume function in udc driver |
| 358 | + * to stop and start udc driver. |
| 359 | + */ |
| 360 | +static int maxotg_start_gadget(struct otg_fsm *fsm, int on) |
| 361 | +{ |
| 362 | + struct otg_transceiver *xceiv = fsm->transceiver; |
| 363 | + struct device *dev; |
| 364 | + |
| 365 | + pr_debug("%s: gadget %s\n", __func__, on ? "on" : "off"); |
| 366 | + |
| 367 | + if (!xceiv->gadget || !xceiv->gadget->dev.parent) |
| 368 | + return -ENODEV; |
| 369 | + |
| 370 | + dev = xceiv->gadget->dev.parent; |
| 371 | + |
| 372 | + if (on) |
| 373 | + dev->driver->resume(dev); |
| 374 | + else |
| 375 | + dev->driver->suspend(dev, otg_suspend_state); |
| 376 | + |
| 377 | + return 0; |
| 378 | +} |
| 379 | + |
| 380 | + |
| 381 | +/* delayed interrupt handler */ |
| 382 | +static void handle_irq(struct work_struct *work) |
| 383 | +{ |
| 384 | + u8 latch; |
| 385 | + int id_host; |
| 386 | + struct otg_fsm *fsm = &max_otg_dev->fsm; |
| 387 | + struct otg_transceiver *otg = &max_otg_dev->otg; |
| 388 | + |
| 389 | + if (max_otg_dev == NULL) |
| 390 | + return; |
| 391 | + |
| 392 | + latch = max3353_read_reg(MAX3353_INTR_LATCH); |
| 393 | + |
| 394 | + if (latch) { |
| 395 | + id_host = max3353_read_id_pin(); |
| 396 | + fsm->id = !id_host; |
| 397 | + pr_debug("\t\t\t%s host mode %s\n", __func__, |
| 398 | + id_host ? "ON" : "OFF"); |
| 399 | + |
| 400 | + if (otg->host) |
| 401 | + otg->host->is_b_host = fsm->id; |
| 402 | + if (otg->gadget) |
| 403 | + otg->gadget->is_a_peripheral = !fsm->id; |
| 404 | + |
| 405 | + if (fsm->id) { /* switch to gadget */ |
| 406 | + schedule_delayed_work(&max_otg_dev->otg_event, 100); |
| 407 | + } else { /* switch to host */ |
| 408 | + cancel_delayed_work(&max_otg_dev->otg_event); |
| 409 | + maxotg_start_gadget(fsm, 0); |
| 410 | + maxotg_start_host(fsm, 1); |
| 411 | + } |
| 412 | + } |
| 413 | + enable_irq(MAX3353_IRQ); |
| 414 | +} |
| 415 | + |
| 416 | +DECLARE_DELAYED_WORK(max3353_dwq, handle_irq); |
| 417 | + |
| 418 | +/* |
| 419 | + * MAX3353 interrupt handler |
| 420 | + * |
| 421 | + * We're interested in ID pin changes. Since we can't do i2c |
| 422 | + * operations from interrupt context, we use a delayed workqueue |
| 423 | + * routine to clear the interrupt in the MAX3353, and to handle |
| 424 | + * the role switching. The delay also allows for debouncing the |
| 425 | + * state of the ID pin. To avoid the flood of interrupts between |
| 426 | + * the irq and its processing, we disable the irq here, and re-enable |
| 427 | + * it in the delayed routine. |
| 428 | + */ |
| 429 | +irqreturn_t max3353_isr(int irq, void *dev_id) |
| 430 | +{ |
| 431 | + disable_irq(MAX3353_IRQ); |
| 432 | + schedule_delayed_work(&max3353_dwq, 25); |
| 433 | + |
| 434 | + return IRQ_HANDLED; |
| 435 | +} |
| 436 | + |
| 437 | + |
| 438 | +/* Called by initialization code of host driver. Register host controller |
| 439 | + * to the OTG. Suspend host for OTG role detection. |
| 440 | + */ |
| 441 | +static int set_host(struct otg_transceiver *otg_p, struct usb_bus *host) |
| 442 | +{ |
| 443 | + struct max_otg *otg_dev = container_of(otg_p, struct max_otg, otg); |
| 444 | + |
| 445 | + pr_debug("%s() host %p\n", __func__, host); |
| 446 | + |
| 447 | + if (!otg_p || otg_dev != max_otg_dev) |
| 448 | + return -ENODEV; |
| 449 | + |
| 450 | + otg_p->host = host; |
| 451 | + if (host) { |
| 452 | + pr_debug("host off......\n"); |
| 453 | + |
| 454 | + /* must leave time for khubd to finish its thing |
| 455 | + * before yanking the host driver out from under it, |
| 456 | + * so suspend the host after a short delay. |
| 457 | + */ |
| 458 | + otg_dev->host_working = 1; |
| 459 | + schedule_delayed_work(&otg_dev->otg_event, 100); |
| 460 | + return 0; |
| 461 | + } else { /* host driver going away */ |
| 462 | + if (max3353_read_id_pin()) { |
| 463 | + /* Mini-A cable connected */ |
| 464 | + otg_p->state = OTG_STATE_UNDEFINED; |
| 465 | + } |
| 466 | + } |
| 467 | + |
| 468 | + otg_dev->host_working = 0; |
| 469 | + |
| 470 | + return 0; |
| 471 | +} |
| 472 | + |
| 473 | +/* Called by initialization code of udc. Register udc to OTG.*/ |
| 474 | +static int set_peripheral(struct otg_transceiver *otg_p, |
| 475 | + struct usb_gadget *gadget) |
| 476 | +{ |
| 477 | + struct max_otg *otg_dev = container_of(otg_p, struct max_otg, otg); |
| 478 | + |
| 479 | + pr_debug("%s gadget %p\n", __func__, gadget); |
| 480 | + |
| 481 | + pr_debug("otg_dev 0x%x\n", (int)otg_dev); |
| 482 | + pr_debug("max_otg_dev 0x%x\n", (int)max_otg_dev); |
| 483 | + |
| 484 | + if (!otg_p || otg_dev != max_otg_dev) |
| 485 | + return -ENODEV; |
| 486 | + |
| 487 | + if (!gadget) { |
| 488 | + if (!otg_dev->otg.default_a) |
| 489 | + otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); |
| 490 | + usb_gadget_vbus_disconnect(otg_dev->otg.gadget); |
| 491 | + otg_dev->otg.gadget = 0; |
| 492 | + return 0; |
| 493 | + } |
| 494 | + |
| 495 | + otg_p->gadget = gadget; |
| 496 | + otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; |
| 497 | + |
| 498 | + /* start the gadget right away if the ID pin says Mini-B */ |
| 499 | + pr_debug("ID pin=%d\n", otg_dev->fsm.id); |
| 500 | + if (otg_dev->fsm.id == 1) { |
| 501 | + maxotg_start_host(&otg_dev->fsm, 0); |
| 502 | + maxotg_start_gadget(&otg_dev->fsm, 1); |
| 503 | + } |
| 504 | + |
| 505 | + return 0; |
| 506 | +} |
| 507 | + |
| 508 | +/* Set OTG port power, only for B-device */ |
| 509 | +static int set_power(struct otg_transceiver *otg_p, unsigned mA) |
| 510 | +{ |
| 511 | + return 0; |
| 512 | +} |
| 513 | + |
| 514 | +/* Delayed pin detect interrupt processing. |
| 515 | + * |
| 516 | + * When the Mini-A cable is disconnected from the board, |
| 517 | + * the pin-detect interrupt happens before the disconnnect |
| 518 | + * interrupts for the connected device(s). In order to |
| 519 | + * process the disconnect interrupt(s) prior to switching |
| 520 | + * roles, the pin-detect interrupts are delayed, and handled |
| 521 | + * by this routine. |
| 522 | + */ |
| 523 | +static void maxotg_event(struct work_struct *work) |
| 524 | +{ |
| 525 | + struct max_otg *og = container_of(work, struct max_otg, otg_event.work); |
| 526 | + struct otg_fsm *fsm = &og->fsm; |
| 527 | + |
| 528 | + if (fsm->id) { /* switch to gadget */ |
| 529 | + maxotg_start_host(fsm, 0); |
| 530 | + maxotg_start_gadget(fsm, 1); |
| 531 | + } |
| 532 | +} |
| 533 | + |
| 534 | + |
| 535 | +static struct otg_fsm_ops maxotg_ops = { |
| 536 | + .start_host = maxotg_start_host, |
| 537 | + .start_gadget = maxotg_start_gadget, |
| 538 | +}; |
| 539 | + |
| 540 | + |
| 541 | +/* Initialize the global variable max_otg_dev and request IRQ for OTG */ |
| 542 | +static int maxotg_conf(struct platform_device *pdev) |
| 543 | +{ |
| 544 | + int status; |
| 545 | + struct max_otg *max_otg_tc; |
| 546 | + struct fsl_usb2_platform_data *pdata; |
| 547 | + |
| 548 | + pdata = pdev->dev.platform_data; |
| 549 | + |
| 550 | + pr_debug("%s\n", __func__); |
| 551 | + |
| 552 | + if (max_otg_dev) |
| 553 | + return 0; |
| 554 | + |
| 555 | + /* allocate space to fsl otg device */ |
| 556 | + max_otg_tc = kzalloc(sizeof(struct max_otg), GFP_KERNEL); |
| 557 | + if (!max_otg_tc) |
| 558 | + return -ENODEV; |
| 559 | + |
| 560 | + INIT_DELAYED_WORK(&max_otg_tc->otg_event, maxotg_event); |
| 561 | + |
| 562 | + /* Set OTG state machine operations */ |
| 563 | + max_otg_tc->fsm.ops = &maxotg_ops; |
| 564 | + |
| 565 | + /* initialize the otg structure */ |
| 566 | + max_otg_tc->otg.label = DRIVER_DESC; |
| 567 | + max_otg_tc->otg.set_host = set_host; |
| 568 | + max_otg_tc->otg.set_peripheral = set_peripheral; |
| 569 | + max_otg_tc->otg.set_power = set_power; |
| 570 | + |
| 571 | + max_otg_dev = max_otg_tc; |
| 572 | + pr_debug("%s: set max_otg_dev %p, fsm %p\n", __func__, |
| 573 | + max_otg_dev, &max_otg_dev->fsm); |
| 574 | + |
| 575 | + /* Store the otg transceiver */ |
| 576 | + status = otg_set_transceiver(&max_otg_tc->otg); |
| 577 | + if (status) { |
| 578 | + printk(KERN_WARNING ": unable to register OTG transceiver.\n"); |
| 579 | + return status; |
| 580 | + } |
| 581 | + |
| 582 | + return 0; |
| 583 | +} |
| 584 | + |
| 585 | +/* OTG Initialization*/ |
| 586 | +static int maxotg_start(struct platform_device *pdev) |
| 587 | +{ |
| 588 | + struct max_otg *p_otg; |
| 589 | + struct otg_transceiver *otg_trans = otg_get_transceiver(); |
| 590 | + struct otg_fsm *fsm; |
| 591 | + int status; |
| 592 | + struct resource *res; |
| 593 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 594 | + |
| 595 | + p_otg = container_of(otg_trans, struct max_otg, otg); |
| 596 | + fsm = &p_otg->fsm; |
| 597 | + |
| 598 | + /* Initialize the state machine structure with default values */ |
| 599 | + SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); |
| 600 | + fsm->transceiver = &p_otg->otg; |
| 601 | + |
| 602 | + /* We don't require predefined MEM/IRQ resource index */ |
| 603 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 604 | + if (!res) |
| 605 | + return -ENXIO; |
| 606 | + |
| 607 | + /* |
| 608 | + * We don't request_mem_region here to enable resource sharing |
| 609 | + * with host/device |
| 610 | + */ |
| 611 | + usb_dr_regs = ioremap(res->start, sizeof(struct fsl_usb_device_regs)); |
| 612 | + pdata->regs = (void *)usb_dr_regs; |
| 613 | + pr_debug("ioremap %x to %p\n", res->start, pdata->regs); |
| 614 | + |
| 615 | + if (pdata->init && pdata->init(pdev) != 0) |
| 616 | + return -EINVAL; |
| 617 | + |
| 618 | + /* grab the irq */ |
| 619 | + status = request_irq(MAX3353_IRQ, max3353_isr, IRQF_DISABLED, |
| 620 | + driver_name, p_otg); |
| 621 | + if (status) { |
| 622 | + printk(KERN_ERR "max3353: can't get IRQ, rc %d\n", status); |
| 623 | + return -EINVAL; |
| 624 | + } |
| 625 | + |
| 626 | + /* enable interrupts on the part */ |
| 627 | + pr_debug("%s: enabling MAX3353 interrupts\n", __func__); |
| 628 | + max3353_write_reg(MAX3353_INTR_MASK, IM_ID_GND_EN | IM_ID_FLOAT_EN); |
| 629 | + |
| 630 | + /* Export DR controller resources */ |
| 631 | + otg_set_resources(pdev->resource); |
| 632 | + |
| 633 | + /* record initial state of ID pin */ |
| 634 | + p_otg->fsm.id = !max3353_read_id_pin(); |
| 635 | + if (p_otg->fsm.id) |
| 636 | + p_otg->otg.state = OTG_STATE_UNDEFINED; |
| 637 | + else |
| 638 | + p_otg->otg.state = OTG_STATE_A_IDLE; |
| 639 | + |
| 640 | + pr_debug("initial ID pin: fsm.id=%d (%s)\n", p_otg->fsm.id, |
| 641 | + p_otg->fsm.id ? "gadget" : "host"); |
| 642 | + |
| 643 | + return 0; |
| 644 | +} |
| 645 | + |
| 646 | +static int __init maxotg_probe(struct platform_device *pdev) |
| 647 | +{ |
| 648 | + int status; |
| 649 | + struct fsl_usb2_platform_data *pdata; |
| 650 | + |
| 651 | + pr_debug("%s: pdev=0x%p\n", __func__, pdev); |
| 652 | + |
| 653 | + if (!pdev) |
| 654 | + return -ENODEV; |
| 655 | + |
| 656 | + if (!pdev->dev.platform_data) |
| 657 | + return -ENOMEM; |
| 658 | + |
| 659 | + pdata = pdev->dev.platform_data; |
| 660 | + fsl_set_usb_accessors(pdata); |
| 661 | + |
| 662 | + /* configure the OTG */ |
| 663 | + status = maxotg_conf(pdev); |
| 664 | + if (status) { |
| 665 | + printk(KERN_INFO "Couldn't init OTG module\n"); |
| 666 | + return -status; |
| 667 | + } |
| 668 | + |
| 669 | + /* start OTG */ |
| 670 | + status = maxotg_start(pdev); |
| 671 | + |
| 672 | + return status; |
| 673 | +} |
| 674 | + |
| 675 | +static int __exit maxotg_remove(struct platform_device *pdev) |
| 676 | +{ |
| 677 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 678 | + |
| 679 | + /* disable max3353 interrupts */ |
| 680 | + max3353_write_reg(MAX3353_INTR_MASK, 0); |
| 681 | + |
| 682 | + otg_set_transceiver(NULL); |
| 683 | + free_irq(MAX3353_IRQ, max_otg_dev); |
| 684 | + |
| 685 | + iounmap((void *)usb_dr_regs); |
| 686 | + |
| 687 | + kfree(max_otg_dev); |
| 688 | + max_otg_dev = NULL; |
| 689 | + |
| 690 | + if (pdata->exit) |
| 691 | + pdata->exit(pdev); |
| 692 | + |
| 693 | + return 0; |
| 694 | +} |
| 695 | + |
| 696 | +struct platform_driver max3353_otg_driver = { |
| 697 | + .probe = maxotg_probe, |
| 698 | + .remove = __exit_p(maxotg_remove), |
| 699 | + .driver = { |
| 700 | + .name = driver_name, |
| 701 | + .owner = THIS_MODULE, |
| 702 | + }, |
| 703 | +}; |
| 704 | + |
| 705 | + |
| 706 | +static int __init maxotg_init(void) |
| 707 | +{ |
| 708 | + printk(KERN_INFO DRIVER_DESC " loaded, %s\n", DRIVER_VERSION); |
| 709 | + return platform_driver_register(&max3353_otg_driver); |
| 710 | +} |
| 711 | + |
| 712 | +static void __exit maxotg_exit(void) |
| 713 | +{ |
| 714 | + platform_driver_unregister(&max3353_otg_driver); |
| 715 | + printk(KERN_INFO DRIVER_DESC " unloaded\n"); |
| 716 | +} |
| 717 | + |
| 718 | +module_init(maxotg_init); |
| 719 | +module_exit(maxotg_exit); |
| 720 | + |
| 721 | +MODULE_DESCRIPTION(DRIVER_INFO); |
| 722 | +MODULE_AUTHOR(DRIVER_AUTHOR); |
| 723 | +MODULE_LICENSE("GPL"); |
| 724 | --- /dev/null |
| 725 | +++ b/arch/m68k/coldfire/m5441x/max3353_xc.c |
| 726 | @@ -0,0 +1,310 @@ |
| 727 | +/* |
| 728 | + * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. |
| 729 | + * |
| 730 | + * This program is free software; you can redistribute it and/or modify it |
| 731 | + * under the terms of the GNU General Public License as published by the |
| 732 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 733 | + * option) any later version. |
| 734 | + * |
| 735 | + * This program is distributed in the hope that it will be useful, but |
| 736 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 737 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 738 | + * General Public License for more details. |
| 739 | + * |
| 740 | + * You should have received a copy of the GNU General Public License along |
| 741 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 742 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 743 | + */ |
| 744 | +#define DEBUG |
| 745 | +#include <linux/module.h> |
| 746 | +#include <linux/kernel.h> |
| 747 | +#include <linux/types.h> |
| 748 | +#include <linux/init.h> |
| 749 | +#include <linux/slab.h> |
| 750 | +#include <linux/io.h> |
| 751 | +#include <linux/i2c.h> |
| 752 | +#include <linux/usb/fsl_xcvr.h> |
| 753 | +#include <asm/mcfsim.h> |
| 754 | +#include "max3353.h" |
| 755 | + |
| 756 | +#define DRIVER_DESC "Freescale MAX3353 Driver" |
| 757 | + |
| 758 | +static struct i2c_device_id max3353_id[] = { |
| 759 | + {"max3353", 0}, |
| 760 | + {} |
| 761 | +}; |
| 762 | +MODULE_DEVICE_TABLE(i2c, max3353_id); |
| 763 | + |
| 764 | +struct max3353_state { |
| 765 | + struct i2c_client *client; |
| 766 | +}; |
| 767 | + |
| 768 | +static int max3353_probe(struct i2c_client *client, |
| 769 | + const struct i2c_device_id *id); |
| 770 | +static int __devexit max3353_remove(struct i2c_client *client); |
| 771 | + |
| 772 | +static struct i2c_driver max3353_i2c_driver = { |
| 773 | + .driver = { |
| 774 | + .owner = THIS_MODULE, |
| 775 | + .name = "max3353", |
| 776 | + }, |
| 777 | + .probe = max3353_probe, |
| 778 | + .remove = __devexit_p(max3353_remove), |
| 779 | + .id_table = max3353_id, |
| 780 | +}; |
| 781 | + |
| 782 | +static struct i2c_client *max3353_i2c_client; |
| 783 | + |
| 784 | +/* Write a max3353 register*/ |
| 785 | +void max3353_write_reg(u8 reg, u8 data) |
| 786 | +{ |
| 787 | + i2c_smbus_write_byte_data(max3353_i2c_client, reg, data); |
| 788 | +} |
| 789 | +EXPORT_SYMBOL(max3353_write_reg); |
| 790 | + |
| 791 | +/* Read a max3353 register*/ |
| 792 | +u8 max3353_read_reg(u8 reg) |
| 793 | +{ |
| 794 | + return i2c_smbus_read_byte_data(max3353_i2c_client, reg); |
| 795 | +} |
| 796 | +EXPORT_SYMBOL(max3353_read_reg); |
| 797 | + |
| 798 | +/* |
| 799 | + * max3353 I2C probe function |
| 800 | + */ |
| 801 | + |
| 802 | +static int max3353_probe(struct i2c_client *client, |
| 803 | + const struct i2c_device_id *id) |
| 804 | +{ |
| 805 | + struct max3353_state *state; |
| 806 | + struct device *dev = &client->dev; |
| 807 | + |
| 808 | + state = kzalloc(sizeof(struct max3353_state), GFP_KERNEL); |
| 809 | + if (state == NULL) { |
| 810 | + dev_err(dev, "failed to create our state\n"); |
| 811 | + return -ENOMEM; |
| 812 | + } |
| 813 | + |
| 814 | + state->client = client; |
| 815 | + i2c_set_clientdata(client, state); |
| 816 | + |
| 817 | + max3353_i2c_client = client; |
| 818 | + |
| 819 | + /* rest of the initialisation goes here. */ |
| 820 | + printk(KERN_INFO "MAX3353 USB charge pump detected\n"); |
| 821 | + pr_debug("MANUF:%02x %02x %02x %02x PID:%02x %02x %02x %02x\n", |
| 822 | + max3353_read_reg(MAX3353_MAN0), |
| 823 | + max3353_read_reg(MAX3353_MAN1), |
| 824 | + max3353_read_reg(MAX3353_MAN2), |
| 825 | + max3353_read_reg(MAX3353_MAN3), |
| 826 | + max3353_read_reg(MAX3353_PID0), |
| 827 | + max3353_read_reg(MAX3353_PID1), |
| 828 | + max3353_read_reg(MAX3353_PID2), |
| 829 | + max3353_read_reg(MAX3353_PID3)); |
| 830 | + pr_debug("%s done\n", __func__); |
| 831 | + |
| 832 | + return 0; |
| 833 | + |
| 834 | +} |
| 835 | + |
| 836 | +/* |
| 837 | + * max3353 I2C remove function |
| 838 | + */ |
| 839 | +static int __devexit max3353_remove(struct i2c_client *client) |
| 840 | +{ |
| 841 | + struct max3353_state *state = i2c_get_clientdata(client); |
| 842 | + |
| 843 | + max3353_i2c_client = NULL; |
| 844 | + |
| 845 | + kfree(state); |
| 846 | + return 0; |
| 847 | +} |
| 848 | + |
| 849 | +static int max3353_running; |
| 850 | + |
| 851 | +static void max3353_init(struct fsl_xcvr_ops *this) |
| 852 | +{ |
| 853 | + int __maybe_unused rc; |
| 854 | + u8 tmp; |
| 855 | + |
| 856 | + pr_debug("%s\n", __func__); |
| 857 | + |
| 858 | + if (!max3353_running) { |
| 859 | + i2c_add_driver(&max3353_i2c_driver); |
| 860 | + |
| 861 | + /* disable interrupts on the part */ |
| 862 | + max3353_write_reg(MAX3353_INTR_MASK, 0); |
| 863 | + |
| 864 | + /* configure irq mode */ |
| 865 | + tmp = max3353_read_reg(MAX3353_CR1); |
| 866 | + tmp |= CR1_IRQ_PUSH_PULL; |
| 867 | + max3353_write_reg(MAX3353_CR1, tmp); |
| 868 | + |
| 869 | + /* take the part out of shutdown */ |
| 870 | + tmp = max3353_read_reg(MAX3353_CR2); |
| 871 | + tmp &= ~CR2_SHUTDOWN; /* turn on the part */ |
| 872 | + max3353_write_reg(MAX3353_CR2, tmp); |
| 873 | + } |
| 874 | + max3353_running++; |
| 875 | +#if 0 |
| 876 | + /* configure INT2 for max3353 INT */ |
| 877 | + MCF_GPIO_PAR_IRQ0L = |
| 878 | + (MCF_GPIO_PAR_IRQ0L & MCF_GPIO_PAR_IRQL_IRQ2_MASK) | |
| 879 | + MCF_GPIO_PAR_IRQL_IRQ2_IRQ2; |
| 880 | +#else |
| 881 | + /* |
| 882 | + MCF_GPIO_PAR_IRQ0H |= MCF_GPIO_PAR_IRQH_IRQ7; |
| 883 | + MCF_EPORT_EPPAR = MCF_EPORT_EPPAR | MCF_EPORT_EPPAR_EPPA7_LEVEL; |
| 884 | + MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE7; |
| 885 | + MCF_INTC0_ICR7 = 2; |
| 886 | + */ |
| 887 | + /* use IRQ4 on Twr-Ser1 board by J11 selected */ |
| 888 | + MCF_GPIO_PAR_IRQ0H |= MCF_GPIO_PAR_IRQH_IRQ4_IRQ4; |
| 889 | + MCF_EPORT_EPPAR &= ~MCF_EPORT_EPPAR_EPPA4_LEVEL; |
| 890 | + MCF_EPORT_EPIER = MCF_EPORT_EPIER | MCF_EPORT_EPIER_EPIE4; |
| 891 | + MCF_INTC0_ICR4 = 7; |
| 892 | + |
| 893 | +#endif |
| 894 | + /* Configure USB_DP_PDOWN/USB_DM_PDOWN */ |
| 895 | + MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT0; |
| 896 | + MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT1; |
| 897 | + MCF_GPIO_PDDR_I |= 0xc0; |
| 898 | + MCF_GPIO_PODR_I &= 0x3f; |
| 899 | + |
| 900 | + /* Enable VBUS_EN and VBUS_OC signals */ |
| 901 | + MCF_GPIO_PAR_TIMER = |
| 902 | + (MCF_GPIO_PAR_TIMER & |
| 903 | + MCF_GPIO_PAR_TIMER_T3IN_MASK) | |
| 904 | + MCF_GPIO_PAR_TIMER_T3IN_USB0_VBUSEN; |
| 905 | + |
| 906 | + MCF_GPIO_PAR_TIMER = |
| 907 | + (MCF_GPIO_PAR_TIMER & |
| 908 | + MCF_GPIO_PAR_TIMER_T0IN_MASK) | |
| 909 | + MCF_GPIO_PAR_TIMER_T0IN_USBO_VBUSOC; |
| 910 | + |
| 911 | + /* Setup USB_VBUS_OC signal to be active-low */ |
| 912 | + MCF_CCM_MISCCR &= (~MCF_CCM_MISCCR_USBOOC); |
| 913 | + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBPUE; |
| 914 | +} |
| 915 | + |
| 916 | +static void max3353_uninit(struct fsl_xcvr_ops *this) |
| 917 | +{ |
| 918 | + pr_debug("%s\n", __func__); |
| 919 | + |
| 920 | + max3353_running--; |
| 921 | + if (!max3353_running) |
| 922 | + i2c_del_driver(&max3353_i2c_driver); |
| 923 | +} |
| 924 | + |
| 925 | +/* set max3353 as USB host */ |
| 926 | +static inline void max3353_set_host(void) |
| 927 | +{ |
| 928 | + u8 cr1, cr2, status; |
| 929 | + pr_debug("%s\n", __func__); |
| 930 | + |
| 931 | + /* configure transceiver for host mode */ |
| 932 | + cr1 = max3353_read_reg(MAX3353_CR1); |
| 933 | + cr2 = max3353_read_reg(MAX3353_CR2); |
| 934 | + status = max3353_read_reg(MAX3353_STATUS); |
| 935 | + pr_debug("before: CR1 %02x CR2 %02x STATUS %02x\n", cr1, cr2, status); |
| 936 | + |
| 937 | + cr1 &= ~(CR1_DM_PULLDOWN | CR1_DP_PULLDOWN | |
| 938 | + CR1_DM_PULLUP | CR1_DP_PULLUP); |
| 939 | + cr1 |= (CR1_DP_PULLDOWN | CR1_DM_PULLDOWN); |
| 940 | + max3353_write_reg(MAX3353_CR1, cr1); |
| 941 | + |
| 942 | + cr1 = max3353_read_reg(MAX3353_CR1); |
| 943 | + cr2 = max3353_read_reg(MAX3353_CR2); |
| 944 | + status = max3353_read_reg(MAX3353_STATUS); |
| 945 | + pr_debug(" after: CR1 %02x CR2 %02x STATUS %02x\n", cr1, cr2, status); |
| 946 | +} |
| 947 | + |
| 948 | +/* set max3353 as USB device */ |
| 949 | +static inline void max3353_set_dev(void) |
| 950 | +{ |
| 951 | + u8 cr1; |
| 952 | + pr_debug("%s\n", __func__); |
| 953 | + |
| 954 | + /* FS mode, DP pull up */ |
| 955 | + cr1 = max3353_read_reg(MAX3353_CR1); |
| 956 | + cr1 &= ~(CR1_DM_PULLDOWN | CR1_DM_PULLDOWN | CR1_DP_PULLDOWN); |
| 957 | + cr1 |= CR1_DP_PULLUP; |
| 958 | + max3353_write_reg(MAX3353_CR1, cr1); |
| 959 | + |
| 960 | +} |
| 961 | + |
| 962 | +static void max3353_set_vbus_power(struct fsl_xcvr_ops *this, int on) |
| 963 | +{ |
| 964 | + pr_debug("%s(on=%d)\n", __func__, on); |
| 965 | +} |
| 966 | + |
| 967 | + |
| 968 | +/* Enable or disable the D+ pullup. */ |
| 969 | +static void max3353_pullup(int on) |
| 970 | +{ |
| 971 | + u8 cr1; |
| 972 | + unsigned short ccm; |
| 973 | + |
| 974 | + pr_debug("%s(%d)\n", __func__, on); |
| 975 | + |
| 976 | + cr1 = max3353_read_reg(MAX3353_CR1); |
| 977 | + cr1 &= ~(CR1_DM_PULLDOWN | CR1_DP_PULLDOWN | |
| 978 | + CR1_DM_PULLUP | CR1_DP_PULLUP); |
| 979 | + |
| 980 | + ccm = MCF_CCM_UOCSR; |
| 981 | + if (on) { |
| 982 | + cr1 |= CR1_DP_PULLUP; |
| 983 | + ccm |= MCF_CCM_UOCSR_BVLD; |
| 984 | + ccm &= ~MCF_CCM_UOCSR_SEND; |
| 985 | + } else { |
| 986 | + ccm &= ~MCF_CCM_UOCSR_BVLD; |
| 987 | + } |
| 988 | + |
| 989 | + max3353_write_reg(MAX3353_CR1, cr1); |
| 990 | + MCF_CCM_UOCSR = ccm; |
| 991 | +} |
| 992 | + |
| 993 | +/* |
| 994 | + * return the state of the ID pin. |
| 995 | + * return: 0 Mini-B or nothing connected (Gadget mode) |
| 996 | + * 1 Mini-A connected (Host mode) |
| 997 | + */ |
| 998 | +int max3353_read_id_pin(void) |
| 999 | +{ |
| 1000 | + u8 status = max3353_read_reg(MAX3353_STATUS); |
| 1001 | + return !!(status & STATUS_ID_GND); |
| 1002 | +} |
| 1003 | +EXPORT_SYMBOL(max3353_read_id_pin); |
| 1004 | + |
| 1005 | +static struct fsl_xcvr_ops max3353_ops = { |
| 1006 | + .name = "dr-max3353", |
| 1007 | + .init = max3353_init, |
| 1008 | + .uninit = max3353_uninit, |
| 1009 | + .set_host = max3353_set_host, |
| 1010 | + .set_device = max3353_set_dev, |
| 1011 | + .set_vbus_power = max3353_set_vbus_power, |
| 1012 | + .pullup = max3353_pullup, |
| 1013 | +}; |
| 1014 | + |
| 1015 | +/* module init routine. register the transceiver */ |
| 1016 | +static int __init max3353xc_init(void) |
| 1017 | +{ |
| 1018 | + pr_debug("%s\n", __func__); |
| 1019 | + |
| 1020 | + fsl_usb_xcvr_register(&max3353_ops); |
| 1021 | + return 0; |
| 1022 | +} |
| 1023 | + |
| 1024 | +static void __exit max3353xc_exit(void) |
| 1025 | +{ |
| 1026 | + pr_debug("%s\n", __func__); |
| 1027 | + fsl_usb_xcvr_unregister(&max3353_ops); |
| 1028 | +} |
| 1029 | + |
| 1030 | +module_init(max3353xc_init); |
| 1031 | +module_exit(max3353xc_exit); |
| 1032 | + |
| 1033 | +MODULE_ALIAS("max3353"); |
| 1034 | +MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
| 1035 | +MODULE_DESCRIPTION("max3353 transceiver driver"); |
| 1036 | +MODULE_LICENSE("GPL"); |
| 1037 | --- /dev/null |
| 1038 | +++ b/arch/m68k/coldfire/m5441x/usb.c |
| 1039 | @@ -0,0 +1,276 @@ |
| 1040 | +/* |
| 1041 | + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 1042 | + * |
| 1043 | + * The code contained herein is licensed under the GNU General Public |
| 1044 | + * License. You may obtain a copy of the GNU General Public License |
| 1045 | + * Version 2 or later at the following locations: |
| 1046 | + * |
| 1047 | + * http://www.opensource.org/licenses/gpl-license.html |
| 1048 | + * http://www.gnu.org/copyleft/gpl.html |
| 1049 | + */ |
| 1050 | +#include <linux/module.h> |
| 1051 | +#include <linux/kernel.h> |
| 1052 | +#include <linux/types.h> |
| 1053 | +#include <linux/errno.h> |
| 1054 | +#include <linux/err.h> |
| 1055 | +#include <linux/platform_device.h> |
| 1056 | +#include <linux/fsl_devices.h> |
| 1057 | +#include <linux/usb/fsl_xcvr.h> |
| 1058 | +#include <asm/mcfsim.h> |
| 1059 | + |
| 1060 | +#define MCF_SCM_BCR MCF_REG32(0xFC040024) |
| 1061 | +#define MCF_SCM_BCR_GBR (1 << 9) /* global bursts for read */ |
| 1062 | +#define MCF_SCM_BCR_GBW (1 << 8) /* global bursts for write */ |
| 1063 | +#define MCF_SCM_BCR_SBE_ALL (0xff << 0) /* slave burst enable */ |
| 1064 | + |
| 1065 | +#define MAX_XCVR 3 |
| 1066 | +struct fsl_xcvr_ops *g_xc_ops[MAX_XCVR] = { NULL }; |
| 1067 | + |
| 1068 | +#ifdef ULPI_DEBUG |
| 1069 | +void print_ulpi_regs(void) |
| 1070 | +{ |
| 1071 | + pr_debug("MCF_SCM_BCR=0x%08lx MCF_CCM_MISCCR=0x%08x " |
| 1072 | + "MCF_CCM_MISSCR2=0x%08x " |
| 1073 | + "MCF_GPIO_PAR_TIMER=0x%08x MCF_GPIO_PAR_FEC=08%08x " |
| 1074 | + "MCF_GPIO_PAR_SIMP0H=08%08x MCF_GPIO_PODR_G=08%08x\n", |
| 1075 | + MCF_SCM_BCR, MCF_CCM_MISCCR, |
| 1076 | + MCF_CCM_MISCCR2, MCF_GPIO_PAR_TIMER, |
| 1077 | + MCF_GPIO_PAR_FEC, MCF_GPIO_PAR_SIMP0H, MCF_GPIO_PODR_G); |
| 1078 | +} |
| 1079 | +EXPORT_SYMBOL(print_ulpi_regs); |
| 1080 | +#endif |
| 1081 | + |
| 1082 | +static inline void fsl_usb_enable_clk(void) |
| 1083 | +{ |
| 1084 | + pr_debug("%s\n", __func__); |
| 1085 | + |
| 1086 | +#if defined(CONFIG_USB_M5441X_MAX3353_FSLS) |
| 1087 | + MCF_PM_PPMCR0 = 0x30; |
| 1088 | + MCF_CCM_MISCCR &= ~(MCF_CCM_MISCCR_USBOOC | MCF_CCM_MISCCR_USBHOC); |
| 1089 | + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBSRC; |
| 1090 | +#elif !defined(CONFIG_USB_M5441X_PLLCLK) |
| 1091 | + /* Use external clock source if PLL isn't a multiple of 60MHz */ |
| 1092 | + MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_USBSRC; |
| 1093 | + |
| 1094 | + /* Initialize the USB Clock: use USB input clock */ |
| 1095 | + MCF_GPIO_PAR_IRQ0L = |
| 1096 | + (MCF_GPIO_PAR_IRQ0L & |
| 1097 | + MCF_GPIO_PAR_IRQL_IRQ6_MASK) | |
| 1098 | + MCF_GPIO_PAR_IRQL_IRQ6_USBCLKIN; |
| 1099 | +#else |
| 1100 | + uint fvco, usbclk; |
| 1101 | + |
| 1102 | + fvco = CONFIG_MCFCLK * ((MCF_PLL_DR & MCF_PLL_DR_OUTDIV1) + 1); |
| 1103 | + usbclk = fvco / (((MCF_PLL_DR & MCF_PLL_DR_OUTDIV4) >> 16) + 1); |
| 1104 | + |
| 1105 | + if (usbclk != 60000000) |
| 1106 | + printk(KERN_ERR, "The usb host clock must be 60MHZ!\n\n"); |
| 1107 | + |
| 1108 | + MCF_PM_PPMCR0 = 0x30; |
| 1109 | + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBSRC; |
| 1110 | +#endif |
| 1111 | +} |
| 1112 | + |
| 1113 | +static inline void fsl_usb_disable_clk(void) |
| 1114 | +{ |
| 1115 | + pr_debug("%s\n", __func__); |
| 1116 | +} |
| 1117 | + |
| 1118 | +void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops) |
| 1119 | +{ |
| 1120 | + int i; |
| 1121 | + |
| 1122 | + pr_debug("%s '%s'\n", __func__, xcvr_ops->name); |
| 1123 | + for (i = 0; i < MAX_XCVR; i++) { |
| 1124 | + if (g_xc_ops[i] == NULL) { |
| 1125 | + g_xc_ops[i] = xcvr_ops; |
| 1126 | + return; |
| 1127 | + } |
| 1128 | + } |
| 1129 | + |
| 1130 | + pr_debug("%s failed\n", __func__); |
| 1131 | +} |
| 1132 | +EXPORT_SYMBOL_GPL(fsl_usb_xcvr_register); |
| 1133 | + |
| 1134 | +void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops) |
| 1135 | +{ |
| 1136 | + int i; |
| 1137 | + |
| 1138 | + pr_debug("%s '%s'\n", __func__, xcvr_ops->name); |
| 1139 | + for (i = 0; i < MAX_XCVR; i++) { |
| 1140 | + if (g_xc_ops[i] == xcvr_ops) { |
| 1141 | + g_xc_ops[i] = NULL; |
| 1142 | + return; |
| 1143 | + } |
| 1144 | + } |
| 1145 | + |
| 1146 | + pr_debug("%s failed\n", __func__); |
| 1147 | +} |
| 1148 | +EXPORT_SYMBOL_GPL(fsl_usb_xcvr_unregister); |
| 1149 | + |
| 1150 | +static struct fsl_xcvr_ops *fsl_usb_get_xcvr(char *name) |
| 1151 | +{ |
| 1152 | + int i; |
| 1153 | + |
| 1154 | + pr_debug("%s '%s'\n", __func__, name); |
| 1155 | + if (name == NULL) { |
| 1156 | + printk(KERN_ERR "get_xcvr(): No tranceiver name\n"); |
| 1157 | + return NULL; |
| 1158 | + } |
| 1159 | + |
| 1160 | + for (i = 0; i < MAX_XCVR; i++) { |
| 1161 | + if (strcmp(g_xc_ops[i]->name, name) == 0) |
| 1162 | + return g_xc_ops[i]; |
| 1163 | + } |
| 1164 | + pr_debug("Failed %s\n", __func__); |
| 1165 | + return NULL; |
| 1166 | +} |
| 1167 | + |
| 1168 | +/* The dmamask must be set for EHCI to work */ |
| 1169 | +static u64 ehci_dmamask = ~(u32) 0; |
| 1170 | + |
| 1171 | +/*! |
| 1172 | + * Register an instance of a USB host platform device. |
| 1173 | + * |
| 1174 | + * @param res: resource pointer |
| 1175 | + * @param n_res: number of resources |
| 1176 | + * @param config: config pointer |
| 1177 | + * |
| 1178 | + * @return newly-registered platform_device |
| 1179 | + * |
| 1180 | + * Each supported host interface is registered as an instance |
| 1181 | + * of the "fsl-ehci" device. Call this function multiple times |
| 1182 | + * to register each host interface. |
| 1183 | + */ |
| 1184 | +static int instance_id; |
| 1185 | +struct platform_device *host_pdev_register(struct resource *res, int n_res, |
| 1186 | + struct fsl_usb2_platform_data *config) |
| 1187 | +{ |
| 1188 | + struct platform_device *pdev; |
| 1189 | + int rc; |
| 1190 | + |
| 1191 | + pr_debug("register host res=0x%p, size=%d\n", res, n_res); |
| 1192 | + |
| 1193 | + pdev = platform_device_register_simple("fsl-ehci", |
| 1194 | + instance_id, res, n_res); |
| 1195 | + if (IS_ERR(pdev)) { |
| 1196 | + printk(KERN_ERR "usb: can't register %s Host, %ld\n", |
| 1197 | + config->name, PTR_ERR(pdev)); |
| 1198 | + return NULL; |
| 1199 | + } |
| 1200 | + |
| 1201 | + pdev->dev.coherent_dma_mask = 0xffffffff; |
| 1202 | + pdev->dev.dma_mask = &ehci_dmamask; |
| 1203 | + |
| 1204 | + rc = platform_device_add_data(pdev, config, |
| 1205 | + sizeof(struct fsl_usb2_platform_data)); |
| 1206 | + if (rc) { |
| 1207 | + platform_device_unregister(pdev); |
| 1208 | + return NULL; |
| 1209 | + } |
| 1210 | + |
| 1211 | + printk(KERN_INFO "usb: %s host (%s) registered\n", config->name, |
| 1212 | + config->transceiver); |
| 1213 | + pr_debug("pdev=0x%p dev=0x%p resources=0x%p pdata=0x%p\n", |
| 1214 | + pdev, &pdev->dev, pdev->resource, pdev->dev.platform_data); |
| 1215 | + |
| 1216 | + instance_id++; |
| 1217 | + |
| 1218 | + return pdev; |
| 1219 | +} |
| 1220 | + |
| 1221 | +int usb_platform_host_init(struct platform_device *pdev) |
| 1222 | +{ |
| 1223 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 1224 | + struct fsl_xcvr_ops *xops; |
| 1225 | + |
| 1226 | + xops = fsl_usb_get_xcvr(pdata->transceiver); |
| 1227 | + if (!xops) { |
| 1228 | + printk(KERN_ERR "DR transceiver ops missing\n"); |
| 1229 | + return -EINVAL; |
| 1230 | + } |
| 1231 | + pdata->xcvr_ops = xops; |
| 1232 | + pdata->xcvr_type = xops->xcvr_type; |
| 1233 | + pdata->pdev = pdev; |
| 1234 | + xops->pdata = pdata; |
| 1235 | + |
| 1236 | + if (pdata->gpio_usb_active) |
| 1237 | + if (pdata->gpio_usb_active()) |
| 1238 | + return -EINVAL; |
| 1239 | + |
| 1240 | + /* enable USB read, write and slave bursts */ |
| 1241 | + MCF_SCM_BCR = MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW | MCF_SCM_BCR_SBE_ALL; |
| 1242 | + fsl_usb_enable_clk(); |
| 1243 | + |
| 1244 | + if (xops->init) |
| 1245 | + xops->init(xops); |
| 1246 | + |
| 1247 | + return 0; |
| 1248 | +} |
| 1249 | + |
| 1250 | +void usb_platform_host_uninit(struct platform_device *pdev) |
| 1251 | +{ |
| 1252 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 1253 | + |
| 1254 | + if (pdata->xcvr_ops && pdata->xcvr_ops->uninit) |
| 1255 | + pdata->xcvr_ops->uninit(pdata->xcvr_ops); |
| 1256 | + |
| 1257 | + pdata->regs = NULL; |
| 1258 | + |
| 1259 | + if (pdata->gpio_usb_inactive) |
| 1260 | + pdata->gpio_usb_inactive(); |
| 1261 | + |
| 1262 | + fsl_usb_disable_clk(); |
| 1263 | +} |
| 1264 | + |
| 1265 | + |
| 1266 | +static int dr_used; |
| 1267 | + |
| 1268 | +int usb_platform_dr_init(struct platform_device *pdev) |
| 1269 | +{ |
| 1270 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 1271 | + struct fsl_xcvr_ops *xops; |
| 1272 | + |
| 1273 | + pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata); |
| 1274 | + |
| 1275 | + xops = fsl_usb_get_xcvr(pdata->transceiver); |
| 1276 | + if (!xops) { |
| 1277 | + printk(KERN_ERR "DR transceiver ops missing\n"); |
| 1278 | + return -EINVAL; |
| 1279 | + } |
| 1280 | + pdata->xcvr_ops = xops; |
| 1281 | + pdata->xcvr_type = xops->xcvr_type; |
| 1282 | + pdata->pdev = pdev; |
| 1283 | + xops->pdata = pdata; |
| 1284 | + |
| 1285 | + /* enable USB read, write and slave bursts */ |
| 1286 | + MCF_SCM_BCR = MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW | MCF_SCM_BCR_SBE_ALL; |
| 1287 | + |
| 1288 | + if (!dr_used) { |
| 1289 | + fsl_usb_enable_clk(); |
| 1290 | + |
| 1291 | + if (xops->init) |
| 1292 | + xops->init(xops); |
| 1293 | + } |
| 1294 | + |
| 1295 | + dr_used++; |
| 1296 | + pr_debug("%s: success\n", __func__); |
| 1297 | + return 0; |
| 1298 | +} |
| 1299 | +EXPORT_SYMBOL_GPL(usb_platform_dr_init); |
| 1300 | + |
| 1301 | +void usb_platform_dr_uninit(struct platform_device *pdev) |
| 1302 | +{ |
| 1303 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 1304 | + pr_debug("%s\n", __func__); |
| 1305 | + |
| 1306 | + dr_used--; |
| 1307 | + if (!dr_used) { |
| 1308 | + if (pdata->xcvr_ops && pdata->xcvr_ops->uninit) |
| 1309 | + pdata->xcvr_ops->uninit(pdata->xcvr_ops); |
| 1310 | + |
| 1311 | + pdata->regs = NULL; |
| 1312 | + fsl_usb_disable_clk(); |
| 1313 | + } |
| 1314 | +} |
| 1315 | +EXPORT_SYMBOL_GPL(usb_platform_dr_uninit); |
| 1316 | --- /dev/null |
| 1317 | +++ b/arch/m68k/coldfire/m5441x/usb.h |
| 1318 | @@ -0,0 +1,76 @@ |
| 1319 | +/* |
| 1320 | + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 1321 | + */ |
| 1322 | + |
| 1323 | +/* |
| 1324 | + * The code contained herein is licensed under the GNU General Public |
| 1325 | + * License. You may obtain a copy of the GNU General Public License |
| 1326 | + * Version 2 or later at the following locations: |
| 1327 | + * |
| 1328 | + * http://www.opensource.org/licenses/gpl-license.html |
| 1329 | + * http://www.gnu.org/copyleft/gpl.html |
| 1330 | + */ |
| 1331 | + |
| 1332 | +extern int usb_platform_host_init(struct platform_device *pdev); |
| 1333 | +extern void usb_platform_host_uninit(struct fsl_usb2_platform_data *pdata); |
| 1334 | +extern int usb_platform_dr_init(struct platform_device *pdev); |
| 1335 | +extern void usb_platform_dr_uninit(struct fsl_usb2_platform_data *pdata); |
| 1336 | +extern struct platform_device *host_pdev_register(struct resource *res, |
| 1337 | + int n_res, struct fsl_usb2_platform_data *config); |
| 1338 | + |
| 1339 | + |
| 1340 | +#if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_EHCI_HCD_MODULE |
| 1341 | +static inline void dr_register_host(struct resource *r, int rs) |
| 1342 | +{ |
| 1343 | + PDATA->operating_mode = DR_HOST_MODE; |
| 1344 | + host_pdev_register(r, rs, PDATA); |
| 1345 | +} |
| 1346 | +#else |
| 1347 | +static inline void dr_register_host(struct resource *r, int rs) |
| 1348 | +{ |
| 1349 | +} |
| 1350 | +#endif |
| 1351 | + |
| 1352 | +#ifdef CONFIG_USB_GADGET_FSL_USB2 |
| 1353 | +static struct platform_device dr_udc_device; |
| 1354 | + |
| 1355 | +static inline void dr_register_udc(void) |
| 1356 | +{ |
| 1357 | + PDATA->operating_mode = DR_UDC_MODE; |
| 1358 | + dr_udc_device.dev.platform_data = PDATA; |
| 1359 | + |
| 1360 | + if (platform_device_register(&dr_udc_device)) |
| 1361 | + printk(KERN_ERR "usb: can't register DR gadget\n"); |
| 1362 | + else |
| 1363 | + printk(KERN_INFO "usb: DR gadget (%s) registered\n", |
| 1364 | + PDATA->transceiver); |
| 1365 | +} |
| 1366 | +#else |
| 1367 | +static inline void dr_register_udc(void) |
| 1368 | +{ |
| 1369 | +} |
| 1370 | +#endif |
| 1371 | + |
| 1372 | +#ifdef CONFIG_USB_OTG |
| 1373 | +static struct platform_device dr_otg_device; |
| 1374 | + |
| 1375 | +/* |
| 1376 | + * set the proper operating_mode and |
| 1377 | + * platform_data pointer, then register the |
| 1378 | + * device. |
| 1379 | + */ |
| 1380 | +static inline void dr_register_otg(void) |
| 1381 | +{ |
| 1382 | + PDATA->operating_mode = FSL_USB2_DR_OTG; |
| 1383 | + dr_otg_device.dev.platform_data = PDATA; |
| 1384 | + |
| 1385 | + if (platform_device_register(&dr_otg_device)) |
| 1386 | + printk(KERN_ERR "usb: can't register otg device\n"); |
| 1387 | + else |
| 1388 | + printk(KERN_INFO "usb: DR OTG registered\n"); |
| 1389 | +} |
| 1390 | +#else |
| 1391 | +static inline void dr_register_otg(void) |
| 1392 | +{ |
| 1393 | +} |
| 1394 | +#endif |
| 1395 | --- /dev/null |
| 1396 | +++ b/arch/m68k/coldfire/m5441x/usb_dr.c |
| 1397 | @@ -0,0 +1,179 @@ |
| 1398 | +/* |
| 1399 | + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 1400 | + * |
| 1401 | + * The code contained herein is licensed under the GNU General Public |
| 1402 | + * License. You may obtain a copy of the GNU General Public License |
| 1403 | + * Version 2 or later at the following locations: |
| 1404 | + * |
| 1405 | + * http://www.opensource.org/licenses/gpl-license.html |
| 1406 | + * http://www.gnu.org/copyleft/gpl.html |
| 1407 | + */ |
| 1408 | +#include <linux/kernel.h> |
| 1409 | +#include <linux/types.h> |
| 1410 | +#include <linux/platform_device.h> |
| 1411 | +#include <linux/fsl_devices.h> |
| 1412 | +#include <asm/mcfsim.h> |
| 1413 | + |
| 1414 | +#define USB_OTGREGS_BASE MCF_REG32(0xFC0B0000) |
| 1415 | +#define INT_USB (64 + 64 + 64 + 17) /* INTC1:17 17.2.9.1*/ |
| 1416 | +#define INT_UOCSR (64 + 64 + 64 + 27) /* INTC1:27 17.2.9.1 */ |
| 1417 | + |
| 1418 | +/* |
| 1419 | + * Determine which platform_data struct to use, based on which |
| 1420 | + * transceiver is configured. |
| 1421 | + * PDATA is a pointer to it. |
| 1422 | + */ |
| 1423 | +#ifdef CONFIG_USB_M5441X_ULPI |
| 1424 | +static struct fsl_usb2_platform_data dr_config_ulpi; |
| 1425 | +#define PDATA (&dr_config_ulpi) |
| 1426 | +#else |
| 1427 | +static struct fsl_usb2_platform_data dr_config_fsls; |
| 1428 | +#define PDATA (&dr_config_fsls) |
| 1429 | +#endif |
| 1430 | + |
| 1431 | +/* |
| 1432 | + * Used to set pdata->operating_mode before registering the platform_device. |
| 1433 | + * If OTG is configured, the controller operates in OTG mode, |
| 1434 | + * otherwise it's either host or device. |
| 1435 | + */ |
| 1436 | +#ifdef CONFIG_USB_OTG |
| 1437 | +#define DR_UDC_MODE FSL_USB2_DR_OTG |
| 1438 | +#define DR_HOST_MODE FSL_USB2_DR_OTG |
| 1439 | +#else |
| 1440 | +#define DR_UDC_MODE FSL_USB2_DR_DEVICE |
| 1441 | +#define DR_HOST_MODE FSL_USB2_DR_HOST |
| 1442 | +#endif |
| 1443 | + |
| 1444 | +#include "usb.h" |
| 1445 | + |
| 1446 | +/* |
| 1447 | + * platform data structs |
| 1448 | + * - Which one to use is determined by CONFIG options in usb.h |
| 1449 | + * - operating_mode plugged at run time |
| 1450 | + */ |
| 1451 | + |
| 1452 | +/* off-chip ULPI transceiver */ |
| 1453 | +static struct fsl_usb2_platform_data __maybe_unused dr_config_ulpi = { |
| 1454 | + .name = "DR", |
| 1455 | + .init = usb_platform_dr_init, |
| 1456 | + .exit = usb_platform_dr_uninit, |
| 1457 | + .phy_mode = FSL_USB2_PHY_ULPI, |
| 1458 | + .transceiver = "dr-ulpi", |
| 1459 | + .power_budget = 500, |
| 1460 | + .es = 1, |
| 1461 | + .big_endian_mmio = 1, |
| 1462 | + .big_endian_desc = 1, |
| 1463 | + .le_setup_buf = 1, |
| 1464 | +}; |
| 1465 | + |
| 1466 | +/* on-chip FS/LS serial transceiver */ |
| 1467 | +static struct fsl_usb2_platform_data __maybe_unused dr_config_fsls = { |
| 1468 | + .name = "DR", |
| 1469 | + .init = usb_platform_dr_init, |
| 1470 | + .exit = usb_platform_dr_uninit, |
| 1471 | + .phy_mode = FSL_USB2_PHY_SERIAL, |
| 1472 | +#ifdef CONFIG_USB_M5441X_MAX3353_FSLS |
| 1473 | + .transceiver = "dr-max3353", |
| 1474 | +#else |
| 1475 | + .transceiver = "dr-fsls", |
| 1476 | +#endif |
| 1477 | + .power_budget = 500, |
| 1478 | + .es = 1, |
| 1479 | + .big_endian_mmio = 1, |
| 1480 | + .big_endian_desc = 1, |
| 1481 | + .le_setup_buf = 1, |
| 1482 | +}; |
| 1483 | + |
| 1484 | +/* |
| 1485 | + * resources |
| 1486 | + */ |
| 1487 | +static struct resource dr_udc_resources[] = { |
| 1488 | + [0] = { |
| 1489 | + .start = (u32)(&USB_OTGREGS_BASE), |
| 1490 | + .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), |
| 1491 | + .flags = IORESOURCE_MEM, |
| 1492 | + }, |
| 1493 | + [1] = { |
| 1494 | + .start = INT_USB, |
| 1495 | + .flags = IORESOURCE_IRQ, |
| 1496 | + }, |
| 1497 | +}; |
| 1498 | + |
| 1499 | +static struct resource dr_otg_resources[] = { |
| 1500 | + [0] = { |
| 1501 | + .start = (u32)(&USB_OTGREGS_BASE), |
| 1502 | + .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), |
| 1503 | + .flags = IORESOURCE_MEM, |
| 1504 | + }, |
| 1505 | + [1] = { |
| 1506 | + .start = INT_USB, |
| 1507 | + .flags = IORESOURCE_IRQ, |
| 1508 | + }, |
| 1509 | +}; |
| 1510 | + |
| 1511 | +static struct resource dr_host_resources[] = { |
| 1512 | + [0] = { |
| 1513 | + .start = (u32)(&USB_OTGREGS_BASE), |
| 1514 | + .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), |
| 1515 | + .flags = IORESOURCE_MEM, |
| 1516 | + }, |
| 1517 | + [1] = { |
| 1518 | + .start = INT_USB, |
| 1519 | + .flags = IORESOURCE_IRQ, |
| 1520 | + }, |
| 1521 | +}; |
| 1522 | + |
| 1523 | +static u64 dr_udc_dmamask = ~(u32) 0; |
| 1524 | +static void dr_udc_release(struct device *dev) |
| 1525 | +{ |
| 1526 | +} |
| 1527 | + |
| 1528 | +static u64 dr_otg_dmamask = ~(u32) 0; |
| 1529 | +static void dr_otg_release(struct device *dev) |
| 1530 | +{ |
| 1531 | +} |
| 1532 | + |
| 1533 | +/* |
| 1534 | + * platform device structs |
| 1535 | + * dev.platform_data field plugged at run time |
| 1536 | + */ |
| 1537 | +static struct platform_device __maybe_unused dr_udc_device = { |
| 1538 | + .name = "fsl-usb2-udc", |
| 1539 | + .id = -1, |
| 1540 | + .dev = { |
| 1541 | + .release = dr_udc_release, |
| 1542 | + .dma_mask = &dr_udc_dmamask, |
| 1543 | + .coherent_dma_mask = 0xffffffff, |
| 1544 | + }, |
| 1545 | + .resource = dr_udc_resources, |
| 1546 | + .num_resources = ARRAY_SIZE(dr_udc_resources), |
| 1547 | +}; |
| 1548 | + |
| 1549 | +static struct platform_device __maybe_unused dr_otg_device = { |
| 1550 | +#ifdef CONFIG_USB_M5441X_MAX3353_FSLS |
| 1551 | + .name = "max3353-otg", |
| 1552 | +#else |
| 1553 | + .name = "fsl-usb2-otg", |
| 1554 | +#endif |
| 1555 | + .id = -1, |
| 1556 | + .dev = { |
| 1557 | + .release = dr_otg_release, |
| 1558 | + .dma_mask = &dr_otg_dmamask, |
| 1559 | + .coherent_dma_mask = 0xffffffff, |
| 1560 | + }, |
| 1561 | + .resource = dr_otg_resources, |
| 1562 | + .num_resources = ARRAY_SIZE(dr_otg_resources), |
| 1563 | +}; |
| 1564 | + |
| 1565 | +static int __init usb_dr_init(void) |
| 1566 | +{ |
| 1567 | + pr_debug("%s:\n", __func__); |
| 1568 | + |
| 1569 | + dr_register_otg(); |
| 1570 | + dr_register_host(dr_host_resources, ARRAY_SIZE(dr_host_resources)); |
| 1571 | + dr_register_udc(); |
| 1572 | + |
| 1573 | + return 0; |
| 1574 | +} |
| 1575 | + |
| 1576 | +module_init(usb_dr_init); |
| 1577 | --- /dev/null |
| 1578 | +++ b/arch/m68k/coldfire/m5441x/usb_host.c |
| 1579 | @@ -0,0 +1,115 @@ |
| 1580 | +/* |
| 1581 | + * Copyright (C) 2004-2011 Freescale Semiconductor, Inc. All rights reserved. |
| 1582 | + * |
| 1583 | + * This program is free software; you can redistribute it and/or modify it |
| 1584 | + * under the terms of the GNU General Public License as published by the |
| 1585 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 1586 | + * option) any later version. |
| 1587 | + * |
| 1588 | + * This program is distributed in the hope that it will be useful, but |
| 1589 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1590 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 1591 | + * General Public License for more details. |
| 1592 | + * |
| 1593 | + * You should have received a copy of the GNU General Public License along |
| 1594 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 1595 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 1596 | + */ |
| 1597 | + |
| 1598 | +#include <linux/kernel.h> |
| 1599 | +#include <linux/platform_device.h> |
| 1600 | +#include <linux/fsl_devices.h> |
| 1601 | +#include <asm/mcfsim.h> |
| 1602 | + |
| 1603 | +#define USB_H1REGS_BASE (0xFC0B4000) |
| 1604 | +#define INT_USB_HOST (64 + 64 + 64 + 18) /* INTC1:18*/ |
| 1605 | + |
| 1606 | + |
| 1607 | +/* |
| 1608 | + * Define Host module platform_data struct to use, based on which |
| 1609 | + * transceiver is configured. |
| 1610 | + * PDATA is a pointer to it. |
| 1611 | + */ |
| 1612 | +#if defined(CONFIG_USB_M5441X_H1_FSLS) |
| 1613 | +static struct fsl_usb2_platform_data h1_config_fsls; |
| 1614 | +#define PDATA (&h1_config_fsls) |
| 1615 | +#else |
| 1616 | +#warning "Unknow ColdFire USB Host module transceiver!" |
| 1617 | +#endif |
| 1618 | +/* |
| 1619 | + * Used to set pdata->operating_mode before registering the platform_device. |
| 1620 | + */ |
| 1621 | +#define DR_UDC_MODE FSL_USB2_DR_DEVICE |
| 1622 | +#define DR_HOST_MODE FSL_USB2_DR_HOST |
| 1623 | + |
| 1624 | +#include "usb.h" |
| 1625 | + |
| 1626 | +static int h1_gpio_active(void) |
| 1627 | +{ |
| 1628 | + /* Configure USB_DP_PDOWN/USB_DM_PDOWN (external resistor) */ |
| 1629 | + MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT0; |
| 1630 | + MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT1; |
| 1631 | + MCF_GPIO_PDDR_I |= 0xc0; |
| 1632 | + MCF_GPIO_PODR_I &= 0x3f; |
| 1633 | + |
| 1634 | + MCF_GPIO_PAR_CS &= 0x0F; /*Enable GPIOB5, GPIOB6*/ |
| 1635 | + |
| 1636 | + MCF_GPIO_PDDR_B &= 0xDF; /*GPIOB5, input, USB_OC*/ |
| 1637 | + MCF_GPIO_PCR_B |= 0x0C00; /*pull up*/ |
| 1638 | + |
| 1639 | + MCF_GPIO_PDDR_B |= 0x40; /*GPIOB6, output*/ |
| 1640 | + MCF_GPIO_PODR_B |= 0x40; /*GPIOB6, output 1, VBUS enable*/ |
| 1641 | + MCF_GPIO_PCR_B &= ~0x3000; /*pull disable*/ |
| 1642 | + |
| 1643 | + return 0; |
| 1644 | +} |
| 1645 | + |
| 1646 | +static void h1_gpio_inactive(void) |
| 1647 | +{ |
| 1648 | + MCF_GPIO_PODR_B &= 0xBF; /*GPIOB6, output 0*/ |
| 1649 | +} |
| 1650 | + |
| 1651 | + |
| 1652 | +/* |
| 1653 | + * platform data struct |
| 1654 | + * - operating_mode plugged at run time |
| 1655 | + */ |
| 1656 | + |
| 1657 | +/* on-chip FS/LS serial transceiver */ |
| 1658 | +static struct fsl_usb2_platform_data usbh1_config = { |
| 1659 | + .name = "Host1", |
| 1660 | + .init = usb_platform_host_init, |
| 1661 | + .exit = usb_platform_host_uninit, |
| 1662 | + .operating_mode = FSL_USB2_MPH_HOST, |
| 1663 | + .power_budget = 500, /* MIC2076: 500 mA max power */ |
| 1664 | + .phy_mode = FSL_USB2_PHY_SERIAL, /* FS/LS on-chip xcvr */ |
| 1665 | + .transceiver = "h1-fsls", |
| 1666 | + .gpio_usb_active = h1_gpio_active, |
| 1667 | + .gpio_usb_inactive = h1_gpio_inactive, |
| 1668 | + .es = 1, |
| 1669 | + .big_endian_mmio = 1, |
| 1670 | + .big_endian_desc = 1, |
| 1671 | +}; |
| 1672 | + |
| 1673 | +/* |
| 1674 | + * resources |
| 1675 | + */ |
| 1676 | +static struct resource h1_resources[] = { |
| 1677 | + [0] = { |
| 1678 | + .start = USB_H1REGS_BASE, |
| 1679 | + .end = USB_H1REGS_BASE + 0x1ff, |
| 1680 | + .flags = IORESOURCE_MEM, |
| 1681 | + }, |
| 1682 | + [1] = { |
| 1683 | + .start = INT_USB_HOST, |
| 1684 | + .flags = IORESOURCE_IRQ, |
| 1685 | + }, |
| 1686 | +}; |
| 1687 | + |
| 1688 | +static int __init usbh1_init(void) |
| 1689 | +{ |
| 1690 | + host_pdev_register(h1_resources, ARRAY_SIZE(h1_resources), |
| 1691 | + &usbh1_config); |
| 1692 | + return 0; |
| 1693 | +} |
| 1694 | +module_init(usbh1_init); |
| 1695 | --- /dev/null |
| 1696 | +++ b/arch/m68k/coldfire/m5441x/xcvr.c |
| 1697 | @@ -0,0 +1,198 @@ |
| 1698 | +/* |
| 1699 | + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 1700 | + * |
| 1701 | + * The code contained herein is licensed under the GNU General Public |
| 1702 | + * License. You may obtain a copy of the GNU General Public License |
| 1703 | + * Version 2 or later at the following locations: |
| 1704 | + * |
| 1705 | + * http://www.opensource.org/licenses/gpl-license.html |
| 1706 | + * http://www.gnu.org/copyleft/gpl.html |
| 1707 | + */ |
| 1708 | +#include <linux/module.h> |
| 1709 | +#include <linux/kernel.h> |
| 1710 | +#include <linux/types.h> |
| 1711 | +#include <linux/init.h> |
| 1712 | +#include <linux/io.h> |
| 1713 | +#include <linux/delay.h> |
| 1714 | +#include <linux/usb/fsl_xcvr.h> |
| 1715 | +#include <asm/mcfsim.h> |
| 1716 | + |
| 1717 | +/* Use the configured xcvr_ops */ |
| 1718 | +#ifdef CONFIG_USB_M5441X_ULPI |
| 1719 | +#define XCVR_OPS (&xcvr_ops_ulpi) |
| 1720 | +#elif defined CONFIG_USB_M5441X_FSLS |
| 1721 | +#define XCVR_OPS (&xcvr_ops_fsls) |
| 1722 | +#else |
| 1723 | +#error "Invalid USB transceiver selection." |
| 1724 | +#endif |
| 1725 | + |
| 1726 | +#define MCF_FEC_ENET0_RCR MCF_REG32(0xFC0D4084) |
| 1727 | + |
| 1728 | +/* |
| 1729 | + * Init routine for on-chip FSLS xcvr |
| 1730 | + */ |
| 1731 | +static void xcvr_fsls_init(struct fsl_xcvr_ops *this) |
| 1732 | +{ |
| 1733 | + pr_debug("%s: name=%s\n", __func__, this->name); |
| 1734 | + |
| 1735 | + /* Configure USB_DP_PDOWN/USB_DM_PDOWN (external resistor) */ |
| 1736 | + MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT0; |
| 1737 | + MCF_GPIO_PAR_DBGH1 &= ~MCF_GPIO_PAR_DEBUGH1_DAT1; |
| 1738 | + MCF_GPIO_PDDR_I |= 0xc0; |
| 1739 | + MCF_GPIO_PODR_I &= 0x3f; |
| 1740 | + |
| 1741 | + |
| 1742 | + MCF_GPIO_PAR_CS &= 0x0F; /*Enable GPIOB5, GPIOB6*/ |
| 1743 | + |
| 1744 | + MCF_GPIO_PDDR_B &= 0xDF; /*GPIOB5, input*/ |
| 1745 | + MCF_GPIO_PDDR_B |= 0x40; /*GPIOB6, output*/ |
| 1746 | + |
| 1747 | + MCF_GPIO_PODR_B |= 0x40; /*GPIOB6, output 1*/ |
| 1748 | +#if 0 |
| 1749 | + /* Enable VBUS_EN and VBUS_OC signals */ |
| 1750 | + MCF_GPIO_PAR_TIMER = |
| 1751 | + (MCF_GPIO_PAR_TIMER & |
| 1752 | + MCF_GPIO_PAR_TIMER_T3IN_MASK) | |
| 1753 | + MCF_GPIO_PAR_TIMER_T3IN_USB0_VBUSEN; |
| 1754 | + |
| 1755 | + MCF_GPIO_PAR_TIMER = |
| 1756 | + (MCF_GPIO_PAR_TIMER & |
| 1757 | + MCF_GPIO_PAR_TIMER_T0IN_MASK) | |
| 1758 | + MCF_GPIO_PAR_TIMER_T0IN_USBO_VBUSOC; |
| 1759 | + |
| 1760 | + /* Setup USB_VBUS_OC signal to be active-low */ |
| 1761 | + MCF_CCM_MISCCR &= (~MCF_CCM_MISCCR_USBOOC); |
| 1762 | + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBPUE; |
| 1763 | +#endif |
| 1764 | + |
| 1765 | +} |
| 1766 | + |
| 1767 | +/* |
| 1768 | + * Init routine for off-chip ULPI xcvr |
| 1769 | + */ |
| 1770 | +static void xcvr_ulpi_init(struct fsl_xcvr_ops *this) |
| 1771 | +{ |
| 1772 | + pr_debug("%s: name=%s\n", __func__, this->name); |
| 1773 | + |
| 1774 | + /* disable FEC2 clock */ |
| 1775 | + MCF_PM_PPMSR0 = 54; |
| 1776 | + |
| 1777 | + /* enable USB OTG clock*/ |
| 1778 | + MCF_PM_PPMCR0 = 44; |
| 1779 | + |
| 1780 | + /* Chip select for ULPI: GPIO G4 as CS between ULPI and RMII1*/ |
| 1781 | + MCF_GPIO_PAR_SIMP0H = |
| 1782 | + (MCF_GPIO_PAR_SIMP0H & |
| 1783 | + MCF_GPIO_PAR_SIMP0H_DAT_MASK) | |
| 1784 | + MCF_GPIO_PAR_SIMP0H_DAT_GPIO; |
| 1785 | + |
| 1786 | + MCF_GPIO_PDDR_G = |
| 1787 | + (MCF_GPIO_PDDR_G & |
| 1788 | + MCF_GPIO_PDDR_G4_MASK) | |
| 1789 | + MCF_GPIO_PDDR_G4_OUTPUT; |
| 1790 | + |
| 1791 | + MCF_GPIO_PODR_G = |
| 1792 | + (MCF_GPIO_PODR_G & |
| 1793 | + MCF_GPIO_PODR_G4_MASK) | |
| 1794 | + MCF_GPIO_PODR_G4_VAL; |
| 1795 | + |
| 1796 | + /* Enable ULPI */ |
| 1797 | + MCF_CCM_MISCCR2 = MCF_CCM_MISCCR2 & (~MCF_CCM_MISCCR2_ULPI); |
| 1798 | + |
| 1799 | + /* Slew rate setting for OTG */ |
| 1800 | + MCF_GPIO_SRCR_FEC = 0x0f; |
| 1801 | + MCF_GPIO_SRCR_TIMER = 0xc3; |
| 1802 | + MCF_GPIO_SRCR_IRQ0 = 0x03; |
| 1803 | + |
| 1804 | + /* Enable the required ULPI signals */ |
| 1805 | + MCF_GPIO_PAR_TIMER = |
| 1806 | + (MCF_GPIO_PAR_TIMER & |
| 1807 | + MCF_GPIO_PAR_TIMER_T3IN_MASK) | |
| 1808 | + MCF_GPIO_PAR_TIMER_T3IN_ULPI_DIR; |
| 1809 | + |
| 1810 | + MCF_GPIO_PAR_TIMER = |
| 1811 | + (MCF_GPIO_PAR_TIMER & |
| 1812 | + MCF_GPIO_PAR_TIMER_T0IN_MASK) | |
| 1813 | + MCF_GPIO_PAR_TIMER_T0IN_ULPI_NXT; |
| 1814 | + |
| 1815 | + MCF_FEC_ENET0_RCR = 0x104; /* FEC0 as RMII mode */ |
| 1816 | + |
| 1817 | + MCF_GPIO_PAR_FEC = |
| 1818 | + (MCF_GPIO_PAR_FEC & |
| 1819 | + MCF_GPIO_PAR_FEC_FEC_MASK) | |
| 1820 | + MCF_GPIO_PAR_FEC_FEC_RMII0FUL_ULPI; |
| 1821 | + |
| 1822 | + |
| 1823 | + pr_debug("MCF_GPIO_PAR_TIMER:0x%x, MCF_GPIO_PAR_FEC:0x%x," |
| 1824 | + "MCF_GPIO_PAR_SIMP0H:0x%x, MCF_GPIO_PDDR_G:0x%x," |
| 1825 | + "MCF_GPIO_PODR_G:0x%x, MCF_CCM_MISCCR2:0x%x\n\n", |
| 1826 | + MCF_GPIO_PAR_TIMER, MCF_GPIO_PAR_FEC, |
| 1827 | + MCF_GPIO_PAR_SIMP0H, MCF_GPIO_PDDR_G, |
| 1828 | + MCF_GPIO_PODR_G, MCF_CCM_MISCCR2); |
| 1829 | + |
| 1830 | + pr_debug("OTGSC:0x%lx, PORTSC:0x%lx, USBMODE:0x%lx, " |
| 1831 | + "USBCMD:0x%lx, USBSTS:0x%lx, USBINTR:0x%lx, " |
| 1832 | + "MCF_CCM_UOCSR:0x%x\n\n", |
| 1833 | + MCF_REG32(0xfc0b01a4), MCF_REG32(0xfc0b0184), |
| 1834 | + MCF_REG32(0xfc0b01a8), MCF_REG32(0xfc0b0140), |
| 1835 | + MCF_REG32(0xfc0b0144), MCF_REG32(0xfc0b0148), |
| 1836 | + MCF_CCM_UOCSR); |
| 1837 | +} |
| 1838 | + |
| 1839 | +static void xcvr_uninit(struct fsl_xcvr_ops *this) |
| 1840 | +{ |
| 1841 | + pr_debug("%s\n", __func__); |
| 1842 | +} |
| 1843 | + |
| 1844 | +static void xcvr_pullup(int on) |
| 1845 | +{ |
| 1846 | + unsigned short ccm = in_be16(&MCF_CCM_UOCSR); |
| 1847 | + |
| 1848 | + pr_debug("%s(%d)\n", __func__, on); |
| 1849 | + |
| 1850 | + ccm = in_be16(&MCF_CCM_UOCSR); |
| 1851 | + if (on) { |
| 1852 | + ccm |= MCF_CCM_UOCSR_BVLD; |
| 1853 | + ccm &= ~MCF_CCM_UOCSR_SEND; |
| 1854 | + out_be16(&MCF_CCM_UOCSR, ccm); |
| 1855 | + } else { |
| 1856 | + ccm &= ~MCF_CCM_UOCSR_BVLD; |
| 1857 | + out_be16(&MCF_CCM_UOCSR, ccm); |
| 1858 | + } |
| 1859 | +} |
| 1860 | + |
| 1861 | +struct fsl_xcvr_ops xcvr_ops_ulpi = { |
| 1862 | + .init = xcvr_ulpi_init, |
| 1863 | + .uninit = xcvr_uninit, |
| 1864 | + .pullup = xcvr_pullup, |
| 1865 | + .name = "dr-ulpi", |
| 1866 | +}; |
| 1867 | + |
| 1868 | +struct fsl_xcvr_ops xcvr_ops_fsls = { |
| 1869 | + .init = xcvr_fsls_init, |
| 1870 | + .uninit = xcvr_uninit, |
| 1871 | + .pullup = xcvr_pullup, |
| 1872 | + .name = "dr-fsls", |
| 1873 | +}; |
| 1874 | + |
| 1875 | +static int __init usb_xcvr_init(void) |
| 1876 | +{ |
| 1877 | + struct fsl_xcvr_ops *xops = XCVR_OPS; |
| 1878 | + |
| 1879 | + pr_debug("%s %s\n", __func__, xops->name); |
| 1880 | + fsl_usb_xcvr_register(xops); |
| 1881 | + |
| 1882 | + return 0; |
| 1883 | +} |
| 1884 | + |
| 1885 | +static void __exit usb_xcvr_exit(void) |
| 1886 | +{ |
| 1887 | + fsl_usb_xcvr_unregister(XCVR_OPS); |
| 1888 | +} |
| 1889 | + |
| 1890 | +module_init(usb_xcvr_init); |
| 1891 | +module_exit(usb_xcvr_exit); |
| 1892 | + |
| 1893 | +MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
| 1894 | +MODULE_DESCRIPTION("External ULPI xcvr driver"); |
| 1895 | +MODULE_LICENSE("GPL"); |
| 1896 | --- /dev/null |
| 1897 | +++ b/arch/m68k/coldfire/m5441x/xcvr_host.c |
| 1898 | @@ -0,0 +1,53 @@ |
| 1899 | +/* |
| 1900 | + * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All rights reserved. |
| 1901 | + * |
| 1902 | + * This program is free software; you can redistribute it and/or modify it |
| 1903 | + * under the terms of the GNU General Public License as published by the |
| 1904 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 1905 | + * option) any later version. |
| 1906 | + * |
| 1907 | + * This program is distributed in the hope that it will be useful, but |
| 1908 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1909 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 1910 | + * General Public License for more details. |
| 1911 | + * |
| 1912 | + * You should have received a copy of the GNU General Public License along |
| 1913 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 1914 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 1915 | + */ |
| 1916 | + |
| 1917 | +#include <linux/module.h> |
| 1918 | +#include <linux/kernel.h> |
| 1919 | +#include <linux/types.h> |
| 1920 | +#include <linux/init.h> |
| 1921 | +#include <linux/io.h> |
| 1922 | +#include <linux/usb/fsl_xcvr.h> |
| 1923 | +#include <asm/mcfsim.h> |
| 1924 | + |
| 1925 | +/* |
| 1926 | + * xcvr_ops for the on-chip xcvr on the DR controller |
| 1927 | + * No ops needed. |
| 1928 | + */ |
| 1929 | +struct fsl_xcvr_ops xcvr_ops_h1_fsls = { |
| 1930 | + .name = "h1-fsls", |
| 1931 | +}; |
| 1932 | + |
| 1933 | + |
| 1934 | +static int __init usb_xcvr_host_init(void) |
| 1935 | +{ |
| 1936 | + fsl_usb_xcvr_register(&xcvr_ops_h1_fsls); |
| 1937 | + |
| 1938 | + return 0; |
| 1939 | +} |
| 1940 | + |
| 1941 | +static void __exit usb_xcvr_host_exit(void) |
| 1942 | +{ |
| 1943 | + fsl_usb_xcvr_unregister(&xcvr_ops_h1_fsls); |
| 1944 | +} |
| 1945 | + |
| 1946 | +module_init(usb_xcvr_host_init); |
| 1947 | +module_exit(usb_xcvr_host_exit); |
| 1948 | + |
| 1949 | +MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
| 1950 | +MODULE_DESCRIPTION("On-chip FS/LS xcvr host driver"); |
| 1951 | +MODULE_LICENSE("GPL"); |
| 1952 | --- /dev/null |
| 1953 | +++ b/arch/m68k/coldfire/m5445x/usb.c |
| 1954 | @@ -0,0 +1,220 @@ |
| 1955 | +/* |
| 1956 | + * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 1957 | + * |
| 1958 | + * This program is free software; you can redistribute it and/or modify it |
| 1959 | + * under the terms of the GNU General Public License as published by the |
| 1960 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 1961 | + * option) any later version. |
| 1962 | + * |
| 1963 | + * This program is distributed in the hope that it will be useful, but |
| 1964 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1965 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 1966 | + * General Public License for more details. |
| 1967 | + * |
| 1968 | + * You should have received a copy of the GNU General Public License along |
| 1969 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 1970 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 1971 | + */ |
| 1972 | + |
| 1973 | +#include <linux/module.h> |
| 1974 | +#include <linux/kernel.h> |
| 1975 | +#include <linux/types.h> |
| 1976 | +#include <linux/errno.h> |
| 1977 | +#include <linux/err.h> |
| 1978 | +#include <linux/platform_device.h> |
| 1979 | +#include <linux/fsl_devices.h> |
| 1980 | +#include <linux/usb/fsl_xcvr.h> |
| 1981 | +#include <asm/mcfsim.h> |
| 1982 | + |
| 1983 | +#define MCF_SCM_BCR MCF_REG32(0xFC040024) |
| 1984 | +#define MCF_SCM_BCR_GBR (1 << 9) /* global bursts for read */ |
| 1985 | +#define MCF_SCM_BCR_GBW (1 << 8) /* global bursts for write */ |
| 1986 | +#define MCF_SCM_BCR_SBE_ALL (0xff << 0) /* slave burst enable */ |
| 1987 | + |
| 1988 | +#define MAX_XCVR 3 |
| 1989 | +struct fsl_xcvr_ops *g_xc_ops[MAX_XCVR] = { NULL }; |
| 1990 | + |
| 1991 | +#ifdef ULPI_DEBUG |
| 1992 | +void print_ulpi_regs(void) |
| 1993 | +{ |
| 1994 | + pr_debug("MCF_SCM_BCR=0x%08lx MCF_CCM_MISCCR=0x%08x " |
| 1995 | + "MCF_GPIO_PAR_DMA=0x%08x MCF_GPIO_PAR_USB=08%08x " |
| 1996 | + "MCF_GPIO_PAR_FEC=08%08x\n", |
| 1997 | + MCF_SCM_BCR, MCF_CCM_MISCCR, MCF_GPIO_PAR_DMA, |
| 1998 | + MCF_GPIO_PAR_USB, MCF_GPIO_PAR_FEC); |
| 1999 | +} |
| 2000 | +EXPORT_SYMBOL(print_ulpi_regs); |
| 2001 | +#endif |
| 2002 | + |
| 2003 | +static inline void fsl_usb_enable_clk(void) |
| 2004 | +{ |
| 2005 | + pr_debug("%s\n", __func__); |
| 2006 | + |
| 2007 | + /* Use external clock source if PLL isn't a multiple of 60MHz */ |
| 2008 | + MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_USBSRC; |
| 2009 | + |
| 2010 | + /* Initialize the USB Clock: use USB input clock */ |
| 2011 | + MCF_GPIO_PAR_DMA = (MCF_GPIO_PAR_DMA & MCF_GPIO_PAR_DMA_DREQ1_MASK) | |
| 2012 | + MCF_GPIO_PAR_DMA_DREQ1_USB_CLKIN; |
| 2013 | +} |
| 2014 | + |
| 2015 | +static inline void fsl_usb_disable_clk(void) |
| 2016 | +{ |
| 2017 | + pr_debug("%s\n", __func__); |
| 2018 | +} |
| 2019 | + |
| 2020 | +void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops) |
| 2021 | +{ |
| 2022 | + int i; |
| 2023 | + |
| 2024 | + pr_debug("%s '%s'\n", __func__, xcvr_ops->name); |
| 2025 | + for (i = 0; i < MAX_XCVR; i++) { |
| 2026 | + if (g_xc_ops[i] == NULL) { |
| 2027 | + g_xc_ops[i] = xcvr_ops; |
| 2028 | + return; |
| 2029 | + } |
| 2030 | + } |
| 2031 | + |
| 2032 | + pr_debug("%s failed\n", __func__); |
| 2033 | +} |
| 2034 | +EXPORT_SYMBOL_GPL(fsl_usb_xcvr_register); |
| 2035 | + |
| 2036 | +void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops) |
| 2037 | +{ |
| 2038 | + int i; |
| 2039 | + |
| 2040 | + pr_debug("%s '%s'\n", __func__, xcvr_ops->name); |
| 2041 | + for (i = 0; i < MAX_XCVR; i++) { |
| 2042 | + if (g_xc_ops[i] == xcvr_ops) { |
| 2043 | + g_xc_ops[i] = NULL; |
| 2044 | + return; |
| 2045 | + } |
| 2046 | + } |
| 2047 | + |
| 2048 | + pr_debug("%s failed\n", __func__); |
| 2049 | +} |
| 2050 | +EXPORT_SYMBOL_GPL(fsl_usb_xcvr_unregister); |
| 2051 | + |
| 2052 | +static struct fsl_xcvr_ops *fsl_usb_get_xcvr(char *name) |
| 2053 | +{ |
| 2054 | + int i; |
| 2055 | + |
| 2056 | + pr_debug("%s '%s'\n", __func__, name); |
| 2057 | + if (name == NULL) { |
| 2058 | + printk(KERN_ERR "get_xcvr(): No tranceiver name\n"); |
| 2059 | + return NULL; |
| 2060 | + } |
| 2061 | + |
| 2062 | + for (i = 0; i < MAX_XCVR; i++) { |
| 2063 | + if (strcmp(g_xc_ops[i]->name, name) == 0) |
| 2064 | + return g_xc_ops[i]; |
| 2065 | + } |
| 2066 | + pr_debug("Failed %s\n", __func__); |
| 2067 | + return NULL; |
| 2068 | +} |
| 2069 | + |
| 2070 | +/* The dmamask must be set for EHCI to work */ |
| 2071 | +static u64 ehci_dmamask = ~(u32) 0; |
| 2072 | + |
| 2073 | +/*! |
| 2074 | + * Register an instance of a USB host platform device. |
| 2075 | + * |
| 2076 | + * @param res: resource pointer |
| 2077 | + * @param n_res: number of resources |
| 2078 | + * @param config: config pointer |
| 2079 | + * |
| 2080 | + * @return newly-registered platform_device |
| 2081 | + * |
| 2082 | + * Each supported host interface is registered as an instance |
| 2083 | + * of the "fsl-ehci" device. Call this function multiple times |
| 2084 | + * to register each host interface. |
| 2085 | + */ |
| 2086 | +static int instance_id; |
| 2087 | +struct platform_device *host_pdev_register(struct resource *res, int n_res, |
| 2088 | + struct fsl_usb2_platform_data *config) |
| 2089 | +{ |
| 2090 | + struct platform_device *pdev; |
| 2091 | + int rc; |
| 2092 | + |
| 2093 | + pr_debug("register host res=0x%p, size=%d\n", res, n_res); |
| 2094 | + |
| 2095 | + pdev = platform_device_register_simple("fsl-ehci", |
| 2096 | + instance_id, res, n_res); |
| 2097 | + if (IS_ERR(pdev)) { |
| 2098 | + printk(KERN_ERR "usb: can't register %s Host, %ld\n", |
| 2099 | + config->name, PTR_ERR(pdev)); |
| 2100 | + return NULL; |
| 2101 | + } |
| 2102 | + |
| 2103 | + pdev->dev.coherent_dma_mask = 0xffffffff; |
| 2104 | + pdev->dev.dma_mask = &ehci_dmamask; |
| 2105 | + |
| 2106 | + rc = platform_device_add_data(pdev, config, |
| 2107 | + sizeof(struct fsl_usb2_platform_data)); |
| 2108 | + if (rc) { |
| 2109 | + platform_device_unregister(pdev); |
| 2110 | + return NULL; |
| 2111 | + } |
| 2112 | + |
| 2113 | + printk(KERN_INFO "usb: %s host (%s) registered\n", config->name, |
| 2114 | + config->transceiver); |
| 2115 | + pr_debug("pdev=0x%p dev=0x%p resources=0x%p pdata=0x%p\n", |
| 2116 | + pdev, &pdev->dev, pdev->resource, pdev->dev.platform_data); |
| 2117 | + |
| 2118 | + instance_id++; |
| 2119 | + |
| 2120 | + return pdev; |
| 2121 | +} |
| 2122 | + |
| 2123 | + |
| 2124 | +static int dr_used; |
| 2125 | + |
| 2126 | +int usb_platform_dr_init(struct platform_device *pdev) |
| 2127 | +{ |
| 2128 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 2129 | + struct fsl_xcvr_ops *xops; |
| 2130 | + |
| 2131 | + pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata); |
| 2132 | + |
| 2133 | + xops = fsl_usb_get_xcvr(pdata->transceiver); |
| 2134 | + if (!xops) { |
| 2135 | + printk(KERN_ERR "DR transceiver ops missing\n"); |
| 2136 | + return -EINVAL; |
| 2137 | + } |
| 2138 | + pdata->xcvr_ops = xops; |
| 2139 | + pdata->xcvr_type = xops->xcvr_type; |
| 2140 | + pdata->pdev = pdev; |
| 2141 | + xops->pdata = pdata; |
| 2142 | + |
| 2143 | + /* enable USB read, write and slave bursts */ |
| 2144 | + MCF_SCM_BCR = MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW | MCF_SCM_BCR_SBE_ALL; |
| 2145 | + |
| 2146 | + if (!dr_used) { |
| 2147 | + fsl_usb_enable_clk(); |
| 2148 | + |
| 2149 | + if (xops->init) |
| 2150 | + xops->init(xops); |
| 2151 | + } |
| 2152 | + |
| 2153 | + dr_used++; |
| 2154 | + pr_debug("%s: success\n", __func__); |
| 2155 | + return 0; |
| 2156 | +} |
| 2157 | +EXPORT_SYMBOL_GPL(usb_platform_dr_init); |
| 2158 | + |
| 2159 | +void usb_platform_dr_uninit(struct platform_device *pdev) |
| 2160 | +{ |
| 2161 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 2162 | + |
| 2163 | + pr_debug("%s\n", __func__); |
| 2164 | + |
| 2165 | + dr_used--; |
| 2166 | + if (!dr_used) { |
| 2167 | + if (pdata->xcvr_ops && pdata->xcvr_ops->uninit) |
| 2168 | + pdata->xcvr_ops->uninit(pdata->xcvr_ops); |
| 2169 | + |
| 2170 | + pdata->regs = NULL; |
| 2171 | + fsl_usb_disable_clk(); |
| 2172 | + } |
| 2173 | +} |
| 2174 | +EXPORT_SYMBOL_GPL(usb_platform_dr_uninit); |
| 2175 | --- /dev/null |
| 2176 | +++ b/arch/m68k/coldfire/m5445x/usb.h |
| 2177 | @@ -0,0 +1,107 @@ |
| 2178 | +/* |
| 2179 | + * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 2180 | + * |
| 2181 | + * This program is free software; you can redistribute it and/or modify it |
| 2182 | + * under the terms of the GNU General Public License as published by the |
| 2183 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 2184 | + * option) any later version. |
| 2185 | + * |
| 2186 | + * This program is distributed in the hope that it will be useful, but |
| 2187 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2188 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 2189 | + * General Public License for more details. |
| 2190 | + * |
| 2191 | + * You should have received a copy of the GNU General Public License along |
| 2192 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 2193 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 2194 | + */ |
| 2195 | + |
| 2196 | + |
| 2197 | +extern int usb_platform_dr_init(struct platform_device *pdev); |
| 2198 | +extern void usb_platform_dr_uninit(struct fsl_usb2_platform_data *pdata); |
| 2199 | +extern struct platform_device *host_pdev_register(struct resource *res, |
| 2200 | + int n_res, struct fsl_usb2_platform_data *config); |
| 2201 | + |
| 2202 | + |
| 2203 | +/* |
| 2204 | + * Determine which platform_data struct to use, based on which |
| 2205 | + * transceiver is configured. |
| 2206 | + * PDATA is a pointer to it. |
| 2207 | + */ |
| 2208 | +#ifdef CONFIG_USB_M5445X_ULPI |
| 2209 | +static struct fsl_usb2_platform_data dr_config_ulpi; |
| 2210 | +#define PDATA (&dr_config_ulpi) |
| 2211 | +#else |
| 2212 | +static struct fsl_usb2_platform_data dr_config_fsls; |
| 2213 | +#define PDATA (&dr_config_fsls) |
| 2214 | +#endif |
| 2215 | + |
| 2216 | +/* |
| 2217 | + * Used to set pdata->operating_mode before registering the platform_device. |
| 2218 | + * If OTG is configured, the controller operates in OTG mode, |
| 2219 | + * otherwise it's either host or device. |
| 2220 | + */ |
| 2221 | +#ifdef CONFIG_USB_OTG |
| 2222 | +#define DR_UDC_MODE FSL_USB2_DR_OTG |
| 2223 | +#define DR_HOST_MODE FSL_USB2_DR_OTG |
| 2224 | +#else |
| 2225 | +#define DR_UDC_MODE FSL_USB2_DR_DEVICE |
| 2226 | +#define DR_HOST_MODE FSL_USB2_DR_HOST |
| 2227 | +#endif |
| 2228 | + |
| 2229 | + |
| 2230 | +#if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_EHCI_HCD_MODULE |
| 2231 | +static inline void dr_register_host(struct resource *r, int rs) |
| 2232 | +{ |
| 2233 | + PDATA->operating_mode = DR_HOST_MODE; |
| 2234 | + host_pdev_register(r, rs, PDATA); |
| 2235 | +} |
| 2236 | +#else |
| 2237 | +static inline void dr_register_host(struct resource *r, int rs) |
| 2238 | +{ |
| 2239 | +} |
| 2240 | +#endif |
| 2241 | + |
| 2242 | +#ifdef CONFIG_USB_GADGET_FSL_USB2 |
| 2243 | +static struct platform_device dr_udc_device; |
| 2244 | + |
| 2245 | +static inline void dr_register_udc(void) |
| 2246 | +{ |
| 2247 | + PDATA->operating_mode = DR_UDC_MODE; |
| 2248 | + dr_udc_device.dev.platform_data = PDATA; |
| 2249 | + |
| 2250 | + if (platform_device_register(&dr_udc_device)) |
| 2251 | + printk(KERN_ERR "usb: can't register DR gadget\n"); |
| 2252 | + else |
| 2253 | + printk(KERN_INFO "usb: DR gadget (%s) registered\n", |
| 2254 | + PDATA->transceiver); |
| 2255 | +} |
| 2256 | +#else |
| 2257 | +static inline void dr_register_udc(void) |
| 2258 | +{ |
| 2259 | +} |
| 2260 | +#endif |
| 2261 | + |
| 2262 | +#ifdef CONFIG_USB_OTG |
| 2263 | +static struct platform_device dr_otg_device; |
| 2264 | + |
| 2265 | +/* |
| 2266 | + * set the proper operating_mode and |
| 2267 | + * platform_data pointer, then register the |
| 2268 | + * device. |
| 2269 | + */ |
| 2270 | +static inline void dr_register_otg(void) |
| 2271 | +{ |
| 2272 | + PDATA->operating_mode = FSL_USB2_DR_OTG; |
| 2273 | + dr_otg_device.dev.platform_data = PDATA; |
| 2274 | + |
| 2275 | + if (platform_device_register(&dr_otg_device)) |
| 2276 | + printk(KERN_ERR "usb: can't register otg device\n"); |
| 2277 | + else |
| 2278 | + printk(KERN_INFO "usb: DR OTG registered\n"); |
| 2279 | +} |
| 2280 | +#else |
| 2281 | +static inline void dr_register_otg(void) |
| 2282 | +{ |
| 2283 | +} |
| 2284 | +#endif |
| 2285 | --- /dev/null |
| 2286 | +++ b/arch/m68k/coldfire/m5445x/usb_dr.c |
| 2287 | @@ -0,0 +1,152 @@ |
| 2288 | +/* |
| 2289 | + * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 2290 | + * |
| 2291 | + * This program is free software; you can redistribute it and/or modify it |
| 2292 | + * under the terms of the GNU General Public License as published by the |
| 2293 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 2294 | + * option) any later version. |
| 2295 | + * |
| 2296 | + * This program is distributed in the hope that it will be useful, but |
| 2297 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2298 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 2299 | + * General Public License for more details. |
| 2300 | + * |
| 2301 | + * You should have received a copy of the GNU General Public License along |
| 2302 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 2303 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 2304 | + */ |
| 2305 | + |
| 2306 | +#include <linux/kernel.h> |
| 2307 | +#include <linux/types.h> |
| 2308 | +#include <linux/platform_device.h> |
| 2309 | +#include <linux/fsl_devices.h> |
| 2310 | +#include <asm/mcfsim.h> |
| 2311 | + |
| 2312 | +#define USB_OTGREGS_BASE MCF_REG32(0xFC0B0000) |
| 2313 | +#define INT_USB (64 + 64 + 47) /* INTC1:47 16.2.9.1 */ |
| 2314 | +#define INT_UOCSR (64 + 64 + 53) /* INTC1:53 16.2.9.1 */ |
| 2315 | + |
| 2316 | +#include "usb.h" |
| 2317 | + |
| 2318 | +/* |
| 2319 | + * platform data structs |
| 2320 | + * - Which one to use is determined by CONFIG options in usb.h |
| 2321 | + * - operating_mode plugged at run time |
| 2322 | + */ |
| 2323 | + |
| 2324 | +/* off-chip ULPI transceiver */ |
| 2325 | +static struct fsl_usb2_platform_data __maybe_unused dr_config_ulpi = { |
| 2326 | + .name = "DR", |
| 2327 | + .init = usb_platform_dr_init, |
| 2328 | + .exit = usb_platform_dr_uninit, |
| 2329 | + .phy_mode = FSL_USB2_PHY_ULPI, |
| 2330 | + .transceiver = "dr-ulpi", |
| 2331 | + .power_budget = 500, |
| 2332 | + .es = 1, |
| 2333 | + .big_endian_mmio = 1, |
| 2334 | + .big_endian_desc = 1, |
| 2335 | + .le_setup_buf = 1, |
| 2336 | +}; |
| 2337 | + |
| 2338 | +/* on-chip FS/LS serial transceiver */ |
| 2339 | +static struct fsl_usb2_platform_data __maybe_unused dr_config_fsls = { |
| 2340 | + .name = "DR", |
| 2341 | + .init = usb_platform_dr_init, |
| 2342 | + .exit = usb_platform_dr_uninit, |
| 2343 | + .phy_mode = FSL_USB2_PHY_SERIAL, |
| 2344 | + .transceiver = "dr-fsls", |
| 2345 | + .power_budget = 500, |
| 2346 | + .es = 1, |
| 2347 | + .big_endian_mmio = 1, |
| 2348 | + .big_endian_desc = 1, |
| 2349 | + .le_setup_buf = 1, |
| 2350 | +}; |
| 2351 | + |
| 2352 | +/* |
| 2353 | + * resources |
| 2354 | + */ |
| 2355 | +static struct resource dr_host_resources[] = { |
| 2356 | + [0] = { |
| 2357 | + .start = (u32)(&USB_OTGREGS_BASE), |
| 2358 | + .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), |
| 2359 | + .flags = IORESOURCE_MEM, |
| 2360 | + }, |
| 2361 | + [1] = { |
| 2362 | + .start = INT_USB, |
| 2363 | + .flags = IORESOURCE_IRQ, |
| 2364 | + }, |
| 2365 | +}; |
| 2366 | + |
| 2367 | +static struct resource dr_otg_resources[] = { |
| 2368 | + [0] = { |
| 2369 | + .start = (u32)(&USB_OTGREGS_BASE), |
| 2370 | + .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), |
| 2371 | + .flags = IORESOURCE_MEM, |
| 2372 | + }, |
| 2373 | + [1] = { |
| 2374 | + .start = INT_USB, |
| 2375 | + .flags = IORESOURCE_IRQ, |
| 2376 | + }, |
| 2377 | +}; |
| 2378 | + |
| 2379 | +static struct resource dr_udc_resources[] = { |
| 2380 | + [0] = { |
| 2381 | + .start = (u32)(&USB_OTGREGS_BASE), |
| 2382 | + .end = (u32)(&USB_OTGREGS_BASE + 0x1ff), |
| 2383 | + .flags = IORESOURCE_MEM, |
| 2384 | + }, |
| 2385 | + [1] = { |
| 2386 | + .start = INT_USB, |
| 2387 | + .flags = IORESOURCE_IRQ, |
| 2388 | + }, |
| 2389 | +}; |
| 2390 | +static u64 dr_udc_dmamask = ~(u32) 0; |
| 2391 | +static void dr_udc_release(struct device *dev) |
| 2392 | +{ |
| 2393 | +} |
| 2394 | + |
| 2395 | +static u64 dr_otg_dmamask = ~(u32) 0; |
| 2396 | +static void dr_otg_release(struct device *dev) |
| 2397 | +{ |
| 2398 | +} |
| 2399 | + |
| 2400 | +/* |
| 2401 | + * platform device structs |
| 2402 | + * dev.platform_data field plugged at run time |
| 2403 | + */ |
| 2404 | +static struct platform_device __maybe_unused dr_udc_device = { |
| 2405 | + .name = "fsl-usb2-udc", |
| 2406 | + .id = -1, |
| 2407 | + .dev = { |
| 2408 | + .release = dr_udc_release, |
| 2409 | + .dma_mask = &dr_udc_dmamask, |
| 2410 | + .coherent_dma_mask = 0xffffffff, |
| 2411 | + }, |
| 2412 | + .resource = dr_udc_resources, |
| 2413 | + .num_resources = ARRAY_SIZE(dr_udc_resources), |
| 2414 | +}; |
| 2415 | + |
| 2416 | +static struct platform_device __maybe_unused dr_otg_device = { |
| 2417 | + .name = "fsl-usb2-otg", |
| 2418 | + .id = -1, |
| 2419 | + .dev = { |
| 2420 | + .release = dr_otg_release, |
| 2421 | + .dma_mask = &dr_otg_dmamask, |
| 2422 | + .coherent_dma_mask = 0xffffffff, |
| 2423 | + }, |
| 2424 | + .resource = dr_otg_resources, |
| 2425 | + .num_resources = ARRAY_SIZE(dr_otg_resources), |
| 2426 | +}; |
| 2427 | + |
| 2428 | +static int __init usb_dr_init(void) |
| 2429 | +{ |
| 2430 | + pr_debug("%s:\n", __func__); |
| 2431 | + |
| 2432 | + dr_register_otg(); |
| 2433 | + dr_register_host(dr_host_resources, ARRAY_SIZE(dr_host_resources)); |
| 2434 | + dr_register_udc(); |
| 2435 | + |
| 2436 | + return 0; |
| 2437 | +} |
| 2438 | + |
| 2439 | +module_init(usb_dr_init); |
| 2440 | --- /dev/null |
| 2441 | +++ b/arch/m68k/coldfire/m5445x/xcvr.c |
| 2442 | @@ -0,0 +1,127 @@ |
| 2443 | +/* |
| 2444 | + * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 2445 | + * |
| 2446 | + * This program is free software; you can redistribute it and/or modify it |
| 2447 | + * under the terms of the GNU General Public License as published by the |
| 2448 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 2449 | + * option) any later version. |
| 2450 | + * |
| 2451 | + * This program is distributed in the hope that it will be useful, but |
| 2452 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2453 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 2454 | + * General Public License for more details. |
| 2455 | + * |
| 2456 | + * You should have received a copy of the GNU General Public License along |
| 2457 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 2458 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 2459 | + */ |
| 2460 | + |
| 2461 | +#include <linux/module.h> |
| 2462 | +#include <linux/kernel.h> |
| 2463 | +#include <linux/types.h> |
| 2464 | +#include <linux/init.h> |
| 2465 | +#include <linux/io.h> |
| 2466 | +#include <linux/usb/fsl_xcvr.h> |
| 2467 | +#include <asm/mcfsim.h> |
| 2468 | + |
| 2469 | +/* Use the configured xcvr_ops */ |
| 2470 | +#ifdef CONFIG_USB_M5445X_ULPI |
| 2471 | +#define XCVR_OPS (&xcvr_ops_ulpi) |
| 2472 | +#elif defined CONFIG_USB_M5445X_FSLS |
| 2473 | +#define XCVR_OPS (&xcvr_ops_fsls) |
| 2474 | +#else |
| 2475 | +#error "Invalid USB transceiver selection." |
| 2476 | +#endif |
| 2477 | + |
| 2478 | +/* |
| 2479 | + * Init routine for on-chip FSLS xcvr |
| 2480 | + */ |
| 2481 | +static void xcvr_fsls_init(struct fsl_xcvr_ops *this) |
| 2482 | +{ |
| 2483 | + pr_debug("%s: name=%s\n", __func__, this->name); |
| 2484 | + |
| 2485 | + /* Enable VBUS_EN and VBUS_OC signals */ |
| 2486 | + MCF_GPIO_PAR_USB = MCF_GPIO_PAR_USB_VBUSEN_VBUSEN | |
| 2487 | + MCF_GPIO_PAR_USB_VBUSOC_VBUSOC; |
| 2488 | + |
| 2489 | + /* Setup USB_VBUS_OC signal to be active-low */ |
| 2490 | + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_USBOC; |
| 2491 | +} |
| 2492 | + |
| 2493 | +/* |
| 2494 | + * Init routine for off-chip ULPI xcvr |
| 2495 | + */ |
| 2496 | +static void xcvr_ulpi_init(struct fsl_xcvr_ops *this) |
| 2497 | +{ |
| 2498 | + pr_debug("%s: name=%s\n", __func__, this->name); |
| 2499 | + |
| 2500 | + /* Enable the required ULPI signals */ |
| 2501 | + MCF_GPIO_PAR_DMA = (MCF_GPIO_PAR_DMA & |
| 2502 | + MCF_GPIO_PAR_DMA_DACK1_MASK) | |
| 2503 | + MCF_GPIO_PAR_DMA_DACK1_ULPI_DIR; |
| 2504 | + |
| 2505 | + MCF_GPIO_PAR_USB = MCF_GPIO_PAR_USB_VBUSEN_ULPI_NXT | |
| 2506 | + MCF_GPIO_PAR_USB_VBUSOC_ULPI_STP; |
| 2507 | + |
| 2508 | + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC & |
| 2509 | + MCF_GPIO_PAR_FEC_FEC0_MASK) | |
| 2510 | + MCF_GPIO_PAR_FEC_FEC0_RMII_ULPI; |
| 2511 | +} |
| 2512 | + |
| 2513 | +static void xcvr_uninit(struct fsl_xcvr_ops *this) |
| 2514 | +{ |
| 2515 | + pr_debug("%s\n", __func__); |
| 2516 | +} |
| 2517 | + |
| 2518 | +static void xcvr_pullup(int on) |
| 2519 | +{ |
| 2520 | + unsigned short ccm = in_be16(&MCF_CCM_UOCSR); |
| 2521 | + |
| 2522 | + pr_debug("%s(%d)\n", __func__, on); |
| 2523 | + |
| 2524 | + ccm = in_be16(&MCF_CCM_UOCSR); |
| 2525 | + if (on) { |
| 2526 | + ccm |= MCF_CCM_UOCSR_BVLD; |
| 2527 | + ccm &= ~MCF_CCM_UOCSR_SEND; |
| 2528 | + out_be16(&MCF_CCM_UOCSR, ccm); |
| 2529 | + } else { |
| 2530 | + ccm &= ~MCF_CCM_UOCSR_BVLD; |
| 2531 | + out_be16(&MCF_CCM_UOCSR, ccm); |
| 2532 | + } |
| 2533 | +} |
| 2534 | + |
| 2535 | +struct fsl_xcvr_ops xcvr_ops_ulpi = { |
| 2536 | + .init = xcvr_ulpi_init, |
| 2537 | + .uninit = xcvr_uninit, |
| 2538 | + .pullup = xcvr_pullup, |
| 2539 | + .name = "dr-ulpi", |
| 2540 | +}; |
| 2541 | + |
| 2542 | +struct fsl_xcvr_ops xcvr_ops_fsls = { |
| 2543 | + .init = xcvr_fsls_init, |
| 2544 | + .uninit = xcvr_uninit, |
| 2545 | + .pullup = xcvr_pullup, |
| 2546 | + .name = "dr-fsls", |
| 2547 | +}; |
| 2548 | + |
| 2549 | +static int __init usb_xcvr_init(void) |
| 2550 | +{ |
| 2551 | + struct fsl_xcvr_ops *xops = XCVR_OPS; |
| 2552 | + |
| 2553 | + pr_debug("%s %s\n", __func__, xops->name); |
| 2554 | + fsl_usb_xcvr_register(xops); |
| 2555 | + |
| 2556 | + return 0; |
| 2557 | +} |
| 2558 | + |
| 2559 | +static void __exit usb_xcvr_exit(void) |
| 2560 | +{ |
| 2561 | + fsl_usb_xcvr_unregister(XCVR_OPS); |
| 2562 | +} |
| 2563 | + |
| 2564 | +module_init(usb_xcvr_init); |
| 2565 | +module_exit(usb_xcvr_exit); |
| 2566 | + |
| 2567 | +MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
| 2568 | +MODULE_DESCRIPTION("External ULPI xcvr driver"); |
| 2569 | +MODULE_LICENSE("GPL"); |
| 2570 | --- /dev/null |
| 2571 | +++ b/arch/m68k/include/asm/fsl_usb_gadget.h |
| 2572 | @@ -0,0 +1,45 @@ |
| 2573 | +/* |
| 2574 | + * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 2575 | + * |
| 2576 | + * This program is free software; you can redistribute it and/or modify it |
| 2577 | + * under the terms of the GNU General Public License as published by the |
| 2578 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 2579 | + * option) any later version. |
| 2580 | + * |
| 2581 | + * This program is distributed in the hope that it will be useful, |
| 2582 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2583 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 2584 | + * GNU General Public License for more details. |
| 2585 | + * |
| 2586 | + * You should have received a copy of the GNU General Public License |
| 2587 | + * along with this program; if not, write to the Free Software |
| 2588 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 2589 | + */ |
| 2590 | + |
| 2591 | +/* |
| 2592 | + * USB Gadget side, platform-specific functionality. |
| 2593 | + */ |
| 2594 | + |
| 2595 | +#include <linux/usb/fsl_xcvr.h> |
| 2596 | + |
| 2597 | +/* Needed for i2c/serial transceivers */ |
| 2598 | +static inline void |
| 2599 | +fsl_platform_set_device_mode(struct fsl_usb2_platform_data *pdata) |
| 2600 | +{ |
| 2601 | + if (pdata->xcvr_ops && pdata->xcvr_ops->set_device) |
| 2602 | + pdata->xcvr_ops->set_device(); |
| 2603 | +} |
| 2604 | + |
| 2605 | +static inline void |
| 2606 | +fsl_platform_pullup_enable(struct fsl_usb2_platform_data *pdata) |
| 2607 | +{ |
| 2608 | + if (pdata->xcvr_ops && pdata->xcvr_ops->pullup) |
| 2609 | + pdata->xcvr_ops->pullup(1); |
| 2610 | +} |
| 2611 | + |
| 2612 | +static inline void |
| 2613 | +fsl_platform_pullup_disable(struct fsl_usb2_platform_data *pdata) |
| 2614 | +{ |
| 2615 | + if (pdata->xcvr_ops && pdata->xcvr_ops->pullup) |
| 2616 | + pdata->xcvr_ops->pullup(0); |
| 2617 | +} |
| 2618 | --- /dev/null |
| 2619 | +++ b/arch/m68k/include/asm/fsl_usb_io.h |
| 2620 | @@ -0,0 +1,43 @@ |
| 2621 | +/* Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 2622 | + * |
| 2623 | + * This program is free software; you can redistribute it and/or modify it |
| 2624 | + * under the terms of the GNU General Public License as published by the |
| 2625 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 2626 | + * option) any later version. |
| 2627 | + * |
| 2628 | + * This program is distributed in the hope that it will be useful, but |
| 2629 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 2630 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 2631 | + * General Public License for more details. |
| 2632 | + * |
| 2633 | + * You should have received a copy of the GNU General Public License along |
| 2634 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 2635 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 2636 | + */ |
| 2637 | +#ifndef _FSL_USB_IO_H |
| 2638 | +#define _FSL_USB_IO_H |
| 2639 | + |
| 2640 | +#undef inb_p |
| 2641 | +#undef outb_p |
| 2642 | +#undef inl_p |
| 2643 | +#undef outl_p |
| 2644 | +#define inb_p in_8 |
| 2645 | +#define outb_p(b, addr) (void)((*(__force volatile u8 *) (addr)) = (b)) |
| 2646 | +#define inl_p in_be32 |
| 2647 | +#define outl_p(l, addr) (void)((*(__force volatile u32 *) (addr)) = (l)) |
| 2648 | + |
| 2649 | +#define fsl_readl(addr) in_be32((__force unsigned *)(addr)) |
| 2650 | +#define fsl_writel(val32, addr) out_be32((__force unsigned *)(addr), (val32)) |
| 2651 | + |
| 2652 | +static inline void fsl_set_usb_accessors(struct fsl_usb2_platform_data *pdata) |
| 2653 | +{ |
| 2654 | +} |
| 2655 | +/* |
| 2656 | +#ifndef cpu_to_hc32 |
| 2657 | +#define cpu_to_hc32(x) (x) |
| 2658 | +#endif |
| 2659 | +#ifndef hc32_to_cpu |
| 2660 | +#define hc32_to_cpu(x) (x) |
| 2661 | +#endif |
| 2662 | +*/ |
| 2663 | +#endif /* _FSL_USB_IO_H */ |
| 2664 | --- /dev/null |
| 2665 | +++ b/arch/m68k/include/asm/fsl_usb_platform.h |
| 2666 | @@ -0,0 +1,78 @@ |
| 2667 | +/* |
| 2668 | + * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 2669 | + */ |
| 2670 | + |
| 2671 | +/* |
| 2672 | + * The code contained herein is licensed under the GNU General Public |
| 2673 | + * License. You may obtain a copy of the GNU General Public License |
| 2674 | + * Version 2 or later at the following locations: |
| 2675 | + * |
| 2676 | + * http://www.opensource.org/licenses/gpl-license.html |
| 2677 | + * http://www.gnu.org/copyleft/gpl.html |
| 2678 | + */ |
| 2679 | + |
| 2680 | +#ifndef FSL_USB_PLATFORM_H |
| 2681 | +#define FSL_USB_PLATFORM_H |
| 2682 | + |
| 2683 | +#include <linux/usb/fsl_xcvr.h> |
| 2684 | +#include <linux/usb/fsl_usb2.h> |
| 2685 | +#include <asm/mcfsim.h> |
| 2686 | + |
| 2687 | +extern struct resource *otg_get_resources(void); |
| 2688 | + |
| 2689 | +extern struct fsl_usb2_platform_data; |
| 2690 | + |
| 2691 | +/* ehci_arc_hc_driver.flags value */ |
| 2692 | +#define FSL_PLATFORM_HC_FLAGS (HCD_USB2 | HCD_MEMORY) |
| 2693 | + |
| 2694 | +static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, |
| 2695 | + enum fsl_usb2_phy_modes phy_mode, |
| 2696 | + unsigned int port_offset); |
| 2697 | + |
| 2698 | +static inline void fsl_platform_usb_setup(struct ehci_hcd *ehci) |
| 2699 | +{ |
| 2700 | + struct fsl_usb2_platform_data *pdata; |
| 2701 | + |
| 2702 | + pdata = ehci_to_hcd(ehci)->self.controller->platform_data; |
| 2703 | + ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); |
| 2704 | +} |
| 2705 | + |
| 2706 | +static inline void fsl_platform_set_host_mode(struct usb_hcd *hcd) |
| 2707 | +{ |
| 2708 | + unsigned int temp; |
| 2709 | + struct fsl_usb2_platform_data *pdata; |
| 2710 | + struct fsl_usb_host_regs *regs; |
| 2711 | + |
| 2712 | + pdata = hcd->self.controller->platform_data; |
| 2713 | + regs = pdata->regs; |
| 2714 | + |
| 2715 | + if (pdata->xcvr_ops && pdata->xcvr_ops->set_host) |
| 2716 | + pdata->xcvr_ops->set_host(); |
| 2717 | + |
| 2718 | + /* set host mode and select "big endian" */ |
| 2719 | + temp = in_be32(®s->usbmode); |
| 2720 | + temp |= USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); |
| 2721 | + out_be32(®s->usbmode, temp); |
| 2722 | + |
| 2723 | + pr_debug("%s: set usbmode to 0x%x\n\n", __func__, |
| 2724 | + in_be32(®s->usbmode)); |
| 2725 | + |
| 2726 | +} |
| 2727 | + |
| 2728 | +static inline void |
| 2729 | +fsl_platform_set_vbus_power(struct fsl_usb2_platform_data *pdata, int on) |
| 2730 | +{ |
| 2731 | +#ifdef CONFIG_USB_M5441X_FSLS |
| 2732 | + MCF_GPIO_PAR_CS &= 0x0F; /*Enable GPIOB5, GPIOB6*/ |
| 2733 | + |
| 2734 | + MCF_GPIO_PDDR_B &= 0xDF; /*GPIOB5, input*/ |
| 2735 | + MCF_GPIO_PDDR_B |= 0x40; /*GPIOB6, output*/ |
| 2736 | + |
| 2737 | + if (on) |
| 2738 | + MCF_GPIO_PODR_B |= 0x40; /*GPIOB6, output 1*/ |
| 2739 | + else |
| 2740 | + MCF_GPIO_PODR_B &= 0xBF; /*GPIOB6, output 0*/ |
| 2741 | +#endif |
| 2742 | +} |
| 2743 | + |
| 2744 | +#endif |
| 2745 | --- a/drivers/Makefile |
| 2746 | +++ b/drivers/Makefile |
| 2747 | @@ -66,6 +66,7 @@ obj-$(CONFIG_PARIDE) += block/paride/ |
| 2748 | obj-$(CONFIG_TC) += tc/ |
| 2749 | obj-$(CONFIG_UWB) += uwb/ |
| 2750 | obj-$(CONFIG_USB_OTG_UTILS) += usb/otg/ |
| 2751 | +obj-$(CONFIG_USB_OTG) += usb/otg/ |
| 2752 | obj-$(CONFIG_USB) += usb/ |
| 2753 | obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/ |
| 2754 | obj-$(CONFIG_PCI) += usb/ |
| 2755 | --- a/drivers/usb/Kconfig |
| 2756 | +++ b/drivers/usb/Kconfig |
| 2757 | @@ -57,6 +57,8 @@ config USB_ARCH_HAS_EHCI |
| 2758 | boolean |
| 2759 | default y if PPC_83xx |
| 2760 | default y if PPC_MPC512x |
| 2761 | + default y if M5445X |
| 2762 | + default y if M5441X |
| 2763 | default y if SOC_AU1200 |
| 2764 | default y if ARCH_IXP4XX |
| 2765 | default y if ARCH_W90X900 |
| 2766 | --- a/drivers/usb/core/Kconfig |
| 2767 | +++ b/drivers/usb/core/Kconfig |
| 2768 | @@ -109,7 +109,7 @@ config USB_SUSPEND |
| 2769 | config USB_OTG |
| 2770 | bool "OTG support" |
| 2771 | depends on USB && EXPERIMENTAL |
| 2772 | - depends on USB_SUSPEND |
| 2773 | +# depends on USB_SUSPEND |
| 2774 | default n |
| 2775 | help |
| 2776 | The most notable feature of USB OTG is support for a |
| 2777 | --- a/drivers/usb/gadget/Kconfig |
| 2778 | +++ b/drivers/usb/gadget/Kconfig |
| 2779 | @@ -156,7 +156,7 @@ config USB_ATMEL_USBA |
| 2780 | |
| 2781 | config USB_GADGET_FSL_USB2 |
| 2782 | boolean "Freescale Highspeed USB DR Peripheral Controller" |
| 2783 | - depends on FSL_SOC || ARCH_MXC |
| 2784 | + depends on FSL_SOC || ARCH_MXC || HAVE_FSL_USB_DR |
| 2785 | select USB_GADGET_DUALSPEED |
| 2786 | select USB_FSL_MPH_DR_OF if OF |
| 2787 | help |
| 2788 | --- a/drivers/usb/gadget/fsl_udc_core.c |
| 2789 | +++ b/drivers/usb/gadget/fsl_udc_core.c |
| 2790 | @@ -1,5 +1,5 @@ |
| 2791 | /* |
| 2792 | - * Copyright (C) 2004-2007 Freescale Semicondutor, Inc. All rights reserved. |
| 2793 | + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. All rights reserved. |
| 2794 | * |
| 2795 | * Author: Li Yang <leoli@freescale.com> |
| 2796 | * Jiang Bo <tanya.jiang@freescale.com> |
| 2797 | @@ -52,6 +52,12 @@ |
| 2798 | #define DRIVER_AUTHOR "Li Yang/Jiang Bo" |
| 2799 | #define DRIVER_VERSION "Apr 20, 2007" |
| 2800 | |
| 2801 | + |
| 2802 | +#define USB_MODE_CTRL_MODE_MASK 0x00000003 |
| 2803 | +#define USB_MODE_ES 0x00000004 /* (big) Endian */ |
| 2804 | +#define cpu_to_hc32(x) (x) |
| 2805 | +#define hc32_to_cpu(x) (x) |
| 2806 | + |
| 2807 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) |
| 2808 | |
| 2809 | static const char driver_name[] = "fsl-usb2-udc"; |
| 2810 | @@ -62,6 +68,9 @@ static struct usb_dr_device *dr_regs; |
| 2811 | static struct usb_sys_interface *usb_sys_regs; |
| 2812 | #endif |
| 2813 | |
| 2814 | +static int fsl_udc_suspend(struct device *dev, pm_message_t state); |
| 2815 | +static int fsl_udc_resume(struct device *dev); |
| 2816 | + |
| 2817 | /* it is initialized in probe() */ |
| 2818 | static struct fsl_udc *udc_controller = NULL; |
| 2819 | |
| 2820 | @@ -76,6 +85,7 @@ fsl_ep0_desc = { |
| 2821 | |
| 2822 | static void fsl_ep_fifo_flush(struct usb_ep *_ep); |
| 2823 | |
| 2824 | +#ifndef CONFIG_COLDFIRE |
| 2825 | #ifdef CONFIG_PPC32 |
| 2826 | #define fsl_readl(addr) in_le32(addr) |
| 2827 | #define fsl_writel(val32, addr) out_le32(addr, val32) |
| 2828 | @@ -83,7 +93,7 @@ static void fsl_ep_fifo_flush(struct usb |
| 2829 | #define fsl_readl(addr) readl(addr) |
| 2830 | #define fsl_writel(val32, addr) writel(val32, addr) |
| 2831 | #endif |
| 2832 | - |
| 2833 | +#endif |
| 2834 | /******************************************************************** |
| 2835 | * Internal Used Function |
| 2836 | ********************************************************************/ |
| 2837 | @@ -184,6 +194,12 @@ static int dr_controller_setup(struct fs |
| 2838 | unsigned long timeout; |
| 2839 | #define FSL_UDC_RESET_TIMEOUT 1000 |
| 2840 | |
| 2841 | +#ifdef CONFIG_COLDFIRE |
| 2842 | + struct fsl_usb2_platform_data *pdata; |
| 2843 | + if (!udc) |
| 2844 | + return -EINVAL; |
| 2845 | + pdata = udc->pdata; |
| 2846 | +#endif |
| 2847 | /* Config PHY interface */ |
| 2848 | portctrl = fsl_readl(&dr_regs->portsc1); |
| 2849 | portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); |
| 2850 | @@ -226,11 +242,20 @@ static int dr_controller_setup(struct fs |
| 2851 | |
| 2852 | /* Set the controller as device mode */ |
| 2853 | tmp = fsl_readl(&dr_regs->usbmode); |
| 2854 | +#ifdef CONFIG_COLDFIRE |
| 2855 | + tmp &= ~USB_MODE_CTRL_MODE_MASK; /* clear mode bits */ |
| 2856 | +#endif |
| 2857 | tmp |= USB_MODE_CTRL_MODE_DEVICE; |
| 2858 | /* Disable Setup Lockout */ |
| 2859 | tmp |= USB_MODE_SETUP_LOCK_OFF; |
| 2860 | +#ifdef CONFIG_COLDFIRE |
| 2861 | + if (pdata->es) |
| 2862 | + tmp |= USB_MODE_ES; |
| 2863 | +#endif |
| 2864 | fsl_writel(tmp, &dr_regs->usbmode); |
| 2865 | - |
| 2866 | +#ifdef CONFIG_COLDFIRE |
| 2867 | + fsl_platform_set_device_mode(pdata); |
| 2868 | +#endif |
| 2869 | /* Clear the setup status */ |
| 2870 | fsl_writel(0, &dr_regs->usbsts); |
| 2871 | |
| 2872 | @@ -243,7 +268,7 @@ static int dr_controller_setup(struct fs |
| 2873 | fsl_readl(&dr_regs->endpointlistaddr)); |
| 2874 | |
| 2875 | /* Config control enable i/o output, cpu endian register */ |
| 2876 | -#ifndef CONFIG_ARCH_MXC |
| 2877 | +#if !defined(CONFIG_ARCH_MXC) && !defined(CONFIG_COLDFIRE) |
| 2878 | ctrl = __raw_readl(&usb_sys_regs->control); |
| 2879 | ctrl |= USB_CTRL_IOENB; |
| 2880 | __raw_writel(ctrl, &usb_sys_regs->control); |
| 2881 | @@ -267,7 +292,9 @@ static int dr_controller_setup(struct fs |
| 2882 | static void dr_controller_run(struct fsl_udc *udc) |
| 2883 | { |
| 2884 | u32 temp; |
| 2885 | - |
| 2886 | +#ifdef CONFIG_COLDFIRE |
| 2887 | + fsl_platform_pullup_enable(udc->pdata); |
| 2888 | +#endif |
| 2889 | /* Enable DR irq reg */ |
| 2890 | temp = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN |
| 2891 | | USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN |
| 2892 | @@ -277,12 +304,12 @@ static void dr_controller_run(struct fsl |
| 2893 | |
| 2894 | /* Clear stopped bit */ |
| 2895 | udc->stopped = 0; |
| 2896 | - |
| 2897 | +#ifndef CONFIG_COLDFIRE |
| 2898 | /* Set the controller as device mode */ |
| 2899 | temp = fsl_readl(&dr_regs->usbmode); |
| 2900 | temp |= USB_MODE_CTRL_MODE_DEVICE; |
| 2901 | fsl_writel(temp, &dr_regs->usbmode); |
| 2902 | - |
| 2903 | +#endif |
| 2904 | /* Set controller to Run */ |
| 2905 | temp = fsl_readl(&dr_regs->usbcmd); |
| 2906 | temp |= USB_CMD_RUN_STOP; |
| 2907 | @@ -292,7 +319,18 @@ static void dr_controller_run(struct fsl |
| 2908 | static void dr_controller_stop(struct fsl_udc *udc) |
| 2909 | { |
| 2910 | unsigned int tmp; |
| 2911 | - |
| 2912 | +#ifdef CONFIG_COLDFIRE |
| 2913 | + if (udc->gadget.is_otg) { |
| 2914 | +#ifdef CONFIG_USB_M5441X_MAX3353_FSLS |
| 2915 | + if (max3353_read_id_pin()) { |
| 2916 | +#else |
| 2917 | + if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) { |
| 2918 | +#endif |
| 2919 | + pr_debug("udc: Leaving early\n"); |
| 2920 | + return; |
| 2921 | + } |
| 2922 | + } |
| 2923 | +#endif |
| 2924 | /* disable all INTR */ |
| 2925 | fsl_writel(0, &dr_regs->usbintr); |
| 2926 | |
| 2927 | @@ -301,7 +339,9 @@ static void dr_controller_stop(struct fs |
| 2928 | |
| 2929 | /* disable IO output */ |
| 2930 | /* usb_sys_regs->control = 0; */ |
| 2931 | - |
| 2932 | +#ifdef CONFIG_COLDFIRE |
| 2933 | + fsl_platform_pullup_disable(udc->pdata); |
| 2934 | +#endif |
| 2935 | /* set controller to Stop */ |
| 2936 | tmp = fsl_readl(&dr_regs->usbcmd); |
| 2937 | tmp &= ~USB_CMD_RUN_STOP; |
| 2938 | @@ -408,10 +448,13 @@ static void struct_ep_qh_setup(struct fs |
| 2939 | } |
| 2940 | if (zlt) |
| 2941 | tmp |= EP_QUEUE_HEAD_ZLT_SEL; |
| 2942 | - |
| 2943 | +#ifdef CONFIG_COLDFIRE |
| 2944 | + p_QH->max_pkt_length = cpu_to_hc32(tmp); |
| 2945 | +#else |
| 2946 | p_QH->max_pkt_length = cpu_to_le32(tmp); |
| 2947 | p_QH->next_dtd_ptr = 1; |
| 2948 | p_QH->size_ioc_int_sts = 0; |
| 2949 | +#endif |
| 2950 | } |
| 2951 | |
| 2952 | /* Setup qh structure and ep register for ep0. */ |
| 2953 | @@ -616,7 +659,11 @@ static void fsl_queue_td(struct fsl_ep * |
| 2954 | struct fsl_req *lastreq; |
| 2955 | lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); |
| 2956 | lastreq->tail->next_td_ptr = |
| 2957 | +#ifdef CONFIG_COLDFIRE |
| 2958 | + cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); |
| 2959 | +#else |
| 2960 | cpu_to_le32(req->head->td_dma & DTD_ADDR_MASK); |
| 2961 | +#endif |
| 2962 | /* Read prime bit, if 1 goto done */ |
| 2963 | if (fsl_readl(&dr_regs->endpointprime) & bitmask) |
| 2964 | goto out; |
| 2965 | @@ -641,11 +688,19 @@ static void fsl_queue_td(struct fsl_ep * |
| 2966 | |
| 2967 | /* Write dQH next pointer and terminate bit to 0 */ |
| 2968 | temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; |
| 2969 | +#ifdef CONFIG_COLDFIRE |
| 2970 | + dQH->next_dtd_ptr = cpu_to_hc32(temp); |
| 2971 | +#else |
| 2972 | dQH->next_dtd_ptr = cpu_to_le32(temp); |
| 2973 | - |
| 2974 | +#endif |
| 2975 | /* Clear active and halt bit */ |
| 2976 | +#ifdef CONFIG_COLDFIRE |
| 2977 | + temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE |
| 2978 | + | EP_QUEUE_HEAD_STATUS_HALT)); |
| 2979 | +#else |
| 2980 | temp = cpu_to_le32(~(EP_QUEUE_HEAD_STATUS_ACTIVE |
| 2981 | | EP_QUEUE_HEAD_STATUS_HALT)); |
| 2982 | +#endif |
| 2983 | dQH->size_ioc_int_sts &= temp; |
| 2984 | |
| 2985 | /* Ensure that updates to the QH will occure before priming. */ |
| 2986 | @@ -682,18 +737,32 @@ static struct ep_td_struct *fsl_build_dt |
| 2987 | |
| 2988 | dtd->td_dma = *dma; |
| 2989 | /* Clear reserved field */ |
| 2990 | +#ifdef CONFIG_COLDFIRE |
| 2991 | + swap_temp = hc32_to_cpu(dtd->size_ioc_sts); |
| 2992 | +#else |
| 2993 | swap_temp = cpu_to_le32(dtd->size_ioc_sts); |
| 2994 | +#endif |
| 2995 | swap_temp &= ~DTD_RESERVED_FIELDS; |
| 2996 | +#ifdef CONFIG_COLDFIRE |
| 2997 | + dtd->size_ioc_sts = cpu_to_hc32(swap_temp); |
| 2998 | +#else |
| 2999 | dtd->size_ioc_sts = cpu_to_le32(swap_temp); |
| 3000 | - |
| 3001 | +#endif |
| 3002 | /* Init all of buffer page pointers */ |
| 3003 | swap_temp = (u32) (req->req.dma + req->req.actual); |
| 3004 | +#ifdef CONFIG_COLDFIRE |
| 3005 | + dtd->buff_ptr0 = cpu_to_hc32(swap_temp); |
| 3006 | + dtd->buff_ptr1 = cpu_to_hc32(swap_temp + 0x1000); |
| 3007 | + dtd->buff_ptr2 = cpu_to_hc32(swap_temp + 0x2000); |
| 3008 | + dtd->buff_ptr3 = cpu_to_hc32(swap_temp + 0x3000); |
| 3009 | + dtd->buff_ptr4 = cpu_to_hc32(swap_temp + 0x4000); |
| 3010 | +#else |
| 3011 | dtd->buff_ptr0 = cpu_to_le32(swap_temp); |
| 3012 | dtd->buff_ptr1 = cpu_to_le32(swap_temp + 0x1000); |
| 3013 | dtd->buff_ptr2 = cpu_to_le32(swap_temp + 0x2000); |
| 3014 | dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000); |
| 3015 | dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000); |
| 3016 | - |
| 3017 | +#endif |
| 3018 | req->req.actual += *length; |
| 3019 | |
| 3020 | /* zlp is needed if req->req.zero is set */ |
| 3021 | @@ -715,9 +784,11 @@ static struct ep_td_struct *fsl_build_dt |
| 3022 | /* Enable interrupt for the last dtd of a request */ |
| 3023 | if (*is_last && !req->req.no_interrupt) |
| 3024 | swap_temp |= DTD_IOC; |
| 3025 | - |
| 3026 | +#ifdef CONFIG_COLDFIRE |
| 3027 | + dtd->size_ioc_sts = cpu_to_hc32(swap_temp); |
| 3028 | +#else |
| 3029 | dtd->size_ioc_sts = cpu_to_le32(swap_temp); |
| 3030 | - |
| 3031 | +#endif |
| 3032 | mb(); |
| 3033 | |
| 3034 | VDBG("length = %d address= 0x%x", *length, (int)*dma); |
| 3035 | @@ -743,16 +814,22 @@ static int fsl_req_to_dtd(struct fsl_req |
| 3036 | is_first = 0; |
| 3037 | req->head = dtd; |
| 3038 | } else { |
| 3039 | +#ifdef CONFIG_COLDFIRE |
| 3040 | + last_dtd->next_td_ptr = cpu_to_hc32(dma); |
| 3041 | +#else |
| 3042 | last_dtd->next_td_ptr = cpu_to_le32(dma); |
| 3043 | +#endif |
| 3044 | last_dtd->next_td_virt = dtd; |
| 3045 | } |
| 3046 | last_dtd = dtd; |
| 3047 | |
| 3048 | req->dtd_count++; |
| 3049 | } while (!is_last); |
| 3050 | - |
| 3051 | +#ifdef CONFIG_COLDFIRE |
| 3052 | + dtd->next_td_ptr = cpu_to_hc32(DTD_NEXT_TERMINATE); |
| 3053 | +#else |
| 3054 | dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE); |
| 3055 | - |
| 3056 | +#endif |
| 3057 | req->tail = dtd; |
| 3058 | |
| 3059 | return 0; |
| 3060 | @@ -963,7 +1040,39 @@ out: |
| 3061 | |
| 3062 | return status; |
| 3063 | } |
| 3064 | +#ifdef CONFIG_COLDFIRE |
| 3065 | +static int arcotg_fifo_status(struct usb_ep *_ep) |
| 3066 | +{ |
| 3067 | + struct fsl_ep *ep; |
| 3068 | + struct fsl_udc *udc; |
| 3069 | + int size = 0; |
| 3070 | + u32 bitmask; |
| 3071 | + struct ep_queue_head *d_qh; |
| 3072 | + |
| 3073 | + ep = container_of(_ep, struct fsl_ep, ep); |
| 3074 | + if (!_ep || (!ep->desc && ep_index(ep) != 0)) |
| 3075 | + return -ENODEV; |
| 3076 | + |
| 3077 | + udc = (struct fsl_udc *)ep->udc; |
| 3078 | + |
| 3079 | + if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) |
| 3080 | + return -ESHUTDOWN; |
| 3081 | + |
| 3082 | + d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)]; |
| 3083 | + |
| 3084 | + bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) : |
| 3085 | + (1 << (ep_index(ep))); |
| 3086 | + |
| 3087 | + if (fsl_readl(&dr_regs->endptstatus) & bitmask) |
| 3088 | + size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE) |
| 3089 | + >> DTD_LENGTH_BIT_POS; |
| 3090 | + |
| 3091 | + pr_debug("%s %u\n", __func__, size); |
| 3092 | + return size; |
| 3093 | +} |
| 3094 | + |
| 3095 | |
| 3096 | +#endif |
| 3097 | static void fsl_ep_fifo_flush(struct usb_ep *_ep) |
| 3098 | { |
| 3099 | struct fsl_ep *ep; |
| 3100 | @@ -1016,6 +1125,9 @@ static struct usb_ep_ops fsl_ep_ops = { |
| 3101 | .dequeue = fsl_ep_dequeue, |
| 3102 | |
| 3103 | .set_halt = fsl_ep_set_halt, |
| 3104 | +#ifdef CONFIG_COLDFIRE |
| 3105 | + .fifo_status = arcotg_fifo_status, |
| 3106 | +#endif |
| 3107 | .fifo_flush = fsl_ep_fifo_flush, /* flush fifo */ |
| 3108 | }; |
| 3109 | |
| 3110 | @@ -1396,7 +1508,9 @@ static void tripwire_handler(struct fsl_ |
| 3111 | { |
| 3112 | u32 temp; |
| 3113 | struct ep_queue_head *qh; |
| 3114 | - |
| 3115 | +#ifdef CONFIG_COLDFIRE |
| 3116 | + struct fsl_usb2_platform_data *pdata = udc->pdata; |
| 3117 | +#endif |
| 3118 | qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT]; |
| 3119 | |
| 3120 | /* Clear bit in ENDPTSETUPSTAT */ |
| 3121 | @@ -1410,7 +1524,20 @@ static void tripwire_handler(struct fsl_ |
| 3122 | fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd); |
| 3123 | |
| 3124 | /* Copy the setup packet to local buffer */ |
| 3125 | +#if CONFIG_COLDFIRE |
| 3126 | + if (pdata->le_setup_buf) { |
| 3127 | + u32 *p = (u32 *)buffer_ptr; |
| 3128 | + u32 *s = (u32 *)qh->setup_buffer; |
| 3129 | + |
| 3130 | + /* Convert little endian setup buffer to CPU endian */ |
| 3131 | + *p++ = le32_to_cpu(*s++); |
| 3132 | + *p = le32_to_cpu(*s); |
| 3133 | + } else { |
| 3134 | + memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8); |
| 3135 | + } |
| 3136 | +#else |
| 3137 | memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8); |
| 3138 | +#endif |
| 3139 | } while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW)); |
| 3140 | |
| 3141 | /* Clear Setup Tripwire */ |
| 3142 | @@ -1434,19 +1561,19 @@ static int process_ep_req(struct fsl_udc |
| 3143 | actual = curr_req->req.length; |
| 3144 | |
| 3145 | for (j = 0; j < curr_req->dtd_count; j++) { |
| 3146 | - remaining_length = (le32_to_cpu(curr_td->size_ioc_sts) |
| 3147 | + remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts) |
| 3148 | & DTD_PACKET_SIZE) |
| 3149 | >> DTD_LENGTH_BIT_POS; |
| 3150 | actual -= remaining_length; |
| 3151 | |
| 3152 | - if ((errors = le32_to_cpu(curr_td->size_ioc_sts) & |
| 3153 | - DTD_ERROR_MASK)) { |
| 3154 | + errors = hc32_to_cpu(curr_td->size_ioc_sts); |
| 3155 | + if (errors & DTD_ERROR_MASK) { |
| 3156 | if (errors & DTD_STATUS_HALTED) { |
| 3157 | ERR("dTD error %08x QH=%d\n", errors, pipe); |
| 3158 | /* Clear the errors and Halt condition */ |
| 3159 | - tmp = le32_to_cpu(curr_qh->size_ioc_int_sts); |
| 3160 | + tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts); |
| 3161 | tmp &= ~errors; |
| 3162 | - curr_qh->size_ioc_int_sts = cpu_to_le32(tmp); |
| 3163 | + curr_qh->size_ioc_int_sts = cpu_to_hc32(tmp); |
| 3164 | status = -EPIPE; |
| 3165 | /* FIXME: continue with next queued TD? */ |
| 3166 | |
| 3167 | @@ -1464,7 +1591,7 @@ static int process_ep_req(struct fsl_udc |
| 3168 | ERR("Unknown error has occured (0x%x)!\n", |
| 3169 | errors); |
| 3170 | |
| 3171 | - } else if (le32_to_cpu(curr_td->size_ioc_sts) |
| 3172 | + } else if (hc32_to_cpu(curr_td->size_ioc_sts) |
| 3173 | & DTD_STATUS_ACTIVE) { |
| 3174 | VDBG("Request not complete"); |
| 3175 | status = REQ_UNCOMPLETE; |
| 3176 | @@ -1552,7 +1679,10 @@ static void dtd_complete_irq(struct fsl_ |
| 3177 | static void port_change_irq(struct fsl_udc *udc) |
| 3178 | { |
| 3179 | u32 speed; |
| 3180 | - |
| 3181 | +#ifdef CONFIG_COLDFIRE |
| 3182 | + if (udc->bus_reset) |
| 3183 | + udc->bus_reset = 0; |
| 3184 | +#endif |
| 3185 | /* Bus resetting is finished */ |
| 3186 | if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { |
| 3187 | /* Get the speed */ |
| 3188 | @@ -1660,6 +1790,10 @@ static void reset_irq(struct fsl_udc *ud |
| 3189 | |
| 3190 | if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) { |
| 3191 | VDBG("Bus reset"); |
| 3192 | +#ifdef CONFIG_COLDFIRE |
| 3193 | + /* Bus is reseting */ |
| 3194 | + udc->bus_reset = 1; |
| 3195 | +#endif |
| 3196 | /* Reset all the queues, include XD, dTD, EP queue |
| 3197 | * head and TR Queue */ |
| 3198 | reset_queues(udc); |
| 3199 | @@ -1793,19 +1927,49 @@ int usb_gadget_probe_driver(struct usb_g |
| 3200 | udc_controller->driver = NULL; |
| 3201 | goto out; |
| 3202 | } |
| 3203 | - |
| 3204 | +#ifdef CONFIG_COLDFIRE |
| 3205 | + if (udc_controller->transceiver) { |
| 3206 | + /* Suspend the controller until OTG enable it */ |
| 3207 | + udc_controller->stopped = 1; |
| 3208 | + printk(KERN_INFO "Suspend udc for OTG auto detect\n"); |
| 3209 | + |
| 3210 | + /* export udc suspend/resume call to OTG */ |
| 3211 | + udc_controller->gadget.dev.driver->suspend = fsl_udc_suspend; |
| 3212 | + udc_controller->gadget.dev.driver->resume = fsl_udc_resume; |
| 3213 | + |
| 3214 | + /* connect to bus through transceiver */ |
| 3215 | + if (udc_controller->transceiver) { |
| 3216 | + retval = otg_set_peripheral(udc_controller->transceiver, |
| 3217 | + &udc_controller->gadget); |
| 3218 | + if (retval < 0) { |
| 3219 | + ERR("can't bind to transceiver\n"); |
| 3220 | + driver->unbind(&udc_controller->gadget); |
| 3221 | + udc_controller->gadget.dev.driver = 0; |
| 3222 | + udc_controller->driver = 0; |
| 3223 | + return retval; |
| 3224 | + } |
| 3225 | + } |
| 3226 | + } else { |
| 3227 | + /* Enable DR IRQ reg and Set usbcmd reg Run bit */ |
| 3228 | + dr_controller_run(udc_controller); |
| 3229 | + udc_controller->usb_state = USB_STATE_ATTACHED; |
| 3230 | + udc_controller->ep0_state = WAIT_FOR_SETUP; |
| 3231 | + udc_controller->ep0_dir = 0; |
| 3232 | + } |
| 3233 | +#else |
| 3234 | /* Enable DR IRQ reg and Set usbcmd reg Run bit */ |
| 3235 | dr_controller_run(udc_controller); |
| 3236 | udc_controller->usb_state = USB_STATE_ATTACHED; |
| 3237 | udc_controller->ep0_state = WAIT_FOR_SETUP; |
| 3238 | udc_controller->ep0_dir = 0; |
| 3239 | +#endif |
| 3240 | printk(KERN_INFO "%s: bind to driver %s\n", |
| 3241 | udc_controller->gadget.name, driver->driver.name); |
| 3242 | |
| 3243 | out: |
| 3244 | if (retval) |
| 3245 | printk(KERN_WARNING "gadget driver register failed %d\n", |
| 3246 | - retval); |
| 3247 | + retval); |
| 3248 | return retval; |
| 3249 | } |
| 3250 | EXPORT_SYMBOL(usb_gadget_probe_driver); |
| 3251 | @@ -2239,7 +2403,7 @@ static int __init fsl_udc_probe(struct p |
| 3252 | int ret = -ENODEV; |
| 3253 | unsigned int i; |
| 3254 | u32 dccparams; |
| 3255 | - |
| 3256 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 3257 | if (strcmp(pdev->name, driver_name)) { |
| 3258 | VDBG("Wrong device"); |
| 3259 | return -ENODEV; |
| 3260 | @@ -2253,6 +2417,24 @@ static int __init fsl_udc_probe(struct p |
| 3261 | |
| 3262 | spin_lock_init(&udc_controller->lock); |
| 3263 | udc_controller->stopped = 1; |
| 3264 | +#ifdef CONFIG_COLDFIRE |
| 3265 | + udc_controller->pdata = pdata; |
| 3266 | +#endif |
| 3267 | +#ifdef CONFIG_USB_OTG |
| 3268 | + /* Memory and interrupt resources will be passed from OTG */ |
| 3269 | + udc_controller->transceiver = otg_get_transceiver(); |
| 3270 | + if (!udc_controller->transceiver) { |
| 3271 | + printk(KERN_ERR "Can't find OTG driver!\n"); |
| 3272 | + ret = -ENODEV; |
| 3273 | + goto err_kfree; |
| 3274 | + } |
| 3275 | + |
| 3276 | + res = otg_get_resources(); |
| 3277 | + if (!res) { |
| 3278 | + DBG("resource not registered!\n"); |
| 3279 | + return -ENODEV; |
| 3280 | + } |
| 3281 | +#else |
| 3282 | |
| 3283 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 3284 | if (!res) { |
| 3285 | @@ -2266,18 +2448,30 @@ static int __init fsl_udc_probe(struct p |
| 3286 | ret = -EBUSY; |
| 3287 | goto err_kfree; |
| 3288 | } |
| 3289 | - |
| 3290 | +#endif |
| 3291 | dr_regs = ioremap(res->start, resource_size(res)); |
| 3292 | if (!dr_regs) { |
| 3293 | ret = -ENOMEM; |
| 3294 | goto err_release_mem_region; |
| 3295 | } |
| 3296 | +#ifdef CONFIG_COLDFIRE |
| 3297 | + pdata->regs = (void *)dr_regs; |
| 3298 | + fsl_set_usb_accessors(pdata); |
| 3299 | + |
| 3300 | + /* |
| 3301 | + * do platform specific init: check the clock, grab/config pins, etc. |
| 3302 | + */ |
| 3303 | + if (pdata->init && pdata->init(pdev)) { |
| 3304 | + ret = -ENODEV; |
| 3305 | + goto err_iounmap_noclk; |
| 3306 | + } |
| 3307 | |
| 3308 | +#else |
| 3309 | #ifndef CONFIG_ARCH_MXC |
| 3310 | usb_sys_regs = (struct usb_sys_interface *) |
| 3311 | ((u32)dr_regs + USB_DR_SYS_OFFSET); |
| 3312 | #endif |
| 3313 | - |
| 3314 | +#endif |
| 3315 | /* Initialize USB clocks */ |
| 3316 | ret = fsl_udc_clk_init(pdev); |
| 3317 | if (ret < 0) |
| 3318 | @@ -2293,8 +2487,12 @@ static int __init fsl_udc_probe(struct p |
| 3319 | /* Get max device endpoints */ |
| 3320 | /* DEN is bidirectional ep number, max_ep doubles the number */ |
| 3321 | udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2; |
| 3322 | - |
| 3323 | +#ifdef CONFIG_USB_OTG |
| 3324 | + res++; |
| 3325 | + udc_controller->irq = res->start; |
| 3326 | +#else |
| 3327 | udc_controller->irq = platform_get_irq(pdev, 0); |
| 3328 | +#endif |
| 3329 | if (!udc_controller->irq) { |
| 3330 | ret = -ENODEV; |
| 3331 | goto err_iounmap; |
| 3332 | @@ -2314,11 +2512,17 @@ static int __init fsl_udc_probe(struct p |
| 3333 | ret = -ENOMEM; |
| 3334 | goto err_free_irq; |
| 3335 | } |
| 3336 | - |
| 3337 | +#ifdef CONFIG_COLDFIRE |
| 3338 | + if (!udc_controller->transceiver) { |
| 3339 | + /* initialize usb hw reg except for regs for EP, |
| 3340 | + * leave usbintr reg untouched */ |
| 3341 | + dr_controller_setup(udc_controller); |
| 3342 | + } |
| 3343 | +#else |
| 3344 | /* initialize usb hw reg except for regs for EP, |
| 3345 | * leave usbintr reg untouched */ |
| 3346 | dr_controller_setup(udc_controller); |
| 3347 | - |
| 3348 | +#endif |
| 3349 | fsl_udc_clk_finalize(pdev); |
| 3350 | |
| 3351 | /* Setup gadget structure */ |
| 3352 | @@ -2336,7 +2540,10 @@ static int __init fsl_udc_probe(struct p |
| 3353 | ret = device_register(&udc_controller->gadget.dev); |
| 3354 | if (ret < 0) |
| 3355 | goto err_free_irq; |
| 3356 | - |
| 3357 | +#ifdef CONFIG_COLDFIRE |
| 3358 | + if (udc_controller->transceiver) |
| 3359 | + udc_controller->gadget.is_otg = 1; |
| 3360 | +#endif |
| 3361 | /* setup QH and epctrl for ep0 */ |
| 3362 | ep0_setup(udc_controller); |
| 3363 | |
| 3364 | @@ -2392,7 +2599,9 @@ err_kfree: |
| 3365 | static int __exit fsl_udc_remove(struct platform_device *pdev) |
| 3366 | { |
| 3367 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 3368 | - |
| 3369 | +#ifdef CONFIG_COLDFIRE |
| 3370 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 3371 | +#endif |
| 3372 | DECLARE_COMPLETION(done); |
| 3373 | |
| 3374 | if (!udc_controller) |
| 3375 | @@ -2412,31 +2621,103 @@ static int __exit fsl_udc_remove(struct |
| 3376 | dma_pool_destroy(udc_controller->td_pool); |
| 3377 | free_irq(udc_controller->irq, udc_controller); |
| 3378 | iounmap(dr_regs); |
| 3379 | +#ifndef CONFIG_USB_OTG |
| 3380 | release_mem_region(res->start, res->end - res->start + 1); |
| 3381 | - |
| 3382 | +#endif |
| 3383 | device_unregister(&udc_controller->gadget.dev); |
| 3384 | /* free udc --wait for the release() finished */ |
| 3385 | wait_for_completion(&done); |
| 3386 | +#ifdef CONFIG_COLDFIRE |
| 3387 | + /* |
| 3388 | + * do platform specific un-initialization: |
| 3389 | + * release iomux pins, etc. |
| 3390 | + */ |
| 3391 | + if (pdata->exit) |
| 3392 | + pdata->exit(pdev); |
| 3393 | + |
| 3394 | +#endif |
| 3395 | + return 0; |
| 3396 | +} |
| 3397 | +#ifdef CONFIG_COLDFIRE |
| 3398 | + |
| 3399 | +static int udc_suspend(struct fsl_udc *udc) |
| 3400 | +{ |
| 3401 | + u32 mode, usbcmd; |
| 3402 | + |
| 3403 | + mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK; |
| 3404 | + usbcmd = fsl_readl(&dr_regs->usbcmd); |
| 3405 | + |
| 3406 | + pr_debug("%s(): mode 0x%x stopped %d\n", __func__, mode, udc->stopped); |
| 3407 | + |
| 3408 | + /* |
| 3409 | + * If the controller is already stopped, then this must be a |
| 3410 | + * PM suspend. Remember this fact, so that we will leave the |
| 3411 | + * controller stopped at PM resume time. |
| 3412 | + */ |
| 3413 | + if (udc->stopped) { |
| 3414 | + pr_debug("gadget already stopped, leaving early\n"); |
| 3415 | + udc->already_stopped = 1; |
| 3416 | + return 0; |
| 3417 | + } |
| 3418 | |
| 3419 | + if (mode != USB_MODE_CTRL_MODE_DEVICE) { |
| 3420 | + pr_debug("gadget not in device mode, leaving early\n"); |
| 3421 | + return 0; |
| 3422 | + } |
| 3423 | + |
| 3424 | + printk(KERN_INFO "USB Gadget suspended\n"); |
| 3425 | + |
| 3426 | + /* stop the controller */ |
| 3427 | + usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP; |
| 3428 | + fsl_writel(usbcmd, &dr_regs->usbcmd); |
| 3429 | + |
| 3430 | + udc->stopped = 1; |
| 3431 | return 0; |
| 3432 | } |
| 3433 | |
| 3434 | +#endif |
| 3435 | /*----------------------------------------------------------------- |
| 3436 | * Modify Power management attributes |
| 3437 | * Used by OTG statemachine to disable gadget temporarily |
| 3438 | -----------------------------------------------------------------*/ |
| 3439 | +#ifdef CONFIG_COLDFIRE |
| 3440 | +static int fsl_udc_suspend(struct device *dev, pm_message_t state) |
| 3441 | +#else |
| 3442 | static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) |
| 3443 | +#endif |
| 3444 | { |
| 3445 | +#ifdef CONFIG_COLDFIRE |
| 3446 | + return udc_suspend(udc_controller); |
| 3447 | +#else |
| 3448 | dr_controller_stop(udc_controller); |
| 3449 | return 0; |
| 3450 | +#endif |
| 3451 | } |
| 3452 | |
| 3453 | /*----------------------------------------------------------------- |
| 3454 | * Invoked on USB resume. May be called in_interrupt. |
| 3455 | * Here we start the DR controller and enable the irq |
| 3456 | *-----------------------------------------------------------------*/ |
| 3457 | +#ifdef CONFIG_COLDFIRE |
| 3458 | +static int fsl_udc_resume(struct device *dev) |
| 3459 | +#else |
| 3460 | static int fsl_udc_resume(struct platform_device *pdev) |
| 3461 | +#endif |
| 3462 | { |
| 3463 | +#ifdef CONFIG_COLDFIRE |
| 3464 | + pr_debug("%s(): stopped %d already_stopped %d\n", __func__, |
| 3465 | + udc_controller->stopped, udc_controller->already_stopped); |
| 3466 | + |
| 3467 | + /* |
| 3468 | + * If the controller was stopped at suspend time, then |
| 3469 | + * don't resume it now. |
| 3470 | + */ |
| 3471 | + if (udc_controller->already_stopped) { |
| 3472 | + udc_controller->already_stopped = 0; |
| 3473 | + pr_debug("gadget was already stopped, leaving early\n"); |
| 3474 | + return 0; |
| 3475 | + } |
| 3476 | +#endif |
| 3477 | /* Enable DR irq reg and set controller Run */ |
| 3478 | if (udc_controller->stopped) { |
| 3479 | dr_controller_setup(udc_controller); |
| 3480 | @@ -2445,6 +2726,9 @@ static int fsl_udc_resume(struct platfor |
| 3481 | udc_controller->usb_state = USB_STATE_ATTACHED; |
| 3482 | udc_controller->ep0_state = WAIT_FOR_SETUP; |
| 3483 | udc_controller->ep0_dir = 0; |
| 3484 | + |
| 3485 | + printk(KERN_INFO "USB Gadget resumed\n"); |
| 3486 | + |
| 3487 | return 0; |
| 3488 | } |
| 3489 | |
| 3490 | @@ -2455,11 +2739,15 @@ static int fsl_udc_resume(struct platfor |
| 3491 | static struct platform_driver udc_driver = { |
| 3492 | .remove = __exit_p(fsl_udc_remove), |
| 3493 | /* these suspend and resume are not usb suspend and resume */ |
| 3494 | +#ifndef CONFIG_COLDFIRE |
| 3495 | .suspend = fsl_udc_suspend, |
| 3496 | .resume = fsl_udc_resume, |
| 3497 | +#endif |
| 3498 | .driver = { |
| 3499 | .name = (char *)driver_name, |
| 3500 | .owner = THIS_MODULE, |
| 3501 | + .suspend = fsl_udc_suspend, |
| 3502 | + .resume = fsl_udc_resume, |
| 3503 | }, |
| 3504 | }; |
| 3505 | |
| 3506 | --- a/drivers/usb/gadget/fsl_usb2_udc.h |
| 3507 | +++ b/drivers/usb/gadget/fsl_usb2_udc.h |
| 3508 | @@ -461,6 +461,7 @@ struct fsl_ep { |
| 3509 | struct fsl_udc { |
| 3510 | struct usb_gadget gadget; |
| 3511 | struct usb_gadget_driver *driver; |
| 3512 | + struct fsl_usb2_platform_data *pdata; |
| 3513 | struct completion *done; /* to make sure release() is done */ |
| 3514 | struct fsl_ep *eps; |
| 3515 | unsigned int max_ep; |
| 3516 | @@ -473,6 +474,7 @@ struct fsl_udc { |
| 3517 | unsigned vbus_active:1; |
| 3518 | unsigned stopped:1; |
| 3519 | unsigned remote_wakeup:1; |
| 3520 | + unsigned already_stopped:1; |
| 3521 | |
| 3522 | struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */ |
| 3523 | struct fsl_req *status_req; /* ep0 status request */ |
| 3524 | @@ -482,6 +484,7 @@ struct fsl_udc { |
| 3525 | size_t ep_qh_size; /* size after alignment adjustment*/ |
| 3526 | dma_addr_t ep_qh_dma; /* dma address of QH */ |
| 3527 | |
| 3528 | + u32 bus_reset; /* Device is bus reseting */ |
| 3529 | u32 max_pipes; /* Device max pipes */ |
| 3530 | u32 resume_state; /* USB state to resume */ |
| 3531 | u32 usb_state; /* USB current state */ |
| 3532 | @@ -581,4 +584,17 @@ static inline void fsl_udc_clk_release(v |
| 3533 | } |
| 3534 | #endif |
| 3535 | |
| 3536 | +#ifdef CONFIG_COLDFIRE |
| 3537 | +#include <asm/mcfsim.h> |
| 3538 | +#include <asm/fsl_usb_io.h> |
| 3539 | +#include <asm/fsl_usb_gadget.h> |
| 3540 | +#include <asm/cf_cacheflush.h> |
| 3541 | + |
| 3542 | +extern struct resource *otg_get_resources(void); |
| 3543 | +#ifdef CONFIG_USB_M5441X_MAX3353_FSLS |
| 3544 | +extern int max3353_read_id_pin(void); |
| 3545 | +#endif |
| 3546 | + |
| 3547 | +#endif |
| 3548 | + |
| 3549 | #endif |
| 3550 | --- a/drivers/usb/gadget/serial.c |
| 3551 | +++ b/drivers/usb/gadget/serial.c |
| 3552 | @@ -4,6 +4,7 @@ |
| 3553 | * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) |
| 3554 | * Copyright (C) 2008 by David Brownell |
| 3555 | * Copyright (C) 2008 by Nokia Corporation |
| 3556 | + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 3557 | * |
| 3558 | * This software is distributed under the terms of the GNU General |
| 3559 | * Public License ("GPL") as published by the Free Software Foundation, |
| 3560 | @@ -134,7 +135,44 @@ MODULE_PARM_DESC(use_obex, "Use CDC OBEX |
| 3561 | static unsigned n_ports = 1; |
| 3562 | module_param(n_ports, uint, 0); |
| 3563 | MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); |
| 3564 | - |
| 3565 | +/*-------------------------------------------------------------------------*/ |
| 3566 | +#if 0 |
| 3567 | +static void gs_setup_complete_set_line_coding(struct usb_ep *ep, |
| 3568 | + struct usb_request *req) |
| 3569 | +{ |
| 3570 | + struct gs_dev *dev = ep->driver_data; |
| 3571 | + struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ |
| 3572 | + |
| 3573 | + switch (req->status) { |
| 3574 | + case 0: |
| 3575 | + /* normal completion */ |
| 3576 | + if (req->actual != sizeof(port->port_line_coding)) |
| 3577 | + usb_ep_set_halt(ep); |
| 3578 | + else if (port) { |
| 3579 | + struct usb_cdc_line_coding *value = req->buf; |
| 3580 | + |
| 3581 | + /* REVISIT: we currently just remember this data. |
| 3582 | + * If we change that, (a) validate it first, then |
| 3583 | + * (b) update whatever hardware needs updating. |
| 3584 | + */ |
| 3585 | + spin_lock(&port->port_lock); |
| 3586 | + port->port_line_coding = *value; |
| 3587 | + spin_unlock(&port->port_lock); |
| 3588 | + } |
| 3589 | + break; |
| 3590 | + |
| 3591 | + case -ESHUTDOWN: |
| 3592 | + /* disconnect */ |
| 3593 | + gs_free_req(ep, req); |
| 3594 | + break; |
| 3595 | + |
| 3596 | + default: |
| 3597 | + /* unexpected */ |
| 3598 | + break; |
| 3599 | + } |
| 3600 | + return; |
| 3601 | +} |
| 3602 | +#endif |
| 3603 | /*-------------------------------------------------------------------------*/ |
| 3604 | |
| 3605 | static int __init serial_bind_config(struct usb_configuration *c) |
| 3606 | --- a/drivers/usb/host/Kconfig |
| 3607 | +++ b/drivers/usb/host/Kconfig |
| 3608 | @@ -95,13 +95,14 @@ config USB_EHCI_BIG_ENDIAN_MMIO |
| 3609 | bool |
| 3610 | depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \ |
| 3611 | ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ |
| 3612 | - PPC_MPC512x || CPU_CAVIUM_OCTEON) |
| 3613 | + PPC_MPC512x || CPU_CAVIUM_OCTEON || \ |
| 3614 | + COLDFIRE) |
| 3615 | default y |
| 3616 | |
| 3617 | config USB_EHCI_BIG_ENDIAN_DESC |
| 3618 | bool |
| 3619 | depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ |
| 3620 | - PPC_MPC512x) |
| 3621 | + PPC_MPC512x || COLDFIRE) |
| 3622 | default y |
| 3623 | |
| 3624 | config XPS_USB_HCD_XILINX |
| 3625 | @@ -120,12 +121,77 @@ config USB_FSL_MPH_DR_OF |
| 3626 | |
| 3627 | config USB_EHCI_FSL |
| 3628 | bool "Support for Freescale on-chip EHCI USB controller" |
| 3629 | - depends on USB_EHCI_HCD && FSL_SOC |
| 3630 | + depends on USB_EHCI_HCD && (FSL_SOC || COLDFIRE) |
| 3631 | select USB_EHCI_ROOT_HUB_TT |
| 3632 | select USB_FSL_MPH_DR_OF if OF |
| 3633 | ---help--- |
| 3634 | Variation of ARC USB block used in some Freescale chips. |
| 3635 | |
| 3636 | +config USB_M5441X_PLLCLK |
| 3637 | + bool "ColdFire USB module use PLL clock source" |
| 3638 | + depends on M5441X |
| 3639 | + ---help--- |
| 3640 | + Select USB clock source from PLL instead external USBCLKIN, |
| 3641 | + to generate the exact USB module 60MHZ clock, the system clock |
| 3642 | + must be shrink to match the divide requirement which is down |
| 3643 | + in u-boot. |
| 3644 | + |
| 3645 | +config USB_M5441X_H1 |
| 3646 | + bool "ColdFire EHCI USB Host module support" |
| 3647 | + depends on USB_EHCI_HCD && M5441X |
| 3648 | + ---help--- |
| 3649 | + Some ColdFire platform have two USB controllers, one is HOST module, |
| 3650 | + the other is OTG module, this config select the HOST module support. |
| 3651 | + |
| 3652 | +choice |
| 3653 | + prompt "Selcet ColdFire HOST module transceiver" |
| 3654 | + depends on USB_M5441X_H1 |
| 3655 | + default USB_M5441X_H1_FSLS |
| 3656 | + |
| 3657 | +config USB_M5441X_H1_FSLS |
| 3658 | + bool "on-chip (FS/LS only)" |
| 3659 | + depends on M5441X |
| 3660 | + ---help--- |
| 3661 | + Enable support for the on-chip FS/LS transceiver. |
| 3662 | +endchoice |
| 3663 | + |
| 3664 | +choice |
| 3665 | + prompt "Select ColdiFire OTG module transceiver" |
| 3666 | + depends on M5445X || M5441X |
| 3667 | + default USB_M5445X_ULPI if M5445X |
| 3668 | + default USB_M5441X_ULPI if M5441X |
| 3669 | + |
| 3670 | +config USB_M5445X_ULPI |
| 3671 | + bool "External ULPI" |
| 3672 | + depends on M5445X |
| 3673 | + ---help--- |
| 3674 | + Enable support for the external HS ULPI transceiver. |
| 3675 | + |
| 3676 | +config USB_M5445X_FSLS |
| 3677 | + bool "On-chip (FL/LS only)" |
| 3678 | + depends on M54455EVB |
| 3679 | + ---help--- |
| 3680 | + Enable support for the on-chip FL/LS transceiver. |
| 3681 | + |
| 3682 | +config USB_M5441X_ULPI |
| 3683 | + bool "External ULPI" |
| 3684 | + depends on M5441X |
| 3685 | + ---help--- |
| 3686 | + Enable support for the external HS ULPI transceiver. |
| 3687 | + |
| 3688 | +config USB_M5441X_FSLS |
| 3689 | + bool "On-chip (FL/LS only)" |
| 3690 | + depends on M54418EVB |
| 3691 | + ---help--- |
| 3692 | + Enable support for the on-chip FL/LS transceiver. |
| 3693 | + |
| 3694 | +config USB_M5441X_MAX3353_FSLS |
| 3695 | + bool "MAX3353 chip charge pump to on-chip (FS/LS only)" |
| 3696 | + depends on M54418EVB |
| 3697 | + ---help--- |
| 3698 | + Max3353 provides charge pump for SER1 board on m54418 platform. |
| 3699 | +endchoice |
| 3700 | + |
| 3701 | config USB_EHCI_MXC |
| 3702 | bool "Support for Freescale on-chip EHCI USB controller" |
| 3703 | depends on USB_EHCI_HCD && ARCH_MXC |
| 3704 | --- a/drivers/usb/host/ehci-fsl.c |
| 3705 | +++ b/drivers/usb/host/ehci-fsl.c |
| 3706 | @@ -22,16 +22,21 @@ |
| 3707 | * Jerry Huang <Chang-Ming.Huang@freescale.com> and |
| 3708 | * Anton Vorontsov <avorontsov@ru.mvista.com>. |
| 3709 | */ |
| 3710 | - |
| 3711 | #include <linux/kernel.h> |
| 3712 | #include <linux/types.h> |
| 3713 | #include <linux/delay.h> |
| 3714 | #include <linux/pm.h> |
| 3715 | #include <linux/platform_device.h> |
| 3716 | #include <linux/fsl_devices.h> |
| 3717 | - |
| 3718 | +#include <linux/usb/otg.h> |
| 3719 | #include "ehci-fsl.h" |
| 3720 | |
| 3721 | +#ifdef DEBUG |
| 3722 | +#define DBG(X...) printk(X) |
| 3723 | +#else |
| 3724 | +#define DBG(X...) |
| 3725 | +#endif |
| 3726 | + |
| 3727 | /* configure so an HC device and id are always provided */ |
| 3728 | /* always called with process context; sleeping is OK */ |
| 3729 | |
| 3730 | @@ -75,7 +80,27 @@ static int usb_hcd_fsl_probe(const struc |
| 3731 | dev_name(&pdev->dev)); |
| 3732 | return -ENODEV; |
| 3733 | } |
| 3734 | - |
| 3735 | + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); |
| 3736 | + if (!hcd) { |
| 3737 | + retval = -ENOMEM; |
| 3738 | + goto err1; |
| 3739 | + } |
| 3740 | +#ifdef CONFIG_USB_OTG |
| 3741 | + if (pdata->operating_mode == FSL_USB2_DR_OTG) { |
| 3742 | + res = otg_get_resources(); |
| 3743 | + if (!res) { |
| 3744 | + dev_err(&pdev->dev, |
| 3745 | + "Found HC with no IRQ. Check %s setup!\n", |
| 3746 | + dev_name(&pdev->dev)); |
| 3747 | + return -ENODEV; |
| 3748 | + goto err2; |
| 3749 | + } |
| 3750 | + irq = res[1].start; |
| 3751 | + hcd->rsrc_start = res[0].start; |
| 3752 | + hcd->rsrc_len = res[0].end - res[0].start + 1; |
| 3753 | + } else |
| 3754 | +#endif |
| 3755 | + { |
| 3756 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 3757 | if (!res) { |
| 3758 | dev_err(&pdev->dev, |
| 3759 | @@ -85,12 +110,6 @@ static int usb_hcd_fsl_probe(const struc |
| 3760 | } |
| 3761 | irq = res->start; |
| 3762 | |
| 3763 | - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); |
| 3764 | - if (!hcd) { |
| 3765 | - retval = -ENOMEM; |
| 3766 | - goto err1; |
| 3767 | - } |
| 3768 | - |
| 3769 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 3770 | if (!res) { |
| 3771 | dev_err(&pdev->dev, |
| 3772 | @@ -101,12 +120,15 @@ static int usb_hcd_fsl_probe(const struc |
| 3773 | } |
| 3774 | hcd->rsrc_start = res->start; |
| 3775 | hcd->rsrc_len = res->end - res->start + 1; |
| 3776 | +#ifndef CONFIG_USB_OTG |
| 3777 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, |
| 3778 | driver->description)) { |
| 3779 | dev_dbg(&pdev->dev, "controller already in use\n"); |
| 3780 | retval = -EBUSY; |
| 3781 | goto err2; |
| 3782 | } |
| 3783 | +#endif |
| 3784 | + } |
| 3785 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
| 3786 | |
| 3787 | if (hcd->regs == NULL) { |
| 3788 | @@ -124,22 +146,56 @@ static int usb_hcd_fsl_probe(const struc |
| 3789 | retval = -ENODEV; |
| 3790 | goto err3; |
| 3791 | } |
| 3792 | - |
| 3793 | +#ifndef CONFIG_COLDFIRE |
| 3794 | /* Enable USB controller, 83xx or 8536 */ |
| 3795 | if (pdata->have_sysif_regs) |
| 3796 | setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); |
| 3797 | - |
| 3798 | +#endif |
| 3799 | /* Don't need to set host mode here. It will be done by tdi_reset() */ |
| 3800 | - |
| 3801 | +#ifdef CONFIG_COLDFIRE |
| 3802 | + fsl_platform_set_host_mode(hcd); |
| 3803 | + hcd->power_budget = pdata->power_budget; |
| 3804 | +#endif |
| 3805 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); |
| 3806 | if (retval != 0) |
| 3807 | goto err4; |
| 3808 | +#ifdef CONFIG_COLDFIRE |
| 3809 | + fsl_platform_set_vbus_power(pdata, 1); |
| 3810 | +#endif |
| 3811 | +#ifdef CONFIG_USB_OTG |
| 3812 | + if (pdata->operating_mode == FSL_USB2_DR_OTG) { |
| 3813 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 3814 | + |
| 3815 | + DBG("pdev=0x%p hcd=0x%p ehci=0x%p\n", pdev, hcd, ehci); |
| 3816 | + |
| 3817 | + ehci->transceiver = otg_get_transceiver(); |
| 3818 | + DBG("ehci->transceiver=0x%p\n", ehci->transceiver); |
| 3819 | + |
| 3820 | + if (ehci->transceiver) { |
| 3821 | + retval = otg_set_host(ehci->transceiver, |
| 3822 | + &ehci_to_hcd(ehci)->self); |
| 3823 | + if (retval) { |
| 3824 | + printk(KERN_INFO "otg transceiver set host failed\n"); |
| 3825 | + if (ehci->transceiver) |
| 3826 | + put_device(ehci->transceiver->dev); |
| 3827 | + goto err4; |
| 3828 | + } |
| 3829 | + } else { |
| 3830 | + printk(KERN_ERR "can't find transceiver\n"); |
| 3831 | + retval = -ENODEV; |
| 3832 | + goto err4; |
| 3833 | + } |
| 3834 | + } |
| 3835 | +#endif |
| 3836 | + |
| 3837 | return retval; |
| 3838 | |
| 3839 | err4: |
| 3840 | iounmap(hcd->regs); |
| 3841 | err3: |
| 3842 | +#ifndef CONFIG_USB_OTG |
| 3843 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 3844 | +#endif |
| 3845 | err2: |
| 3846 | usb_put_hcd(hcd); |
| 3847 | err1: |
| 3848 | @@ -164,9 +220,24 @@ static void usb_hcd_fsl_remove(struct us |
| 3849 | struct platform_device *pdev) |
| 3850 | { |
| 3851 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 3852 | +#ifdef CONFIG_COLDFIRE |
| 3853 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 3854 | |
| 3855 | + /* DDD shouldn't we turn off the power here? */ |
| 3856 | + fsl_platform_set_vbus_power(pdata, 0); |
| 3857 | + |
| 3858 | + if (ehci->transceiver) { |
| 3859 | + (void)otg_set_host(ehci->transceiver, 0); |
| 3860 | + put_device(ehci->transceiver->dev); |
| 3861 | + } else { |
| 3862 | + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 3863 | + } |
| 3864 | + |
| 3865 | + |
| 3866 | +#endif |
| 3867 | usb_remove_hcd(hcd); |
| 3868 | |
| 3869 | + usb_put_hcd(hcd); |
| 3870 | /* |
| 3871 | * do platform specific un-initialization: |
| 3872 | * release iomux pins, disable clock, etc. |
| 3873 | @@ -174,8 +245,6 @@ static void usb_hcd_fsl_remove(struct us |
| 3874 | if (pdata->exit) |
| 3875 | pdata->exit(pdev); |
| 3876 | iounmap(hcd->regs); |
| 3877 | - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 3878 | - usb_put_hcd(hcd); |
| 3879 | } |
| 3880 | |
| 3881 | static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, |
| 3882 | @@ -238,7 +307,7 @@ static void ehci_fsl_usb_setup(struct eh |
| 3883 | if ((pdata->operating_mode == FSL_USB2_DR_HOST) || |
| 3884 | (pdata->operating_mode == FSL_USB2_DR_OTG)) |
| 3885 | ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); |
| 3886 | - |
| 3887 | +#ifndef CONFIG_COLDFIRE |
| 3888 | if (pdata->operating_mode == FSL_USB2_MPH_HOST) { |
| 3889 | unsigned int chip, rev, svr; |
| 3890 | |
| 3891 | @@ -255,7 +324,7 @@ static void ehci_fsl_usb_setup(struct eh |
| 3892 | if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) |
| 3893 | ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); |
| 3894 | } |
| 3895 | - |
| 3896 | +#endif |
| 3897 | if (pdata->have_sysif_regs) { |
| 3898 | #ifdef CONFIG_PPC_85xx |
| 3899 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); |
| 3900 | @@ -271,7 +340,11 @@ static void ehci_fsl_usb_setup(struct eh |
| 3901 | /* called after powerup, by probe or system-pm "wakeup" */ |
| 3902 | static int ehci_fsl_reinit(struct ehci_hcd *ehci) |
| 3903 | { |
| 3904 | +#ifdef CONFIG_COLDFIRE |
| 3905 | + fsl_platform_usb_setup(ehci); |
| 3906 | +#else |
| 3907 | ehci_fsl_usb_setup(ehci); |
| 3908 | +#endif |
| 3909 | ehci_port_power(ehci, 0); |
| 3910 | |
| 3911 | return 0; |
| 3912 | @@ -334,7 +407,6 @@ static struct ehci_fsl *hcd_to_ehci_fsl( |
| 3913 | |
| 3914 | return container_of(ehci, struct ehci_fsl, ehci); |
| 3915 | } |
| 3916 | - |
| 3917 | static int ehci_fsl_drv_suspend(struct device *dev) |
| 3918 | { |
| 3919 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 3920 | @@ -371,7 +443,6 @@ static int ehci_fsl_drv_resume(struct de |
| 3921 | |
| 3922 | return 0; |
| 3923 | } |
| 3924 | - |
| 3925 | static int ehci_fsl_drv_restore(struct device *dev) |
| 3926 | { |
| 3927 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 3928 | @@ -387,6 +458,144 @@ static struct dev_pm_ops ehci_fsl_pm_ops |
| 3929 | }; |
| 3930 | |
| 3931 | #define EHCI_FSL_PM_OPS (&ehci_fsl_pm_ops) |
| 3932 | + |
| 3933 | +/* suspend/resume, section 4.3 */ |
| 3934 | + |
| 3935 | +/* These routines rely on the bus (pci, platform, etc) |
| 3936 | + * to handle powerdown and wakeup, and currently also on |
| 3937 | + * transceivers that don't need any software attention to set up |
| 3938 | + * the right sort of wakeup. |
| 3939 | + * |
| 3940 | + * They're also used for turning on/off the port when doing OTG. |
| 3941 | + */ |
| 3942 | +static int ehci_fsl_suspend(struct device *dev, |
| 3943 | + pm_message_t message) |
| 3944 | +{ |
| 3945 | + struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 3946 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 3947 | + u32 tmp; |
| 3948 | + struct fsl_usb2_platform_data *pdata = dev->platform_data; |
| 3949 | + |
| 3950 | +#ifdef DEBUG |
| 3951 | + u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); |
| 3952 | + mode &= USBMODE_CM_MASK; |
| 3953 | + tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ |
| 3954 | + |
| 3955 | + DBG(KERN_DEBUG "%s('%s'): suspend=%d already_suspended=%d " |
| 3956 | + "mode=%d usbcmd %08x\n", __func__, pdata->name, |
| 3957 | + pdata->suspended, pdata->already_suspended, mode, tmp); |
| 3958 | +#endif |
| 3959 | + /* |
| 3960 | + * If the controller is already suspended, then this must be a |
| 3961 | + * PM suspend. Remember this fact, so that we will leave the |
| 3962 | + * controller suspended at PM resume time. |
| 3963 | + */ |
| 3964 | + if (pdata->suspended) { |
| 3965 | + pr_debug("%s: already suspended, leaving early\n", __func__); |
| 3966 | + pdata->already_suspended = 1; |
| 3967 | + return 0; |
| 3968 | + } |
| 3969 | + |
| 3970 | + pr_debug("%s: suspending...\n", __func__); |
| 3971 | + |
| 3972 | + DBG(KERN_INFO "USB Host suspended\n"); |
| 3973 | + |
| 3974 | + hcd->state = HC_STATE_SUSPENDED; |
| 3975 | + dev->power.power_state = PMSG_SUSPEND; |
| 3976 | + |
| 3977 | + /* ignore non-host interrupts */ |
| 3978 | + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
| 3979 | + |
| 3980 | + /* stop the controller */ |
| 3981 | + tmp = ehci_readl(ehci, &ehci->regs->command); |
| 3982 | + tmp &= ~CMD_RUN; |
| 3983 | + ehci_writel(ehci, tmp, &ehci->regs->command); |
| 3984 | + |
| 3985 | + /* save EHCI registers */ |
| 3986 | + pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); |
| 3987 | + pdata->pm_command &= ~CMD_RUN; |
| 3988 | + pdata->pm_status = ehci_readl(ehci, &ehci->regs->status); |
| 3989 | + pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); |
| 3990 | + pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); |
| 3991 | + pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment); |
| 3992 | + pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); |
| 3993 | + pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); |
| 3994 | + pdata->pm_configured_flag = |
| 3995 | + ehci_readl(ehci, &ehci->regs->configured_flag); |
| 3996 | + pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); |
| 3997 | + |
| 3998 | + /* clear the W1C bits */ |
| 3999 | + pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); |
| 4000 | + |
| 4001 | + pdata->suspended = 1; |
| 4002 | +#if 0 |
| 4003 | + /* clear PP to cut power to the port */ |
| 4004 | + tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); |
| 4005 | + tmp &= ~PORT_POWER; |
| 4006 | + ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); |
| 4007 | +#endif |
| 4008 | + return 0; |
| 4009 | +} |
| 4010 | + |
| 4011 | +static int ehci_fsl_resume(struct device *dev) |
| 4012 | +{ |
| 4013 | + struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 4014 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 4015 | + u32 tmp; |
| 4016 | + struct fsl_usb2_platform_data *pdata = dev->platform_data; |
| 4017 | + |
| 4018 | + pr_debug("%s('%s'): suspend=%d already_suspended=%d\n", __func__, |
| 4019 | + pdata->name, pdata->suspended, pdata->already_suspended); |
| 4020 | + |
| 4021 | + /* |
| 4022 | + * If the controller was already suspended at suspend time, |
| 4023 | + * then don't resume it now. |
| 4024 | + */ |
| 4025 | + if (pdata->already_suspended) { |
| 4026 | + pr_debug("already suspended, leaving early\n"); |
| 4027 | + pdata->already_suspended = 0; |
| 4028 | + return 0; |
| 4029 | + } |
| 4030 | + |
| 4031 | + if (!pdata->suspended) { |
| 4032 | + pr_debug("not suspended, leaving early\n"); |
| 4033 | + return 0; |
| 4034 | + } |
| 4035 | + |
| 4036 | + DBG(KERN_INFO "USB Host resumed\n"); |
| 4037 | + |
| 4038 | + pdata->suspended = 0; |
| 4039 | + |
| 4040 | + pr_debug("%s resuming...\n", __func__); |
| 4041 | + |
| 4042 | + /* set host mode */ |
| 4043 | + fsl_platform_set_host_mode(hcd); |
| 4044 | + |
| 4045 | + |
| 4046 | + /* restore EHCI registers */ |
| 4047 | + ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); |
| 4048 | + ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); |
| 4049 | + ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); |
| 4050 | + ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); |
| 4051 | + ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); |
| 4052 | + ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); |
| 4053 | + ehci_writel(ehci, pdata->pm_configured_flag, |
| 4054 | + &ehci->regs->configured_flag); |
| 4055 | + ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); |
| 4056 | + |
| 4057 | + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
| 4058 | + hcd->state = HC_STATE_RUNNING; |
| 4059 | + dev->power.power_state = PMSG_ON; |
| 4060 | + |
| 4061 | + tmp = ehci_readl(ehci, &ehci->regs->command); |
| 4062 | + tmp |= CMD_RUN; |
| 4063 | + ehci_writel(ehci, tmp, &ehci->regs->command); |
| 4064 | + |
| 4065 | + usb_hcd_resume_root_hub(hcd); |
| 4066 | + |
| 4067 | + return 0; |
| 4068 | +} |
| 4069 | + |
| 4070 | #else |
| 4071 | #define EHCI_FSL_PM_OPS NULL |
| 4072 | #endif /* CONFIG_PM */ |
| 4073 | @@ -431,7 +640,11 @@ static const struct hc_driver ehci_fsl_h |
| 4074 | .bus_suspend = ehci_bus_suspend, |
| 4075 | .bus_resume = ehci_bus_resume, |
| 4076 | .relinquish_port = ehci_relinquish_port, |
| 4077 | +#ifndef CONFIG_COLDFIRE |
| 4078 | .port_handed_over = ehci_port_handed_over, |
| 4079 | +#else |
| 4080 | + .start_port_reset = ehci_start_port_reset, |
| 4081 | +#endif |
| 4082 | |
| 4083 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, |
| 4084 | }; |
| 4085 | @@ -460,8 +673,16 @@ static struct platform_driver ehci_fsl_d |
| 4086 | .probe = ehci_fsl_drv_probe, |
| 4087 | .remove = ehci_fsl_drv_remove, |
| 4088 | .shutdown = usb_hcd_platform_shutdown, |
| 4089 | +#ifdef CONFIG_PM |
| 4090 | +#ifndef CONFIG_COLDFIRE |
| 4091 | + .suspend = ehci_fsl_suspend, |
| 4092 | + .resume = ehci_fsl_resume, |
| 4093 | +#endif |
| 4094 | +#endif |
| 4095 | .driver = { |
| 4096 | .name = "fsl-ehci", |
| 4097 | .pm = EHCI_FSL_PM_OPS, |
| 4098 | + .suspend = ehci_fsl_suspend, |
| 4099 | + .resume = ehci_fsl_resume, |
| 4100 | }, |
| 4101 | }; |
| 4102 | --- a/drivers/usb/host/ehci-fsl.h |
| 4103 | +++ b/drivers/usb/host/ehci-fsl.h |
| 4104 | @@ -42,4 +42,11 @@ |
| 4105 | #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */ |
| 4106 | #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ |
| 4107 | #define SNOOP_SIZE_2GB 0x1e |
| 4108 | + |
| 4109 | +#ifdef CONFIG_COLDFIRE |
| 4110 | +#define FSL_SOC_USB_USBMODE 0x1a8 |
| 4111 | + |
| 4112 | +#include <asm/fsl_usb_platform.h> |
| 4113 | +#include <asm/fsl_usb_io.h> |
| 4114 | +#endif |
| 4115 | #endif /* _EHCI_FSL_H */ |
| 4116 | --- a/drivers/usb/host/ehci-hub.c |
| 4117 | +++ b/drivers/usb/host/ehci-hub.c |
| 4118 | @@ -1,5 +1,6 @@ |
| 4119 | /* |
| 4120 | * Copyright (C) 2001-2004 by David Brownell |
| 4121 | + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 4122 | * |
| 4123 | * This program is free software; you can redistribute it and/or modify it |
| 4124 | * under the terms of the GNU General Public License as published by the |
| 4125 | @@ -41,6 +42,39 @@ static int ehci_hub_control( |
| 4126 | u16 wLength |
| 4127 | ); |
| 4128 | |
| 4129 | +#ifdef CONFIG_COLDFIRE |
| 4130 | + |
| 4131 | +#ifdef CONFIG_USB_OTG |
| 4132 | +static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) |
| 4133 | +{ |
| 4134 | + struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 4135 | + u32 status; |
| 4136 | + |
| 4137 | + if (!port) |
| 4138 | + return -EINVAL; |
| 4139 | + port--; |
| 4140 | + |
| 4141 | + /* start port reset before HNP protocol time out */ |
| 4142 | + status = readl(&ehci->regs->port_status[port]); |
| 4143 | + if (!(status & PORT_CONNECT)) |
| 4144 | + return -ENODEV; |
| 4145 | + |
| 4146 | + /* khubd will finish the reset later */ |
| 4147 | + if (ehci_is_TDI(ehci)) |
| 4148 | + writel(PORT_RESET | (status & ~(PORT_CSC | PORT_PEC |
| 4149 | + | PORT_OCC)), &ehci->regs->port_status[port]); |
| 4150 | + else |
| 4151 | + writel(PORT_RESET, &ehci->regs->port_status[port]); |
| 4152 | + |
| 4153 | + return 0; |
| 4154 | +} |
| 4155 | +#else |
| 4156 | +static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) |
| 4157 | +{ |
| 4158 | + return 0; |
| 4159 | +} |
| 4160 | +#endif /* CONFIG_USB_OTG */ |
| 4161 | +#endif |
| 4162 | /* After a power loss, ports that were owned by the companion must be |
| 4163 | * reset so that the companion can still own them. |
| 4164 | */ |
| 4165 | --- a/drivers/usb/host/ehci.h |
| 4166 | +++ b/drivers/usb/host/ehci.h |
| 4167 | @@ -1,6 +1,7 @@ |
| 4168 | /* |
| 4169 | * Copyright (c) 2001-2002 by David Brownell |
| 4170 | - * |
| 4171 | + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 4172 | + * |
| 4173 | * This program is free software; you can redistribute it and/or modify it |
| 4174 | * under the terms of the GNU General Public License as published by the |
| 4175 | * Free Software Foundation; either version 2 of the License, or (at your |
| 4176 | @@ -147,7 +148,9 @@ struct ehci_hcd { /* one per controlle |
| 4177 | unsigned has_lpm:1; /* support link power management */ |
| 4178 | unsigned has_ppcd:1; /* support per-port change bits */ |
| 4179 | u8 sbrn; /* packed release number */ |
| 4180 | - |
| 4181 | +#if defined(CONFIG_COLDFIRE) |
| 4182 | + struct otg_transceiver *transceiver; |
| 4183 | +#endif |
| 4184 | /* irq statistics */ |
| 4185 | #ifdef EHCI_STATS |
| 4186 | struct ehci_stats stats; |
| 4187 | @@ -617,6 +620,54 @@ ehci_port_speed(struct ehci_hcd *ehci, u |
| 4188 | #define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) |
| 4189 | #endif |
| 4190 | |
| 4191 | +#if defined(CONFIG_COLDFIRE) |
| 4192 | + |
| 4193 | +#if defined(CONFIG_MMU) |
| 4194 | +#include <asm/fsl_usb_io.h> |
| 4195 | +/* |
| 4196 | + * Sorry, include/asm-m68k/io.h is messed up. It will give you a |
| 4197 | + * BE readl or a LE readl depending on whether or not CONFIG_PCI is set. |
| 4198 | + * how broken is that? Do the right thing here. |
| 4199 | + */ |
| 4200 | +#undef readl |
| 4201 | +#undef writel |
| 4202 | + |
| 4203 | +#define readl(addr) in_le32((__force unsigned *)(addr)) |
| 4204 | +#define writel(val, addr) out_le32((__force unsigned *)(addr), (val)) |
| 4205 | + |
| 4206 | +#define readl_be(addr) in_be32((__force unsigned *)(addr)) |
| 4207 | +#define writel_be(val, addr) out_be32((__force unsigned *)(addr), (val)) |
| 4208 | + |
| 4209 | +#else /* !CONFIG_MMU */ |
| 4210 | + |
| 4211 | +#define readl_be(addr) \ |
| 4212 | + ({u32 __v = (*(__force volatile u32 *)addr); __v; }) |
| 4213 | +#define writel_be(val, addr) \ |
| 4214 | + (void)((*(__force volatile u32 *)addr) = val) |
| 4215 | + |
| 4216 | +#ifndef in_be32 |
| 4217 | +#define in_be32(addr) \ |
| 4218 | + ({ u32 __v = (*(__force volatile u32 *)(addr)); __v; }) |
| 4219 | +#endif |
| 4220 | + |
| 4221 | +#ifndef in_le32 |
| 4222 | +#define in_le32(addr) \ |
| 4223 | + ({ u32 __v = le32_to_cpu(*(__force volatile __le32 *)(addr)); __v; }) |
| 4224 | +#endif |
| 4225 | + |
| 4226 | +#ifndef out_be32 |
| 4227 | +#define out_be32(addr, l) (void)((*(__force volatile u32 *)(addr)) = (l)) |
| 4228 | +#endif |
| 4229 | + |
| 4230 | +#ifndef out_le32 |
| 4231 | +#define out_le32(addr, l) \ |
| 4232 | + (void)((*(__force volatile __le32 *)(addr)) = cpu_to_le32(l)) |
| 4233 | +#endif |
| 4234 | + |
| 4235 | +#endif |
| 4236 | + |
| 4237 | +#endif /* CONFIG_COLDFIRE */ |
| 4238 | + |
| 4239 | static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, |
| 4240 | __u32 __iomem * regs) |
| 4241 | { |
| 4242 | --- a/drivers/usb/otg/Makefile |
| 4243 | +++ b/drivers/usb/otg/Makefile |
| 4244 | @@ -18,3 +18,10 @@ obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-x |
| 4245 | obj-$(CONFIG_USB_ULPI) += ulpi.o |
| 4246 | obj-$(CONFIG_USB_MSM_OTG_72K) += msm72k_otg.o |
| 4247 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o |
| 4248 | + |
| 4249 | +obj-$(CONFIG_USB_OTG) += usb.o |
| 4250 | +fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o |
| 4251 | +#ifneq ($(CONFIG_USB_OTG),) |
| 4252 | +ifneq ($(CONFIG_USB_OTG),) |
| 4253 | +obj-m += fsl_usb2_otg.o |
| 4254 | +endif |
| 4255 | --- /dev/null |
| 4256 | +++ b/drivers/usb/otg/fsl_otg.c |
| 4257 | @@ -0,0 +1,1212 @@ |
| 4258 | +/* |
| 4259 | + * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 4260 | + * |
| 4261 | + * Author: Li Yang <LeoLi@freescale.com> |
| 4262 | + * Jerry Huang <Chang-Ming.Huang@freescale.com> |
| 4263 | + * |
| 4264 | + * Initialization based on code from Shlomi Gridish. |
| 4265 | + * |
| 4266 | + * This program is free software; you can redistribute it and/or modify it |
| 4267 | + * under the terms of the GNU General Public License as published by the |
| 4268 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 4269 | + * option) any later version. |
| 4270 | + * |
| 4271 | + * This program is distributed in the hope that it will be useful, but |
| 4272 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 4273 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 4274 | + * General Public License for more details. |
| 4275 | + * |
| 4276 | + * You should have received a copy of the GNU General Public License along |
| 4277 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 4278 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 4279 | + */ |
| 4280 | + |
| 4281 | +#include <linux/module.h> |
| 4282 | +#include <linux/moduleparam.h> |
| 4283 | +#include <linux/kernel.h> |
| 4284 | +#include <linux/delay.h> |
| 4285 | +#include <linux/ioport.h> |
| 4286 | +#include <linux/sched.h> |
| 4287 | +#include <linux/slab.h> |
| 4288 | +#include <linux/smp_lock.h> |
| 4289 | +#include <linux/proc_fs.h> |
| 4290 | +#include <linux/errno.h> |
| 4291 | +#include <linux/init.h> |
| 4292 | +#include <linux/reboot.h> |
| 4293 | +#include <linux/timer.h> |
| 4294 | +#include <linux/list.h> |
| 4295 | +#include <linux/usb.h> |
| 4296 | +#include <linux/device.h> |
| 4297 | +#include <linux/usb/ch9.h> |
| 4298 | +#include <linux/usb/gadget.h> |
| 4299 | +#include <linux/workqueue.h> |
| 4300 | +#include <linux/time.h> |
| 4301 | +#include <linux/fsl_devices.h> |
| 4302 | +#include <linux/platform_device.h> |
| 4303 | + |
| 4304 | +#include <linux/io.h> |
| 4305 | +#include <asm/irq.h> |
| 4306 | +#include <asm/system.h> |
| 4307 | +#include <asm/byteorder.h> |
| 4308 | +#include <linux/uaccess.h> |
| 4309 | +#include <asm/unaligned.h> |
| 4310 | + |
| 4311 | +#include "fsl_otg.h" |
| 4312 | + |
| 4313 | +/* |
| 4314 | +#undef DBG |
| 4315 | +#undef VDBG |
| 4316 | +#define DBG(x...) printk(x) |
| 4317 | +#define VDBG(x...) printk(x) |
| 4318 | +*/ |
| 4319 | + |
| 4320 | +#define CONFIG_USB_OTG_DEBUG_FILES |
| 4321 | +#define DRIVER_VERSION "$Revision: 1.55 $" |
| 4322 | +#define DRIVER_AUTHOR "Jerry Huang/Li Yang" |
| 4323 | +#define DRIVER_DESC "Freescale USB OTG Driver" |
| 4324 | +#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC |
| 4325 | + |
| 4326 | +MODULE_DESCRIPTION("Freescale USB OTG Transceiver Driver"); |
| 4327 | + |
| 4328 | +static const char driver_name[] = "fsl-usb2-otg"; |
| 4329 | + |
| 4330 | +const pm_message_t otg_suspend_state = { |
| 4331 | + .event = 1, |
| 4332 | +}; |
| 4333 | + |
| 4334 | +#define HA_DATA_PULSE 1 |
| 4335 | + |
| 4336 | +volatile static struct usb_dr_mmap *usb_dr_regs; |
| 4337 | +static struct fsl_otg *fsl_otg_dev; |
| 4338 | +static int srp_wait_done; |
| 4339 | + |
| 4340 | +/* FSM timers */ |
| 4341 | +struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, |
| 4342 | + *b_ase0_brst_tmr, *b_se0_srp_tmr; |
| 4343 | + |
| 4344 | +/* Driver specific timers */ |
| 4345 | +struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, |
| 4346 | + *b_srp_wait_tmr, *a_wait_enum_tmr; |
| 4347 | + |
| 4348 | +static struct list_head active_timers; |
| 4349 | + |
| 4350 | +static struct fsl_otg_config fsl_otg_initdata = { |
| 4351 | + .otg_port = 1, |
| 4352 | +}; |
| 4353 | + |
| 4354 | +/* Routines to access transceiver ULPI registers */ |
| 4355 | +u8 view_ulpi(u8 addr) |
| 4356 | +{ |
| 4357 | + u32 temp; |
| 4358 | + |
| 4359 | + temp = 0x40000000 | (addr << 16); |
| 4360 | + temp = cpu_to_le32(temp); |
| 4361 | + fsl_writel(temp, &usb_dr_regs->ulpiview); |
| 4362 | + udelay(1000); |
| 4363 | + while (temp & 0x40) |
| 4364 | + temp = fsl_readl(&usb_dr_regs->ulpiview); |
| 4365 | + return (le32_to_cpu(temp) & 0x0000ff00) >> 8; |
| 4366 | +} |
| 4367 | + |
| 4368 | +int write_ulpi(u8 addr, u8 data) |
| 4369 | +{ |
| 4370 | + u32 temp; |
| 4371 | + |
| 4372 | + temp = 0x60000000 | (addr << 16) | data; |
| 4373 | + temp = cpu_to_hc32(temp); |
| 4374 | + fsl_writel(temp, &usb_dr_regs->ulpiview); |
| 4375 | + return 0; |
| 4376 | +} |
| 4377 | + |
| 4378 | +/* -------------------------------------------------------------*/ |
| 4379 | +/* Operations that will be called from OTG Finite State Machine */ |
| 4380 | + |
| 4381 | +/* Charge vbus for vbus pulsing in SRP */ |
| 4382 | +void fsl_otg_chrg_vbus(int on) |
| 4383 | +{ |
| 4384 | + u32 tmp; |
| 4385 | + |
| 4386 | + tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; |
| 4387 | + |
| 4388 | + if (on) |
| 4389 | + /* stop discharging, start charging */ |
| 4390 | + tmp = (tmp & ~OTGSC_CTRL_VBUS_DISCHARGE) | |
| 4391 | + OTGSC_CTRL_VBUS_CHARGE; |
| 4392 | + else |
| 4393 | + /* stop charging */ |
| 4394 | + tmp &= ~OTGSC_CTRL_VBUS_CHARGE; |
| 4395 | + |
| 4396 | + fsl_writel(tmp, &usb_dr_regs->otgsc); |
| 4397 | +} |
| 4398 | + |
| 4399 | +/* Discharge vbus through a resistor to ground */ |
| 4400 | +void fsl_otg_dischrg_vbus(int on) |
| 4401 | +{ |
| 4402 | + u32 tmp; |
| 4403 | + |
| 4404 | + tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; |
| 4405 | + |
| 4406 | + if (on) |
| 4407 | + /* stop charging, start discharging */ |
| 4408 | + tmp = (tmp & ~OTGSC_CTRL_VBUS_CHARGE) | |
| 4409 | + OTGSC_CTRL_VBUS_DISCHARGE; |
| 4410 | + else |
| 4411 | + /* stop discharging */ |
| 4412 | + tmp &= ~OTGSC_CTRL_VBUS_DISCHARGE; |
| 4413 | + |
| 4414 | + fsl_writel(tmp, &usb_dr_regs->otgsc); |
| 4415 | +} |
| 4416 | + |
| 4417 | +/* A-device driver vbus, controlled through PP bit in PORTSC */ |
| 4418 | +void fsl_otg_drv_vbus(int on) |
| 4419 | +{ |
| 4420 | +/* if (on) |
| 4421 | + usb_dr_regs->portsc = |
| 4422 | + cpu_to_le32((le32_to_cpu(usb_dr_regs->portsc) & |
| 4423 | + ~PORTSC_W1C_BITS) | PORTSC_PORT_POWER); |
| 4424 | + else |
| 4425 | + usb_dr_regs->portsc = |
| 4426 | + cpu_to_le32(le32_to_cpu(usb_dr_regs->portsc) & |
| 4427 | + ~PORTSC_W1C_BITS & ~PORTSC_PORT_POWER); |
| 4428 | +*/ |
| 4429 | +} |
| 4430 | + |
| 4431 | +/* |
| 4432 | + * Pull-up D+, signalling connect by periperal. Also used in |
| 4433 | + * data-line pulsing in SRP |
| 4434 | + */ |
| 4435 | +void fsl_otg_loc_conn(int on) |
| 4436 | +{ |
| 4437 | + u32 tmp; |
| 4438 | + |
| 4439 | + tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; |
| 4440 | + |
| 4441 | + if (on) |
| 4442 | + tmp |= OTGSC_CTRL_DATA_PULSING; |
| 4443 | + else |
| 4444 | + tmp &= ~OTGSC_CTRL_DATA_PULSING; |
| 4445 | + |
| 4446 | + fsl_writel(tmp, &usb_dr_regs->otgsc); |
| 4447 | +} |
| 4448 | + |
| 4449 | +/* Generate SOF by host. This is controlled through suspend/resume the |
| 4450 | + * port. In host mode, controller will automatically send SOF. |
| 4451 | + * Suspend will block the data on the port. |
| 4452 | + */ |
| 4453 | +void fsl_otg_loc_sof(int on) |
| 4454 | +{ |
| 4455 | + u32 tmp; |
| 4456 | + |
| 4457 | + tmp = fsl_readl(&fsl_otg_dev->dr_mem_map->portsc) & ~PORTSC_W1C_BITS; |
| 4458 | + if (on) |
| 4459 | + tmp |= PORTSC_PORT_FORCE_RESUME; |
| 4460 | + else |
| 4461 | + tmp |= PORTSC_PORT_SUSPEND; |
| 4462 | + |
| 4463 | + fsl_writel(tmp, &fsl_otg_dev->dr_mem_map->portsc); |
| 4464 | + |
| 4465 | +} |
| 4466 | + |
| 4467 | +/* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */ |
| 4468 | +void fsl_otg_start_pulse(void) |
| 4469 | +{ |
| 4470 | + u32 tmp; |
| 4471 | + |
| 4472 | + srp_wait_done = 0; |
| 4473 | +#ifdef HA_DATA_PULSE |
| 4474 | + tmp = fsl_readl(&usb_dr_regs->otgsc) & ~OTGSC_INTSTS_MASK; |
| 4475 | + tmp |= OTGSC_HA_DATA_PULSE; |
| 4476 | + fsl_writel(tmp, &usb_dr_regs->otgsc); |
| 4477 | +#else |
| 4478 | + fsl_otg_loc_conn(1); |
| 4479 | +#endif |
| 4480 | + |
| 4481 | + fsl_otg_add_timer(b_data_pulse_tmr); |
| 4482 | +} |
| 4483 | + |
| 4484 | +void fsl_otg_pulse_vbus(void); |
| 4485 | + |
| 4486 | +void b_data_pulse_end(unsigned long foo) |
| 4487 | +{ |
| 4488 | +#ifdef HA_DATA_PULSE |
| 4489 | +#else |
| 4490 | + fsl_otg_loc_conn(0); |
| 4491 | +#endif |
| 4492 | + |
| 4493 | + /* Do VBUS pulse after data pulse */ |
| 4494 | + fsl_otg_pulse_vbus(); |
| 4495 | +} |
| 4496 | + |
| 4497 | +void fsl_otg_pulse_vbus(void) |
| 4498 | +{ |
| 4499 | + srp_wait_done = 0; |
| 4500 | + fsl_otg_chrg_vbus(1); |
| 4501 | + /* start the timer to end vbus charge */ |
| 4502 | + fsl_otg_add_timer(b_vbus_pulse_tmr); |
| 4503 | +} |
| 4504 | + |
| 4505 | +void b_vbus_pulse_end(unsigned long foo) |
| 4506 | +{ |
| 4507 | + fsl_otg_chrg_vbus(0); |
| 4508 | + |
| 4509 | + /* As USB3300 using the same a_sess_vld and b_sess_vld voltage |
| 4510 | + * we need to discharge the bus for a while to distinguish |
| 4511 | + * residual voltage of vbus pulsing and A device pull up */ |
| 4512 | + fsl_otg_dischrg_vbus(1); |
| 4513 | + fsl_otg_add_timer(b_srp_wait_tmr); |
| 4514 | +} |
| 4515 | + |
| 4516 | +void b_srp_end(unsigned long foo) |
| 4517 | +{ |
| 4518 | + fsl_otg_dischrg_vbus(0); |
| 4519 | + srp_wait_done = 1; |
| 4520 | + |
| 4521 | + if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) && |
| 4522 | + fsl_otg_dev->fsm.b_sess_vld) |
| 4523 | + fsl_otg_dev->fsm.b_srp_done = 1; |
| 4524 | +} |
| 4525 | + |
| 4526 | +/* Workaround for a_host suspending too fast. When a_bus_req=0, |
| 4527 | + * a_host will start by SRP. It needs to set b_hnp_enable before |
| 4528 | + * actually suspending to start HNP |
| 4529 | + */ |
| 4530 | +void a_wait_enum(unsigned long foo) |
| 4531 | +{ |
| 4532 | + VDBG("a_wait_enum timeout\n"); |
| 4533 | + if (!fsl_otg_dev->otg.host->b_hnp_enable) |
| 4534 | + fsl_otg_add_timer(a_wait_enum_tmr); |
| 4535 | + else |
| 4536 | + otg_statemachine(&fsl_otg_dev->fsm); |
| 4537 | +} |
| 4538 | + |
| 4539 | +/* ------------------------------------------------------*/ |
| 4540 | + |
| 4541 | +/* The timeout callback function to set time out bit */ |
| 4542 | +void set_tmout(unsigned long indicator) |
| 4543 | +{ |
| 4544 | + *(int *)indicator = 1; |
| 4545 | +} |
| 4546 | + |
| 4547 | +/* Initialize timers */ |
| 4548 | +int fsl_otg_init_timers(struct otg_fsm *fsm) |
| 4549 | +{ |
| 4550 | + /* FSM used timers */ |
| 4551 | + a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, |
| 4552 | + (unsigned long)&fsm->a_wait_vrise_tmout); |
| 4553 | + if (a_wait_vrise_tmr == NULL) |
| 4554 | + return -ENOMEM; |
| 4555 | + |
| 4556 | + a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON, |
| 4557 | + (unsigned long)&fsm->a_wait_bcon_tmout); |
| 4558 | + if (a_wait_bcon_tmr == NULL) |
| 4559 | + return -ENOMEM; |
| 4560 | + |
| 4561 | + a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, |
| 4562 | + (unsigned long)&fsm->a_aidl_bdis_tmout); |
| 4563 | + if (a_aidl_bdis_tmr == NULL) |
| 4564 | + return -ENOMEM; |
| 4565 | + |
| 4566 | + b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, |
| 4567 | + (unsigned long)&fsm->b_ase0_brst_tmout); |
| 4568 | + if (b_ase0_brst_tmr == NULL) |
| 4569 | + return -ENOMEM; |
| 4570 | + |
| 4571 | + b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, |
| 4572 | + (unsigned long)&fsm->b_se0_srp); |
| 4573 | + if (b_se0_srp_tmr == NULL) |
| 4574 | + return -ENOMEM; |
| 4575 | + |
| 4576 | + b_srp_fail_tmr = otg_timer_initializer(&set_tmout, TB_SRP_FAIL, |
| 4577 | + (unsigned long)&fsm->b_srp_done); |
| 4578 | + if (b_srp_fail_tmr == NULL) |
| 4579 | + return -ENOMEM; |
| 4580 | + |
| 4581 | + a_wait_enum_tmr = otg_timer_initializer(&a_wait_enum, 10, |
| 4582 | + (unsigned long)&fsm); |
| 4583 | + if (a_wait_enum_tmr == NULL) |
| 4584 | + return -ENOMEM; |
| 4585 | + |
| 4586 | + /* device driver used timers */ |
| 4587 | + b_srp_wait_tmr = otg_timer_initializer(&b_srp_end, TB_SRP_WAIT, 0); |
| 4588 | + if (b_srp_wait_tmr == NULL) |
| 4589 | + return -ENOMEM; |
| 4590 | + |
| 4591 | + b_data_pulse_tmr = otg_timer_initializer(&b_data_pulse_end, |
| 4592 | + TB_DATA_PLS, 0); |
| 4593 | + if (b_data_pulse_tmr == NULL) |
| 4594 | + return -ENOMEM; |
| 4595 | + |
| 4596 | + b_vbus_pulse_tmr = otg_timer_initializer(&b_vbus_pulse_end, |
| 4597 | + TB_VBUS_PLS, 0); |
| 4598 | + if (b_vbus_pulse_tmr == NULL) |
| 4599 | + return -ENOMEM; |
| 4600 | + |
| 4601 | + return 0; |
| 4602 | +} |
| 4603 | + |
| 4604 | +/* Uninitialize timers */ |
| 4605 | +void fsl_otg_uninit_timers(void) |
| 4606 | +{ |
| 4607 | + /* FSM used timers */ |
| 4608 | + if (a_wait_vrise_tmr != NULL) |
| 4609 | + kfree(a_wait_vrise_tmr); |
| 4610 | + if (a_wait_bcon_tmr != NULL) |
| 4611 | + kfree(a_wait_bcon_tmr); |
| 4612 | + if (a_aidl_bdis_tmr != NULL) |
| 4613 | + kfree(a_aidl_bdis_tmr); |
| 4614 | + if (b_ase0_brst_tmr != NULL) |
| 4615 | + kfree(b_ase0_brst_tmr); |
| 4616 | + if (b_se0_srp_tmr != NULL) |
| 4617 | + kfree(b_se0_srp_tmr); |
| 4618 | + if (b_srp_fail_tmr != NULL) |
| 4619 | + kfree(b_srp_fail_tmr); |
| 4620 | + if (a_wait_enum_tmr != NULL) |
| 4621 | + kfree(a_wait_enum_tmr); |
| 4622 | + |
| 4623 | + /* device driver used timers */ |
| 4624 | + if (b_srp_wait_tmr != NULL) |
| 4625 | + kfree(b_srp_wait_tmr); |
| 4626 | + if (b_data_pulse_tmr != NULL) |
| 4627 | + kfree(b_data_pulse_tmr); |
| 4628 | + if (b_vbus_pulse_tmr != NULL) |
| 4629 | + kfree(b_vbus_pulse_tmr); |
| 4630 | +} |
| 4631 | + |
| 4632 | +/* Add timer to timer list */ |
| 4633 | +void fsl_otg_add_timer(void *gtimer) |
| 4634 | +{ |
| 4635 | + struct fsl_otg_timer *timer = (struct fsl_otg_timer *)gtimer; |
| 4636 | + struct fsl_otg_timer *tmp_timer; |
| 4637 | + |
| 4638 | + /* Check if the timer is already in the active list, |
| 4639 | + * if so update timer count |
| 4640 | + */ |
| 4641 | + list_for_each_entry(tmp_timer, &active_timers, list) |
| 4642 | + if (tmp_timer == timer) { |
| 4643 | + timer->count = timer->expires; |
| 4644 | + return; |
| 4645 | + } |
| 4646 | + timer->count = timer->expires; |
| 4647 | + list_add_tail(&timer->list, &active_timers); |
| 4648 | +} |
| 4649 | + |
| 4650 | +/* Remove timer from the timer list; clear timeout status */ |
| 4651 | +void fsl_otg_del_timer(void *gtimer) |
| 4652 | +{ |
| 4653 | + struct fsl_otg_timer *timer = (struct fsl_otg_timer *)gtimer; |
| 4654 | + struct fsl_otg_timer *tmp_timer, *del_tmp; |
| 4655 | + |
| 4656 | + list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) |
| 4657 | + if (tmp_timer == timer) |
| 4658 | + list_del(&timer->list); |
| 4659 | +} |
| 4660 | + |
| 4661 | +/* Reduce timer count by 1, and find timeout conditions. |
| 4662 | + * Called by fsl_otg 1ms timer interrupt |
| 4663 | + */ |
| 4664 | +int fsl_otg_tick_timer(void) |
| 4665 | +{ |
| 4666 | + struct fsl_otg_timer *tmp_timer, *del_tmp; |
| 4667 | + int expired = 0; |
| 4668 | + |
| 4669 | + list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { |
| 4670 | + tmp_timer->count--; |
| 4671 | + /* check if timer expires */ |
| 4672 | + if (!tmp_timer->count) { |
| 4673 | + list_del(&tmp_timer->list); |
| 4674 | + tmp_timer->function(tmp_timer->data); |
| 4675 | + expired = 1; |
| 4676 | + } |
| 4677 | + } |
| 4678 | + |
| 4679 | + return expired; |
| 4680 | +} |
| 4681 | + |
| 4682 | +/* Reset controller, not reset the bus */ |
| 4683 | +void otg_reset_controller(void) |
| 4684 | +{ |
| 4685 | + u32 command; |
| 4686 | + |
| 4687 | + command = fsl_readl(&usb_dr_regs->usbcmd); |
| 4688 | + command |= (1 << 1); |
| 4689 | + fsl_writel(command, &usb_dr_regs->usbcmd); |
| 4690 | + while (fsl_readl(&usb_dr_regs->usbcmd) & (1 << 1)) |
| 4691 | + ; |
| 4692 | +} |
| 4693 | + |
| 4694 | +/* Call suspend/resume routines in host driver */ |
| 4695 | +int fsl_otg_start_host(struct otg_fsm *fsm, int on) |
| 4696 | +{ |
| 4697 | + struct otg_transceiver *xceiv = fsm->transceiver; |
| 4698 | + struct device *dev; |
| 4699 | + struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); |
| 4700 | + u32 retval = 0; |
| 4701 | + |
| 4702 | + if (!xceiv->host) |
| 4703 | + return -ENODEV; |
| 4704 | + dev = xceiv->host->controller; |
| 4705 | + |
| 4706 | + /* Update a_vbus_vld state as a_vbus_vld int is disabled |
| 4707 | + * in device mode |
| 4708 | + */ |
| 4709 | + fsm->a_vbus_vld = |
| 4710 | + !!(fsl_readl(&usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID); |
| 4711 | + if (on) { |
| 4712 | + /* start fsl usb host controller */ |
| 4713 | + if (otg_dev->host_working) |
| 4714 | + goto end; |
| 4715 | + else { |
| 4716 | + otg_reset_controller(); |
| 4717 | + VDBG("host on......\n"); |
| 4718 | + if (dev->driver->resume) { |
| 4719 | + retval = dev->driver->resume(dev); |
| 4720 | + if (fsm->id) { |
| 4721 | + /* default-b */ |
| 4722 | + fsl_otg_drv_vbus(1); |
| 4723 | + /* Workaround: b_host can't driver |
| 4724 | + * vbus, but PP in PORTSC needs to |
| 4725 | + * be 1 for host to work. |
| 4726 | + * So we set drv_vbus bit in |
| 4727 | + * transceiver to 0 thru ULPI. */ |
| 4728 | + write_ulpi(0x0c, 0x20); |
| 4729 | + } |
| 4730 | + } |
| 4731 | + |
| 4732 | + otg_dev->host_working = 1; |
| 4733 | + } |
| 4734 | + } else { |
| 4735 | + /* stop fsl usb host controller */ |
| 4736 | + if (!otg_dev->host_working) |
| 4737 | + goto end; |
| 4738 | + else { |
| 4739 | + VDBG("host off......\n"); |
| 4740 | + if (dev && dev->driver) { |
| 4741 | + retval = dev->driver->suspend(dev, |
| 4742 | + otg_suspend_state); |
| 4743 | + if (fsm->id) |
| 4744 | + /* default-b */ |
| 4745 | + fsl_otg_drv_vbus(0); |
| 4746 | + } |
| 4747 | + otg_dev->host_working = 0; |
| 4748 | + } |
| 4749 | + } |
| 4750 | +end: |
| 4751 | + return retval; |
| 4752 | +} |
| 4753 | + |
| 4754 | +/* Call suspend and resume function in udc driver |
| 4755 | + * to stop and start udc driver. |
| 4756 | + */ |
| 4757 | +int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) |
| 4758 | +{ |
| 4759 | + struct otg_transceiver *xceiv = fsm->transceiver; |
| 4760 | + struct device *dev; |
| 4761 | + |
| 4762 | + if (!xceiv->gadget || !xceiv->gadget->dev.parent) |
| 4763 | + return -ENODEV; |
| 4764 | + |
| 4765 | + VDBG("gadget %s\n", on ? "on" : "off"); |
| 4766 | + dev = xceiv->gadget->dev.parent; |
| 4767 | + |
| 4768 | + if (on) |
| 4769 | + dev->driver->resume(dev); |
| 4770 | + else |
| 4771 | + dev->driver->suspend(dev, otg_suspend_state); |
| 4772 | + |
| 4773 | + return 0; |
| 4774 | +} |
| 4775 | + |
| 4776 | +/* Called by initialization code of host driver. Register host controller |
| 4777 | + * to the OTG. Suspend host for OTG role detection. |
| 4778 | + */ |
| 4779 | +static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) |
| 4780 | +{ |
| 4781 | + struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); |
| 4782 | + |
| 4783 | + if (!otg_p || otg_dev != fsl_otg_dev) |
| 4784 | + return -ENODEV; |
| 4785 | + |
| 4786 | + DBG("%s\n", __func__); |
| 4787 | + otg_p->host = host; |
| 4788 | + |
| 4789 | + otg_dev->fsm.a_bus_drop = 0; |
| 4790 | + otg_dev->fsm.a_bus_req = 1; |
| 4791 | + |
| 4792 | + if (host) { |
| 4793 | + VDBG("host off......\n"); |
| 4794 | + |
| 4795 | + otg_p->host->otg_port = fsl_otg_initdata.otg_port; |
| 4796 | + otg_p->host->is_b_host = otg_dev->fsm.id; |
| 4797 | + /* must leave time for khubd to finish its thing |
| 4798 | + * before yanking the host driver out from under it, |
| 4799 | + * so suspend the host after a short delay. |
| 4800 | + */ |
| 4801 | + otg_dev->host_working = 1; |
| 4802 | + schedule_delayed_work(&otg_dev->otg_event, 100); |
| 4803 | + return 0; |
| 4804 | + } else { /* host driver going away */ |
| 4805 | + |
| 4806 | + if (!(fsl_readl(&otg_dev->dr_mem_map->otgsc) & |
| 4807 | + OTGSC_STS_USB_ID)) { |
| 4808 | + /* Mini-A cable connected */ |
| 4809 | + struct otg_fsm *fsm = &otg_dev->fsm; |
| 4810 | + |
| 4811 | + otg_p->state = OTG_STATE_UNDEFINED; |
| 4812 | + fsm->protocol = PROTO_UNDEF; |
| 4813 | + } |
| 4814 | + } |
| 4815 | + |
| 4816 | + otg_dev->host_working = 0; |
| 4817 | + |
| 4818 | + otg_statemachine(&otg_dev->fsm); |
| 4819 | + |
| 4820 | + return 0; |
| 4821 | +} |
| 4822 | + |
| 4823 | +/* Called by initialization code of udc. Register udc to OTG.*/ |
| 4824 | +static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, |
| 4825 | + struct usb_gadget *gadget) |
| 4826 | +{ |
| 4827 | + struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); |
| 4828 | + |
| 4829 | + DBG("%s\n", __func__); |
| 4830 | + VDBG("otg_dev 0x%x\n", (int)otg_dev); |
| 4831 | + VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); |
| 4832 | + |
| 4833 | + if (!otg_p || otg_dev != fsl_otg_dev) |
| 4834 | + return -ENODEV; |
| 4835 | + |
| 4836 | + if (!gadget) { |
| 4837 | + if (!otg_dev->otg.default_a) |
| 4838 | + otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); |
| 4839 | + usb_gadget_vbus_disconnect(otg_dev->otg.gadget); |
| 4840 | + otg_dev->otg.gadget = 0; |
| 4841 | + otg_dev->fsm.b_bus_req = 0; |
| 4842 | + otg_statemachine(&otg_dev->fsm); |
| 4843 | + return 0; |
| 4844 | + } |
| 4845 | + |
| 4846 | + otg_p->gadget = gadget; |
| 4847 | + otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; |
| 4848 | + |
| 4849 | + otg_dev->fsm.b_bus_req = 1; |
| 4850 | + |
| 4851 | + /* start the gadget right away if the ID pin says Mini-B */ |
| 4852 | + DBG("ID pin=%d\n", otg_dev->fsm.id); |
| 4853 | + if (otg_dev->fsm.id == 1) { |
| 4854 | + fsl_otg_start_host(&otg_dev->fsm, 0); |
| 4855 | + otg_drv_vbus(&otg_dev->fsm, 0); |
| 4856 | + fsl_otg_start_gadget(&otg_dev->fsm, 1); |
| 4857 | + } |
| 4858 | + |
| 4859 | + return 0; |
| 4860 | +} |
| 4861 | + |
| 4862 | +/* Set OTG port power, only for B-device */ |
| 4863 | +static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA) |
| 4864 | +{ |
| 4865 | + if (!fsl_otg_dev) |
| 4866 | + return -ENODEV; |
| 4867 | + if (otg_p->state == OTG_STATE_B_PERIPHERAL) |
| 4868 | + printk(KERN_INFO "FSL OTG:Draw %d mA\n", mA); |
| 4869 | + |
| 4870 | + return 0; |
| 4871 | +} |
| 4872 | + |
| 4873 | +/* Delayed pin detect interrupt processing. |
| 4874 | + * |
| 4875 | + * When the Mini-A cable is disconnected from the board, |
| 4876 | + * the pin-detect interrupt happens before the disconnnect |
| 4877 | + * interrupts for the connected device(s). In order to |
| 4878 | + * process the disconnect interrupt(s) prior to switching |
| 4879 | + * roles, the pin-detect interrupts are delayed, and handled |
| 4880 | + * by this routine. |
| 4881 | + */ |
| 4882 | +static void fsl_otg_event(struct work_struct *work) |
| 4883 | +{ |
| 4884 | + struct fsl_otg *og = container_of(work, struct fsl_otg, otg_event.work); |
| 4885 | + struct otg_fsm *fsm = &og->fsm; |
| 4886 | + |
| 4887 | + if (fsm->id) { /* switch to gadget */ |
| 4888 | + fsl_otg_start_host(fsm, 0); |
| 4889 | + otg_drv_vbus(fsm, 0); |
| 4890 | + fsl_otg_start_gadget(fsm, 1); |
| 4891 | + } |
| 4892 | +} |
| 4893 | + |
| 4894 | +/* B-device start SRP */ |
| 4895 | +static int fsl_otg_start_srp(struct otg_transceiver *otg_p) |
| 4896 | +{ |
| 4897 | + struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); |
| 4898 | + |
| 4899 | + if (!otg_p || otg_dev != fsl_otg_dev |
| 4900 | + || otg_p->state != OTG_STATE_B_IDLE) |
| 4901 | + return -ENODEV; |
| 4902 | + |
| 4903 | + otg_dev->fsm.b_bus_req = 1; |
| 4904 | + otg_statemachine(&otg_dev->fsm); |
| 4905 | + |
| 4906 | + return 0; |
| 4907 | +} |
| 4908 | + |
| 4909 | +/* A_host suspend will call this function to start hnp */ |
| 4910 | +static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) |
| 4911 | +{ |
| 4912 | + struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); |
| 4913 | + |
| 4914 | + if (!otg_p || otg_dev != fsl_otg_dev) |
| 4915 | + return -ENODEV; |
| 4916 | + |
| 4917 | + /* printk("start_hnp.............\n"); */ |
| 4918 | + /* clear a_bus_req to enter a_suspend state */ |
| 4919 | + otg_dev->fsm.a_bus_req = 0; |
| 4920 | + otg_statemachine(&otg_dev->fsm); |
| 4921 | + |
| 4922 | + return 0; |
| 4923 | +} |
| 4924 | + |
| 4925 | +/* Interrupt handler. OTG/host/peripheral share the same int line. |
| 4926 | + * OTG driver clears OTGSC interrupts and leaves USB interrupts |
| 4927 | + * intact. It needs to have knowledge of some USB interrupts |
| 4928 | + * such as port change. |
| 4929 | + */ |
| 4930 | +irqreturn_t fsl_otg_isr(int irq, void *dev_id) |
| 4931 | +{ |
| 4932 | + struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; |
| 4933 | + struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg; |
| 4934 | + u32 otg_int_src, otg_sc; |
| 4935 | + |
| 4936 | + otg_sc = fsl_readl(&usb_dr_regs->otgsc); |
| 4937 | + otg_int_src = otg_sc & OTGSC_INTSTS_MASK; |
| 4938 | + |
| 4939 | + /* Only clear otg interrupts */ |
| 4940 | + fsl_writel(otg_sc, &usb_dr_regs->otgsc); |
| 4941 | + |
| 4942 | + /*FIXME: ID change not generate when init to 0 */ |
| 4943 | + fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; |
| 4944 | + otg->default_a = (fsm->id == 0); |
| 4945 | + |
| 4946 | + /* process OTG interrupts */ |
| 4947 | + if (otg_int_src) { |
| 4948 | + if (otg_int_src & OTGSC_INTSTS_USB_ID) { |
| 4949 | + fsm->id = (otg_sc & OTGSC_STS_USB_ID) ? 1 : 0; |
| 4950 | + otg->default_a = (fsm->id == 0); |
| 4951 | + /* clear conn information */ |
| 4952 | + if (fsm->id) |
| 4953 | + fsm->b_conn = 0; |
| 4954 | + else |
| 4955 | + fsm->a_conn = 0; |
| 4956 | + |
| 4957 | + if (otg->host) |
| 4958 | + otg->host->is_b_host = fsm->id; |
| 4959 | + if (otg->gadget) |
| 4960 | + otg->gadget->is_a_peripheral = !fsm->id; |
| 4961 | + VDBG("ID int (ID is %d)\n", fsm->id); |
| 4962 | + |
| 4963 | + if (fsm->id) { /* switch to gadget */ |
| 4964 | + schedule_delayed_work(&((struct fsl_otg *) |
| 4965 | + dev_id)->otg_event, 100); |
| 4966 | + } else { /* switch to host */ |
| 4967 | + cancel_delayed_work(& |
| 4968 | + ((struct fsl_otg *)dev_id)-> |
| 4969 | + otg_event); |
| 4970 | + fsl_otg_start_gadget(fsm, 0); |
| 4971 | + otg_drv_vbus(fsm, 1); |
| 4972 | + fsl_otg_start_host(fsm, 1); |
| 4973 | + } |
| 4974 | + return IRQ_HANDLED; |
| 4975 | + } |
| 4976 | + } |
| 4977 | + return IRQ_NONE; |
| 4978 | +} |
| 4979 | + |
| 4980 | +static struct otg_fsm_ops fsl_otg_ops = { |
| 4981 | + .chrg_vbus = fsl_otg_chrg_vbus, |
| 4982 | + .drv_vbus = fsl_otg_drv_vbus, |
| 4983 | + .loc_conn = fsl_otg_loc_conn, |
| 4984 | + .loc_sof = fsl_otg_loc_sof, |
| 4985 | + .start_pulse = fsl_otg_start_pulse, |
| 4986 | + |
| 4987 | + .add_timer = fsl_otg_add_timer, |
| 4988 | + .del_timer = fsl_otg_del_timer, |
| 4989 | + |
| 4990 | + .start_host = fsl_otg_start_host, |
| 4991 | + .start_gadget = fsl_otg_start_gadget, |
| 4992 | +}; |
| 4993 | + |
| 4994 | +/* Initialize the global variable fsl_otg_dev and request IRQ for OTG */ |
| 4995 | +static int fsl_otg_conf(struct platform_device *pdev) |
| 4996 | +{ |
| 4997 | + int status; |
| 4998 | + struct fsl_otg *fsl_otg_tc; |
| 4999 | + struct fsl_usb2_platform_data *pdata; |
| 5000 | + |
| 5001 | + pdata = pdev->dev.platform_data; |
| 5002 | + |
| 5003 | + if (fsl_otg_dev) |
| 5004 | + return 0; |
| 5005 | + |
| 5006 | + /* allocate space to fsl otg device */ |
| 5007 | + fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL); |
| 5008 | + if (!fsl_otg_tc) |
| 5009 | + return -ENODEV; |
| 5010 | + |
| 5011 | + INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event); |
| 5012 | + |
| 5013 | + INIT_LIST_HEAD(&active_timers); |
| 5014 | + status = fsl_otg_init_timers(&fsl_otg_tc->fsm); |
| 5015 | + if (status) { |
| 5016 | + printk(KERN_INFO "Couldn't init OTG timers\n"); |
| 5017 | + fsl_otg_uninit_timers(); |
| 5018 | + kfree(fsl_otg_tc); |
| 5019 | + return status; |
| 5020 | + } |
| 5021 | + spin_lock_init(&fsl_otg_tc->fsm.lock); |
| 5022 | + |
| 5023 | + /* Set OTG state machine operations */ |
| 5024 | + fsl_otg_tc->fsm.ops = &fsl_otg_ops; |
| 5025 | + |
| 5026 | + /* initialize the otg structure */ |
| 5027 | + fsl_otg_tc->otg.label = DRIVER_DESC; |
| 5028 | + fsl_otg_tc->otg.set_host = fsl_otg_set_host; |
| 5029 | + fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral; |
| 5030 | + fsl_otg_tc->otg.set_power = fsl_otg_set_power; |
| 5031 | + fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; |
| 5032 | + fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; |
| 5033 | + |
| 5034 | + fsl_otg_dev = fsl_otg_tc; |
| 5035 | + |
| 5036 | + /* Store the otg transceiver */ |
| 5037 | + status = otg_set_transceiver(&fsl_otg_tc->otg); |
| 5038 | + if (status) { |
| 5039 | + printk(KERN_WARNING ": unable to register OTG transceiver.\n"); |
| 5040 | + return status; |
| 5041 | + } |
| 5042 | + |
| 5043 | + return 0; |
| 5044 | +} |
| 5045 | + |
| 5046 | +/* OTG Initialization*/ |
| 5047 | +int usb_otg_start(struct platform_device *pdev) |
| 5048 | +{ |
| 5049 | + struct fsl_otg __iomem *p_otg; |
| 5050 | + struct otg_transceiver *otg_trans = otg_get_transceiver(); |
| 5051 | + struct otg_fsm *fsm; |
| 5052 | + volatile unsigned long *p; |
| 5053 | + int status; |
| 5054 | + struct resource *res; |
| 5055 | + u32 temp; |
| 5056 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 5057 | + |
| 5058 | + p_otg = container_of(otg_trans, struct fsl_otg, otg); |
| 5059 | + fsm = &p_otg->fsm; |
| 5060 | + |
| 5061 | + /* Initialize the state machine structure with default values */ |
| 5062 | + SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); |
| 5063 | + fsm->transceiver = &p_otg->otg; |
| 5064 | + |
| 5065 | + /* We don't require predefined MEM/IRQ resource index */ |
| 5066 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 5067 | + if (!res) |
| 5068 | + return -ENXIO; |
| 5069 | + |
| 5070 | + /* We don't request_mem_region here to enable resource sharing |
| 5071 | + * with host/device */ |
| 5072 | + |
| 5073 | + usb_dr_regs = ioremap(res->start, sizeof(struct usb_dr_mmap)); |
| 5074 | + p_otg->dr_mem_map = (struct usb_dr_mmap *)usb_dr_regs; |
| 5075 | + pdata->regs = (void *)usb_dr_regs; |
| 5076 | + |
| 5077 | + /* request irq */ |
| 5078 | + p_otg->irq = platform_get_irq(pdev, 0); |
| 5079 | + status = request_irq(p_otg->irq, fsl_otg_isr, |
| 5080 | + IRQF_SHARED, driver_name, p_otg); |
| 5081 | + if (status) { |
| 5082 | + dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n", |
| 5083 | + p_otg->irq, status); |
| 5084 | + iounmap(p_otg->dr_mem_map); |
| 5085 | + kfree(p_otg); |
| 5086 | + return status; |
| 5087 | + } |
| 5088 | + |
| 5089 | + if (pdata->init && pdata->init(pdev) != 0) |
| 5090 | + return -EINVAL; |
| 5091 | + |
| 5092 | + |
| 5093 | + /* Export DR controller resources */ |
| 5094 | + otg_set_resources(pdev->resource); |
| 5095 | + |
| 5096 | + /* stop the controller */ |
| 5097 | + temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); |
| 5098 | + temp &= ~USB_CMD_RUN_STOP; |
| 5099 | + fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); |
| 5100 | + |
| 5101 | + /* reset the controller */ |
| 5102 | + temp = fsl_readl(&p_otg->dr_mem_map->usbcmd); |
| 5103 | + temp |= USB_CMD_CTRL_RESET; |
| 5104 | + fsl_writel(temp, &p_otg->dr_mem_map->usbcmd); |
| 5105 | + |
| 5106 | + /* wait reset completed */ |
| 5107 | + udelay(2); |
| 5108 | + while (fsl_readl(&p_otg->dr_mem_map->usbcmd) & USB_CMD_CTRL_RESET) |
| 5109 | + ; |
| 5110 | + |
| 5111 | + /* configure the VBUSHS as IDLE(both host and device) */ |
| 5112 | + temp = USB_MODE_STREAM_DISABLE | (pdata->es ? USB_MODE_ES : 0); |
| 5113 | + fsl_writel(temp, &p_otg->dr_mem_map->usbmode); |
| 5114 | + |
| 5115 | + /* configure PHY interface */ |
| 5116 | + temp = fsl_readl(&p_otg->dr_mem_map->portsc); |
| 5117 | + temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW); |
| 5118 | + switch (pdata->phy_mode) { |
| 5119 | + case FSL_USB2_PHY_ULPI: |
| 5120 | + temp |= PORTSC_PTS_ULPI; |
| 5121 | + break; |
| 5122 | + case FSL_USB2_PHY_UTMI_WIDE: |
| 5123 | + temp |= PORTSC_PTW_16BIT; |
| 5124 | + /* fall through */ |
| 5125 | + case FSL_USB2_PHY_UTMI: |
| 5126 | + temp |= PORTSC_PTS_UTMI; |
| 5127 | + /* fall through */ |
| 5128 | + default: |
| 5129 | + break; |
| 5130 | + } |
| 5131 | + fsl_writel(temp, &p_otg->dr_mem_map->portsc); |
| 5132 | + |
| 5133 | + if (pdata->have_sysif_regs) { |
| 5134 | + /* configure control enable IO output, big endian register */ |
| 5135 | + p = (volatile unsigned long *)(&p_otg->dr_mem_map->control); |
| 5136 | + temp = *p; |
| 5137 | + temp |= USB_CTRL_IOENB; |
| 5138 | + *p = temp; |
| 5139 | + } |
| 5140 | + |
| 5141 | + /* disable all interrupt and clear all OTGSC status */ |
| 5142 | + temp = fsl_readl(&p_otg->dr_mem_map->otgsc); |
| 5143 | + temp &= ~OTGSC_INTERRUPT_ENABLE_BITS_MASK; |
| 5144 | + temp |= OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE; |
| 5145 | + fsl_writel(temp, &p_otg->dr_mem_map->otgsc); |
| 5146 | + |
| 5147 | + |
| 5148 | + /* |
| 5149 | + * The identification (id) input is FALSE when a Mini-A plug is inserted |
| 5150 | + * in the devices Mini-AB receptacle. Otherwise, this input is TRUE. |
| 5151 | + * Also: record initial state of ID pin |
| 5152 | + */ |
| 5153 | + if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) { |
| 5154 | + p_otg->otg.state = OTG_STATE_UNDEFINED; |
| 5155 | + p_otg->fsm.id = 1; |
| 5156 | + } else { |
| 5157 | + p_otg->otg.state = OTG_STATE_A_IDLE; |
| 5158 | + p_otg->fsm.id = 0; |
| 5159 | + } |
| 5160 | + |
| 5161 | + DBG("initial ID pin=%d\n", p_otg->fsm.id); |
| 5162 | + |
| 5163 | + /* enable OTG ID pin interrupt */ |
| 5164 | + temp = fsl_readl(&p_otg->dr_mem_map->otgsc); |
| 5165 | + temp |= OTGSC_INTR_USB_ID_EN; |
| 5166 | + temp &= ~(OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN); |
| 5167 | + fsl_writel(temp, &p_otg->dr_mem_map->otgsc); |
| 5168 | + |
| 5169 | + return 0; |
| 5170 | +} |
| 5171 | + |
| 5172 | +/*------------------------------------------------------------------------- |
| 5173 | + PROC File System Support |
| 5174 | +-------------------------------------------------------------------------*/ |
| 5175 | +#ifdef CONFIG_USB_OTG_DEBUG_FILES |
| 5176 | + |
| 5177 | +#include <linux/seq_file.h> |
| 5178 | + |
| 5179 | +static const char proc_filename[] = "driver/fsl_usb2_otg"; |
| 5180 | + |
| 5181 | +static int otg_proc_read(char *page, char **start, off_t off, int count, |
| 5182 | + int *eof, void *_dev) |
| 5183 | +{ |
| 5184 | + struct otg_fsm *fsm = &fsl_otg_dev->fsm; |
| 5185 | + char *buf = page; |
| 5186 | + char *next = buf; |
| 5187 | + unsigned size = count; |
| 5188 | + unsigned long flags; |
| 5189 | + int t; |
| 5190 | + u32 tmp_reg; |
| 5191 | + |
| 5192 | + if (off != 0) |
| 5193 | + return 0; |
| 5194 | + |
| 5195 | + spin_lock_irqsave(&fsm->lock, flags); |
| 5196 | + |
| 5197 | + /* ------basic driver infomation ---- */ |
| 5198 | + t = scnprintf(next, size, |
| 5199 | + DRIVER_DESC "\n" "fsl_usb2_otg version: %s\n\n", |
| 5200 | + DRIVER_VERSION); |
| 5201 | + size -= t; |
| 5202 | + next += t; |
| 5203 | + |
| 5204 | + /* ------ Registers ----- */ |
| 5205 | + tmp_reg = fsl_readl(&usb_dr_regs->otgsc); |
| 5206 | + t = scnprintf(next, size, "OTGSC reg: %08x\n", tmp_reg); |
| 5207 | + size -= t; |
| 5208 | + next += t; |
| 5209 | + |
| 5210 | + tmp_reg = fsl_readl(&usb_dr_regs->portsc); |
| 5211 | + t = scnprintf(next, size, "PORTSC reg: %08x\n", tmp_reg); |
| 5212 | + size -= t; |
| 5213 | + next += t; |
| 5214 | + |
| 5215 | + tmp_reg = fsl_readl(&usb_dr_regs->usbmode); |
| 5216 | + t = scnprintf(next, size, "USBMODE reg: %08x\n", tmp_reg); |
| 5217 | + size -= t; |
| 5218 | + next += t; |
| 5219 | + |
| 5220 | + tmp_reg = fsl_readl(&usb_dr_regs->usbcmd); |
| 5221 | + t = scnprintf(next, size, "USBCMD reg: %08x\n", tmp_reg); |
| 5222 | + size -= t; |
| 5223 | + next += t; |
| 5224 | + |
| 5225 | + tmp_reg = fsl_readl(&usb_dr_regs->usbsts); |
| 5226 | + t = scnprintf(next, size, "USBSTS reg: %08x\n", tmp_reg); |
| 5227 | + size -= t; |
| 5228 | + next += t; |
| 5229 | + |
| 5230 | + tmp_reg = fsl_readl(&usb_dr_regs->usbintr); |
| 5231 | + t = scnprintf(next, size, "USBINTR reg: %08x\n", tmp_reg); |
| 5232 | + size -= t; |
| 5233 | + next += t; |
| 5234 | + |
| 5235 | + /* ------ State ----- */ |
| 5236 | + t = scnprintf(next, size, |
| 5237 | + "OTG state: %s\n\n", |
| 5238 | + state_string(fsl_otg_dev->otg.state)); |
| 5239 | + size -= t; |
| 5240 | + next += t; |
| 5241 | + |
| 5242 | + /* ------ State Machine Variables ----- */ |
| 5243 | + t = scnprintf(next, size, "a_bus_req: %d\n", fsm->a_bus_req); |
| 5244 | + size -= t; |
| 5245 | + next += t; |
| 5246 | + |
| 5247 | + t = scnprintf(next, size, "b_bus_req: %d\n", fsm->b_bus_req); |
| 5248 | + size -= t; |
| 5249 | + next += t; |
| 5250 | + |
| 5251 | + t = scnprintf(next, size, "a_bus_resume: %d\n", fsm->a_bus_resume); |
| 5252 | + size -= t; |
| 5253 | + next += t; |
| 5254 | + |
| 5255 | + t = scnprintf(next, size, "a_bus_suspend: %d\n", fsm->a_bus_suspend); |
| 5256 | + size -= t; |
| 5257 | + next += t; |
| 5258 | + |
| 5259 | + t = scnprintf(next, size, "a_conn: %d\n", fsm->a_conn); |
| 5260 | + size -= t; |
| 5261 | + next += t; |
| 5262 | + |
| 5263 | + t = scnprintf(next, size, "a_sess_vld: %d\n", fsm->a_sess_vld); |
| 5264 | + size -= t; |
| 5265 | + next += t; |
| 5266 | + |
| 5267 | + t = scnprintf(next, size, "a_srp_det: %d\n", fsm->a_srp_det); |
| 5268 | + size -= t; |
| 5269 | + next += t; |
| 5270 | + |
| 5271 | + t = scnprintf(next, size, "a_vbus_vld: %d\n", fsm->a_vbus_vld); |
| 5272 | + size -= t; |
| 5273 | + next += t; |
| 5274 | + |
| 5275 | + t = scnprintf(next, size, "b_bus_resume: %d\n", fsm->b_bus_resume); |
| 5276 | + size -= t; |
| 5277 | + next += t; |
| 5278 | + |
| 5279 | + t = scnprintf(next, size, "b_bus_suspend: %d\n", fsm->b_bus_suspend); |
| 5280 | + size -= t; |
| 5281 | + next += t; |
| 5282 | + |
| 5283 | + t = scnprintf(next, size, "b_conn: %d\n", fsm->b_conn); |
| 5284 | + size -= t; |
| 5285 | + next += t; |
| 5286 | + |
| 5287 | + t = scnprintf(next, size, "b_se0_srp: %d\n", fsm->b_se0_srp); |
| 5288 | + size -= t; |
| 5289 | + next += t; |
| 5290 | + |
| 5291 | + t = scnprintf(next, size, "b_sess_end: %d\n", fsm->b_sess_end); |
| 5292 | + size -= t; |
| 5293 | + next += t; |
| 5294 | + |
| 5295 | + t = scnprintf(next, size, "b_sess_vld: %d\n", fsm->b_sess_vld); |
| 5296 | + size -= t; |
| 5297 | + next += t; |
| 5298 | + |
| 5299 | + t = scnprintf(next, size, "id: %d\n", fsm->id); |
| 5300 | + size -= t; |
| 5301 | + next += t; |
| 5302 | + |
| 5303 | + spin_unlock_irqrestore(&fsm->lock, flags); |
| 5304 | + |
| 5305 | + *eof = 1; |
| 5306 | + return count - size; |
| 5307 | +} |
| 5308 | + |
| 5309 | +#define create_proc_file() create_proc_read_entry(proc_filename, \ |
| 5310 | + 0, NULL, otg_proc_read, NULL) |
| 5311 | + |
| 5312 | +#define remove_proc_file() remove_proc_entry(proc_filename, NULL) |
| 5313 | + |
| 5314 | +#else /* !CONFIG_USB_OTG_DEBUG_FILES */ |
| 5315 | + |
| 5316 | +#define create_proc_file() do {} while (0) |
| 5317 | +#define remove_proc_file() do {} while (0) |
| 5318 | + |
| 5319 | +#endif /*CONFIG_USB_OTG_DEBUG_FILES */ |
| 5320 | + |
| 5321 | +/*----------------------------------------------------------*/ |
| 5322 | +/* Char driver interface to control some OTG input */ |
| 5323 | + |
| 5324 | +/* This function handle some ioctl command,such as get otg |
| 5325 | + * status and set host suspend |
| 5326 | + */ |
| 5327 | +static long fsl_otg_ioctl(struct file *file, |
| 5328 | + unsigned int cmd, unsigned long arg) |
| 5329 | +{ |
| 5330 | + u32 retval = 0; |
| 5331 | + |
| 5332 | + switch (cmd) { |
| 5333 | + case GET_OTG_STATUS: |
| 5334 | + retval = fsl_otg_dev->host_working; |
| 5335 | + break; |
| 5336 | + |
| 5337 | + case SET_A_SUSPEND_REQ: |
| 5338 | + fsl_otg_dev->fsm.a_suspend_req = arg; |
| 5339 | + break; |
| 5340 | + |
| 5341 | + case SET_A_BUS_DROP: |
| 5342 | + fsl_otg_dev->fsm.a_bus_drop = arg; |
| 5343 | + break; |
| 5344 | + |
| 5345 | + case SET_A_BUS_REQ: |
| 5346 | + fsl_otg_dev->fsm.a_bus_req = arg; |
| 5347 | + break; |
| 5348 | + |
| 5349 | + case SET_B_BUS_REQ: |
| 5350 | + fsl_otg_dev->fsm.b_bus_req = arg; |
| 5351 | + break; |
| 5352 | + |
| 5353 | + default: |
| 5354 | + break; |
| 5355 | + } |
| 5356 | + |
| 5357 | + otg_statemachine(&fsl_otg_dev->fsm); |
| 5358 | + |
| 5359 | + return retval; |
| 5360 | +} |
| 5361 | + |
| 5362 | +static int fsl_otg_open(struct inode *inode, struct file *file) |
| 5363 | +{ |
| 5364 | + |
| 5365 | + return 0; |
| 5366 | +} |
| 5367 | + |
| 5368 | +static int fsl_otg_release(struct inode *inode, struct file *file) |
| 5369 | +{ |
| 5370 | + |
| 5371 | + return 0; |
| 5372 | +} |
| 5373 | + |
| 5374 | +static struct file_operations otg_fops = { |
| 5375 | + .owner = THIS_MODULE, |
| 5376 | + .llseek = NULL, |
| 5377 | + .read = NULL, |
| 5378 | + .write = NULL, |
| 5379 | + .unlocked_ioctl = fsl_otg_ioctl, |
| 5380 | + .open = fsl_otg_open, |
| 5381 | + .release = fsl_otg_release, |
| 5382 | +}; |
| 5383 | + |
| 5384 | +static int __init fsl_otg_probe(struct platform_device *pdev) |
| 5385 | +{ |
| 5386 | + int status; |
| 5387 | + struct fsl_usb2_platform_data *pdata; |
| 5388 | + |
| 5389 | + DBG("pdev=0x%p\n", pdev); |
| 5390 | + |
| 5391 | + if (!pdev) |
| 5392 | + return -ENODEV; |
| 5393 | + |
| 5394 | + if (!pdev->dev.platform_data) |
| 5395 | + return -ENOMEM; |
| 5396 | + |
| 5397 | + pdata = pdev->dev.platform_data; |
| 5398 | + fsl_set_usb_accessors(pdata); |
| 5399 | + |
| 5400 | + /* configure the OTG */ |
| 5401 | + status = fsl_otg_conf(pdev); |
| 5402 | + if (status) { |
| 5403 | + printk(KERN_INFO "Couldn't init OTG module\n"); |
| 5404 | + return -status; |
| 5405 | + } |
| 5406 | + |
| 5407 | + /* start OTG */ |
| 5408 | + status = usb_otg_start(pdev); |
| 5409 | + |
| 5410 | + if (register_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME, &otg_fops)) { |
| 5411 | + printk(KERN_WARNING FSL_OTG_NAME |
| 5412 | + ": unable to register FSL OTG device\n"); |
| 5413 | + return -EIO; |
| 5414 | + } |
| 5415 | + |
| 5416 | + create_proc_file(); |
| 5417 | + return status; |
| 5418 | +} |
| 5419 | + |
| 5420 | +static int __exit fsl_otg_remove(struct platform_device *pdev) |
| 5421 | +{ |
| 5422 | + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
| 5423 | + |
| 5424 | + otg_set_transceiver(NULL); |
| 5425 | + free_irq(fsl_otg_dev->irq, fsl_otg_dev); |
| 5426 | + |
| 5427 | + iounmap((void *)usb_dr_regs); |
| 5428 | + |
| 5429 | + kfree(fsl_otg_dev); |
| 5430 | + |
| 5431 | + remove_proc_file(); |
| 5432 | + |
| 5433 | + unregister_chrdev(FSL_OTG_MAJOR, FSL_OTG_NAME); |
| 5434 | + |
| 5435 | + if (pdata->exit) |
| 5436 | + pdata->exit(pdev); |
| 5437 | + |
| 5438 | + return 0; |
| 5439 | +} |
| 5440 | + |
| 5441 | +struct platform_driver fsl_otg_driver = { |
| 5442 | + .probe = fsl_otg_probe, |
| 5443 | + .remove = __exit_p(fsl_otg_remove), |
| 5444 | + .driver = { |
| 5445 | + .name = driver_name, |
| 5446 | + .owner = THIS_MODULE, |
| 5447 | + }, |
| 5448 | +}; |
| 5449 | + |
| 5450 | +/*-------------------------------------------------------------------------*/ |
| 5451 | + |
| 5452 | +static int __init fsl_usb_otg_init(void) |
| 5453 | +{ |
| 5454 | + printk(KERN_INFO DRIVER_DESC " loaded, %s\n", DRIVER_VERSION); |
| 5455 | + return platform_driver_register(&fsl_otg_driver); |
| 5456 | +} |
| 5457 | + |
| 5458 | +static void __exit fsl_usb_otg_exit(void) |
| 5459 | +{ |
| 5460 | + platform_driver_unregister(&fsl_otg_driver); |
| 5461 | + printk(KERN_INFO DRIVER_DESC " unloaded\n"); |
| 5462 | +} |
| 5463 | + |
| 5464 | +module_init(fsl_usb_otg_init); |
| 5465 | +module_exit(fsl_usb_otg_exit); |
| 5466 | + |
| 5467 | +MODULE_DESCRIPTION(DRIVER_INFO); |
| 5468 | +MODULE_AUTHOR(DRIVER_AUTHOR); |
| 5469 | +MODULE_LICENSE("GPL"); |
| 5470 | --- /dev/null |
| 5471 | +++ b/drivers/usb/otg/fsl_otg.h |
| 5472 | @@ -0,0 +1,423 @@ |
| 5473 | +/* Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 5474 | + * |
| 5475 | + * This program is free software; you can redistribute it and/or modify it |
| 5476 | + * under the terms of the GNU General Public License as published by the |
| 5477 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 5478 | + * option) any later version. |
| 5479 | + * |
| 5480 | + * This program is distributed in the hope that it will be useful, but |
| 5481 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 5482 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 5483 | + * General Public License for more details. |
| 5484 | + * |
| 5485 | + * You should have received a copy of the GNU General Public License along |
| 5486 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 5487 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 5488 | + */ |
| 5489 | + |
| 5490 | +#include "otg_fsm.h" |
| 5491 | +#include <linux/usb/otg.h> |
| 5492 | +#include <linux/ioctl.h> |
| 5493 | + |
| 5494 | +#ifdef CONFIG_PPC32 |
| 5495 | +#include <asm/fsl_usb_io.h> |
| 5496 | +#elif CONFIG_COLDFIRE |
| 5497 | +#include <asm/mcfsim.h> |
| 5498 | +#include <asm/fsl_usb_io.h> |
| 5499 | +#endif |
| 5500 | + |
| 5501 | +#define hc32_to_cpu(x) (x) |
| 5502 | +#define cpu_to_hc32(x) (x) |
| 5503 | + |
| 5504 | + /* USB Command Register Bit Masks */ |
| 5505 | +#define USB_CMD_RUN_STOP (0x1<<0) |
| 5506 | +#define USB_CMD_CTRL_RESET (0x1<<1) |
| 5507 | +#define USB_CMD_PERIODIC_SCHEDULE_EN (0x1<<4) |
| 5508 | +#define USB_CMD_ASYNC_SCHEDULE_EN (0x1<<5) |
| 5509 | +#define USB_CMD_INT_AA_DOORBELL (0x1<<6) |
| 5510 | +#define USB_CMD_ASP (0x3<<8) |
| 5511 | +#define USB_CMD_ASYNC_SCH_PARK_EN (0x1<<11) |
| 5512 | +#define USB_CMD_SUTW (0x1<<13) |
| 5513 | +#define USB_CMD_ATDTW (0x1<<14) |
| 5514 | +#define USB_CMD_ITC (0xFF<<16) |
| 5515 | + |
| 5516 | +/* bit 15,3,2 are frame list size */ |
| 5517 | +#define USB_CMD_FRAME_SIZE_1024 (0x0<<15 | 0x0<<2) |
| 5518 | +#define USB_CMD_FRAME_SIZE_512 (0x0<<15 | 0x1<<2) |
| 5519 | +#define USB_CMD_FRAME_SIZE_256 (0x0<<15 | 0x2<<2) |
| 5520 | +#define USB_CMD_FRAME_SIZE_128 (0x0<<15 | 0x3<<2) |
| 5521 | +#define USB_CMD_FRAME_SIZE_64 (0x1<<15 | 0x0<<2) |
| 5522 | +#define USB_CMD_FRAME_SIZE_32 (0x1<<15 | 0x1<<2) |
| 5523 | +#define USB_CMD_FRAME_SIZE_16 (0x1<<15 | 0x2<<2) |
| 5524 | +#define USB_CMD_FRAME_SIZE_8 (0x1<<15 | 0x3<<2) |
| 5525 | + |
| 5526 | +/* bit 9-8 are async schedule park mode count */ |
| 5527 | +#define USB_CMD_ASP_00 (0x0<<8) |
| 5528 | +#define USB_CMD_ASP_01 (0x1<<8) |
| 5529 | +#define USB_CMD_ASP_10 (0x2<<8) |
| 5530 | +#define USB_CMD_ASP_11 (0x3<<8) |
| 5531 | +#define USB_CMD_ASP_BIT_POS (8) |
| 5532 | + |
| 5533 | +/* bit 23-16 are interrupt threshold control */ |
| 5534 | +#define USB_CMD_ITC_NO_THRESHOLD (0x00<<16) |
| 5535 | +#define USB_CMD_ITC_1_MICRO_FRM (0x01<<16) |
| 5536 | +#define USB_CMD_ITC_2_MICRO_FRM (0x02<<16) |
| 5537 | +#define USB_CMD_ITC_4_MICRO_FRM (0x04<<16) |
| 5538 | +#define USB_CMD_ITC_8_MICRO_FRM (0x08<<16) |
| 5539 | +#define USB_CMD_ITC_16_MICRO_FRM (0x10<<16) |
| 5540 | +#define USB_CMD_ITC_32_MICRO_FRM (0x20<<16) |
| 5541 | +#define USB_CMD_ITC_64_MICRO_FRM (0x40<<16) |
| 5542 | +#define USB_CMD_ITC_BIT_POS (16) |
| 5543 | + |
| 5544 | +/* USB Status Register Bit Masks */ |
| 5545 | +#define USB_STS_INT (0x1<<0) |
| 5546 | +#define USB_STS_ERR (0x1<<1) |
| 5547 | +#define USB_STS_PORT_CHANGE (0x1<<2) |
| 5548 | +#define USB_STS_FRM_LST_ROLL (0x1<<3) |
| 5549 | +#define USB_STS_SYS_ERR (0x1<<4) |
| 5550 | +#define USB_STS_IAA (0x1<<5) |
| 5551 | +#define USB_STS_RESET_RECEIVED (0x1<<6) |
| 5552 | +#define USB_STS_SOF (0x1<<7) |
| 5553 | +#define USB_STS_DCSUSPEND (0x1<<8) |
| 5554 | +#define USB_STS_HC_HALTED (0x1<<12) |
| 5555 | +#define USB_STS_RCL (0x1<<13) |
| 5556 | +#define USB_STS_PERIODIC_SCHEDULE (0x1<<14) |
| 5557 | +#define USB_STS_ASYNC_SCHEDULE (0x1<<15) |
| 5558 | + |
| 5559 | +/* USB Interrupt Enable Register Bit Masks */ |
| 5560 | +#define USB_INTR_INT_EN (0x1<<0) |
| 5561 | +#define USB_INTR_ERR_INT_EN (0x1<<1) |
| 5562 | +#define USB_INTR_PC_DETECT_EN (0x1<<2) |
| 5563 | +#define USB_INTR_FRM_LST_ROLL_EN (0x1<<3) |
| 5564 | +#define USB_INTR_SYS_ERR_EN (0x1<<4) |
| 5565 | +#define USB_INTR_ASYN_ADV_EN (0x1<<5) |
| 5566 | +#define USB_INTR_RESET_EN (0x1<<6) |
| 5567 | +#define USB_INTR_SOF_EN (0x1<<7) |
| 5568 | +#define USB_INTR_DEVICE_SUSPEND (0x1<<8) |
| 5569 | + |
| 5570 | +/* Device Address bit masks */ |
| 5571 | +#define USB_DEVICE_ADDRESS_MASK (0x7F<<25) |
| 5572 | +#define USB_DEVICE_ADDRESS_BIT_POS (25) |
| 5573 | +/* PORTSC Register Bit Masks,Only one PORT in OTG mode*/ |
| 5574 | +#define PORTSC_CURRENT_CONNECT_STATUS (0x1<<0) |
| 5575 | +#define PORTSC_CONNECT_STATUS_CHANGE (0x1<<1) |
| 5576 | +#define PORTSC_PORT_ENABLE (0x1<<2) |
| 5577 | +#define PORTSC_PORT_EN_DIS_CHANGE (0x1<<3) |
| 5578 | +#define PORTSC_OVER_CURRENT_ACT (0x1<<4) |
| 5579 | +#define PORTSC_OVER_CUURENT_CHG (0x1<<5) |
| 5580 | +#define PORTSC_PORT_FORCE_RESUME (0x1<<6) |
| 5581 | +#define PORTSC_PORT_SUSPEND (0x1<<7) |
| 5582 | +#define PORTSC_PORT_RESET (0x1<<8) |
| 5583 | +#define PORTSC_LINE_STATUS_BITS (0x3<<10) |
| 5584 | +#define PORTSC_PORT_POWER (0x1<<12) |
| 5585 | +#define PORTSC_PORT_INDICTOR_CTRL (0x3<<14) |
| 5586 | +#define PORTSC_PORT_TEST_CTRL (0xF<<16) |
| 5587 | +#define PORTSC_WAKE_ON_CONNECT_EN (0x1<<20) |
| 5588 | +#define PORTSC_WAKE_ON_CONNECT_DIS (0x1<<21) |
| 5589 | +#define PORTSC_WAKE_ON_OVER_CURRENT (0x1<<22) |
| 5590 | +#define PORTSC_PHY_LOW_POWER_SPD (0x1<<23) |
| 5591 | +#define PORTSC_PORT_FORCE_FULL_SPEED (0x1<<24) |
| 5592 | +#define PORTSC_PORT_SPEED_MASK (0x3<<26) |
| 5593 | +#define PORTSC_TRANSCEIVER_WIDTH (0x1<<28) |
| 5594 | +#define PORTSC_PHY_TYPE_SEL (0x3<<30) |
| 5595 | +/* bit 11-10 are line status */ |
| 5596 | +#define PORTSC_LINE_STATUS_SE0 (0x0<<10) |
| 5597 | +#define PORTSC_LINE_STATUS_JSTATE (0x1<<10) |
| 5598 | +#define PORTSC_LINE_STATUS_KSTATE (0x2<<10) |
| 5599 | +#define PORTSC_LINE_STATUS_UNDEF (0x3<<10) |
| 5600 | +#define PORTSC_LINE_STATUS_BIT_POS (10) |
| 5601 | + |
| 5602 | +/* bit 15-14 are port indicator control */ |
| 5603 | +#define PORTSC_PIC_OFF (0x0<<14) |
| 5604 | +#define PORTSC_PIC_AMBER (0x1<<14) |
| 5605 | +#define PORTSC_PIC_GREEN (0x2<<14) |
| 5606 | +#define PORTSC_PIC_UNDEF (0x3<<14) |
| 5607 | +#define PORTSC_PIC_BIT_POS (14) |
| 5608 | + |
| 5609 | +/* bit 19-16 are port test control */ |
| 5610 | +#define PORTSC_PTC_DISABLE (0x0<<16) |
| 5611 | +#define PORTSC_PTC_JSTATE (0x1<<16) |
| 5612 | +#define PORTSC_PTC_KSTATE (0x2<<16) |
| 5613 | +#define PORTSC_PTC_SEQNAK (0x3<<16) |
| 5614 | +#define PORTSC_PTC_PACKET (0x4<<16) |
| 5615 | +#define PORTSC_PTC_FORCE_EN (0x5<<16) |
| 5616 | +#define PORTSC_PTC_BIT_POS (16) |
| 5617 | + |
| 5618 | +/* bit 27-26 are port speed */ |
| 5619 | +#define PORTSC_PORT_SPEED_FULL (0x0<<26) |
| 5620 | +#define PORTSC_PORT_SPEED_LOW (0x1<<26) |
| 5621 | +#define PORTSC_PORT_SPEED_HIGH (0x2<<26) |
| 5622 | +#define PORTSC_PORT_SPEED_UNDEF (0x3<<26) |
| 5623 | +#define PORTSC_SPEED_BIT_POS (26) |
| 5624 | + |
| 5625 | +/* bit 28 is parallel transceiver width for UTMI interface */ |
| 5626 | +#define PORTSC_PTW (0x1<<28) |
| 5627 | +#define PORTSC_PTW_8BIT (0x0<<28) |
| 5628 | +#define PORTSC_PTW_16BIT (0x1<<28) |
| 5629 | + |
| 5630 | +/* bit 31-30 are port transceiver select */ |
| 5631 | +#define PORTSC_PTS_UTMI (0x0<<30) |
| 5632 | +#define PORTSC_PTS_ULPI (0x2<<30) |
| 5633 | +#define PORTSC_PTS_FSLS_SERIAL (0x3<<30) |
| 5634 | +#define PORTSC_PTS_BIT_POS (30) |
| 5635 | + |
| 5636 | +#define PORTSC_W1C_BITS \ |
| 5637 | + (PORTSC_CONNECT_STATUS_CHANGE | \ |
| 5638 | + PORTSC_PORT_EN_DIS_CHANGE | \ |
| 5639 | + PORTSC_OVER_CUURENT_CHG) |
| 5640 | + |
| 5641 | +/* OTG Status Control Register Bit Masks */ |
| 5642 | +#define OTGSC_CTRL_VBUS_DISCHARGE (0x1<<0) |
| 5643 | +#define OTGSC_CTRL_VBUS_CHARGE (0x1<<1) |
| 5644 | +#define OTGSC_CTRL_OTG_TERMINATION (0x1<<3) |
| 5645 | +#define OTGSC_CTRL_DATA_PULSING (0x1<<4) |
| 5646 | +#define OTGSC_CTRL_ID_PULL_EN (0x1<<5) |
| 5647 | +#define OTGSC_HA_DATA_PULSE (0x1<<6) |
| 5648 | +#define OTGSC_HA_BA (0x1<<7) |
| 5649 | +#define OTGSC_STS_USB_ID (0x1<<8) |
| 5650 | +#define OTGSC_STS_A_VBUS_VALID (0x1<<9) |
| 5651 | +#define OTGSC_STS_A_SESSION_VALID (0x1<<10) |
| 5652 | +#define OTGSC_STS_B_SESSION_VALID (0x1<<11) |
| 5653 | +#define OTGSC_STS_B_SESSION_END (0x1<<12) |
| 5654 | +#define OTGSC_STS_1MS_TOGGLE (0x1<<13) |
| 5655 | +#define OTGSC_STS_DATA_PULSING (0x1<<14) |
| 5656 | +#define OTGSC_INTSTS_USB_ID (0x1<<16) |
| 5657 | +#define OTGSC_INTSTS_A_VBUS_VALID (0x1<<17) |
| 5658 | +#define OTGSC_INTSTS_A_SESSION_VALID (0x1<<18) |
| 5659 | +#define OTGSC_INTSTS_B_SESSION_VALID (0x1<<19) |
| 5660 | +#define OTGSC_INTSTS_B_SESSION_END (0x1<<20) |
| 5661 | +#define OTGSC_INTSTS_1MS (0x1<<21) |
| 5662 | +#define OTGSC_INTSTS_DATA_PULSING (0x1<<22) |
| 5663 | +#define OTGSC_INTR_USB_ID_EN (0x1<<24) |
| 5664 | +#define OTGSC_INTR_A_VBUS_VALID_EN (0x1<<25) |
| 5665 | +#define OTGSC_INTR_A_SESSION_VALID_EN (0x1<<26) |
| 5666 | +#define OTGSC_INTR_B_SESSION_VALID_EN (0x1<<27) |
| 5667 | +#define OTGSC_INTR_B_SESSION_END_EN (0x1<<28) |
| 5668 | +#define OTGSC_INTR_1MS_TIMER_EN (0x1<<29) |
| 5669 | +#define OTGSC_INTR_DATA_PULSING_EN (0x1<<30) |
| 5670 | +#define OTGSC_INTSTS_MASK (0x00ff0000) |
| 5671 | + |
| 5672 | +/* USB MODE Register Bit Masks */ |
| 5673 | +#define USB_MODE_CTRL_MODE_IDLE (0x0<<0) |
| 5674 | +#define USB_MODE_CTRL_MODE_DEVICE (0x2<<0) |
| 5675 | +#define USB_MODE_CTRL_MODE_HOST (0x3<<0) |
| 5676 | +#define USB_MODE_CTRL_MODE_RSV (0x1<<0) |
| 5677 | +#define USB_MODE_SETUP_LOCK_OFF (0x1<<3) |
| 5678 | +#define USB_MODE_STREAM_DISABLE (0x1<<4) |
| 5679 | +#define USB_MODE_ES (0x1<<2) /* (big) Endian Select */ |
| 5680 | + |
| 5681 | +#define MPC8349_OTG_IRQ (38) |
| 5682 | +#define CFG_IMMR_BASE (0xfe000000) |
| 5683 | +#define MPC83xx_USB_DR_BASE (CFG_IMMR_BASE + 0x23000) |
| 5684 | + |
| 5685 | +/* control Register Bit Masks */ |
| 5686 | +#define USB_CTRL_IOENB (0x1<<2) |
| 5687 | +#define USB_CTRL_ULPI_INT0EN (0x1<<0) |
| 5688 | + |
| 5689 | +/* BCSR5 */ |
| 5690 | +#define BCSR5_INT_USB (0x02) |
| 5691 | + |
| 5692 | +/* USB module clk cfg */ |
| 5693 | +#define SCCR_OFFS (0xA08) |
| 5694 | +#define SCCR_USB_CLK_DISABLE (0x00000000) /* USB clk disable */ |
| 5695 | +#define SCCR_USB_MPHCM_11 (0x00c00000) |
| 5696 | +#define SCCR_USB_MPHCM_01 (0x00400000) |
| 5697 | +#define SCCR_USB_MPHCM_10 (0x00800000) |
| 5698 | +#define SCCR_USB_DRCM_11 (0x00300000) |
| 5699 | +#define SCCR_USB_DRCM_01 (0x00100000) |
| 5700 | +#define SCCR_USB_DRCM_10 (0x00200000) |
| 5701 | + |
| 5702 | +#define SICRL_OFFS (0x114) |
| 5703 | +#define SICRL_USB0 (0x40000000) |
| 5704 | +#define SICRL_USB1 (0x20000000) |
| 5705 | + |
| 5706 | +#define SICRH_OFFS (0x118) |
| 5707 | +#define SICRH_USB_UTMI (0x00020000) |
| 5708 | + |
| 5709 | +/* OTG interrupt enable bit masks */ |
| 5710 | +#define OTGSC_INTERRUPT_ENABLE_BITS_MASK \ |
| 5711 | + (OTGSC_INTR_USB_ID_EN | \ |
| 5712 | + OTGSC_INTR_1MS_TIMER_EN | \ |
| 5713 | + OTGSC_INTR_A_VBUS_VALID_EN | \ |
| 5714 | + OTGSC_INTR_A_SESSION_VALID_EN | \ |
| 5715 | + OTGSC_INTR_B_SESSION_VALID_EN | \ |
| 5716 | + OTGSC_INTR_B_SESSION_END_EN | \ |
| 5717 | + OTGSC_INTR_DATA_PULSING_EN) |
| 5718 | + |
| 5719 | +/* OTG interrupt status bit masks */ |
| 5720 | +#define OTGSC_INTERRUPT_STATUS_BITS_MASK \ |
| 5721 | + (OTGSC_INTSTS_USB_ID | \ |
| 5722 | + OTGSC_INTR_1MS_TIMER_EN | \ |
| 5723 | + OTGSC_INTSTS_A_VBUS_VALID | \ |
| 5724 | + OTGSC_INTSTS_A_SESSION_VALID | \ |
| 5725 | + OTGSC_INTSTS_B_SESSION_VALID | \ |
| 5726 | + OTGSC_INTSTS_B_SESSION_END | \ |
| 5727 | + OTGSC_INTSTS_DATA_PULSING) |
| 5728 | + |
| 5729 | +/* |
| 5730 | + * A-DEVICE timing constants |
| 5731 | + */ |
| 5732 | + |
| 5733 | +/* Wait for VBUS Rise */ |
| 5734 | +#define TA_WAIT_VRISE (100) /* a_wait_vrise 100 ms, section: 6.6.5.1 */ |
| 5735 | + |
| 5736 | +/* Wait for B-Connect */ |
| 5737 | +#define TA_WAIT_BCON (10000) /* a_wait_bcon > 1 sec, section: 6.6.5.2 |
| 5738 | + * This is only used to get out of |
| 5739 | + * OTG_STATE_A_WAIT_BCON state if there was |
| 5740 | + * no connection for these many milliseconds |
| 5741 | + */ |
| 5742 | + |
| 5743 | +/* A-Idle to B-Disconnect */ |
| 5744 | +/* It is necessary for this timer to be more than 750 ms because of a bug in OPT |
| 5745 | + * test 5.4 in which B OPT disconnects after 750 ms instead of 75ms as stated |
| 5746 | + * in the test description |
| 5747 | + */ |
| 5748 | +#define TA_AIDL_BDIS (5000) /* a_suspend minimum 200 ms, section: 6.6.5.3 */ |
| 5749 | + |
| 5750 | +/* B-Idle to A-Disconnect */ |
| 5751 | +#define TA_BIDL_ADIS (12) /* 3 to 200 ms */ |
| 5752 | + |
| 5753 | +/* B-device timing constants */ |
| 5754 | + |
| 5755 | + |
| 5756 | +/* Data-Line Pulse Time*/ |
| 5757 | +#define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms, section:5.3.3 */ |
| 5758 | +#define TB_DATA_PLS_MIN (5) /* minimum 5 ms */ |
| 5759 | +#define TB_DATA_PLS_MAX (10) /* maximum 10 ms */ |
| 5760 | + |
| 5761 | +/* SRP Initiate Time */ |
| 5762 | +#define TB_SRP_INIT (100) /* b_srp_init,maximum 100 ms, section:5.3.8 */ |
| 5763 | + |
| 5764 | +/* SRP Fail Time */ |
| 5765 | +#define TB_SRP_FAIL (7000) /* b_srp_init,Fail time 5~30s, section:6.8.2.2*/ |
| 5766 | + |
| 5767 | +/* SRP result wait time */ |
| 5768 | +#define TB_SRP_WAIT (60) |
| 5769 | + |
| 5770 | +/* VBus time */ |
| 5771 | +#define TB_VBUS_PLS (30) /* time to keep vbus pulsing asserted */ |
| 5772 | + |
| 5773 | +/* Discharge time */ |
| 5774 | +/* This time should be less than 10ms. It varies from system to system. */ |
| 5775 | +#define TB_VBUS_DSCHRG (8) |
| 5776 | + |
| 5777 | +/* A-SE0 to B-Reset */ |
| 5778 | +#define TB_ASE0_BRST (20) /* b_wait_acon, mini 3.125 ms,section:6.8.2.4 */ |
| 5779 | + |
| 5780 | +/* A bus suspend timer before we can switch to b_wait_aconn */ |
| 5781 | +#define TB_A_SUSPEND (7) |
| 5782 | +#define TB_BUS_RESUME (12) |
| 5783 | + |
| 5784 | +/* SE0 Time Before SRP */ |
| 5785 | +#define TB_SE0_SRP (2) /* b_idle,minimum 2 ms, section:5.3.2 */ |
| 5786 | + |
| 5787 | + |
| 5788 | +#define SET_OTG_STATE(otg_ptr, newstate) ((otg_ptr)->state = newstate) |
| 5789 | + |
| 5790 | +struct usb_dr_mmap { |
| 5791 | + /* Capability register */ |
| 5792 | + u8 res1[256]; |
| 5793 | + u16 caplength; /* Capability Register Length */ |
| 5794 | + u16 hciversion; /* Host Controller Interface Version */ |
| 5795 | + u32 hcsparams; /* Host Controller Structual Parameters */ |
| 5796 | + u32 hccparams; /* Host Controller Capability Parameters */ |
| 5797 | + u8 res2[20]; |
| 5798 | + u32 dciversion; /* Device Controller Interface Version */ |
| 5799 | + u32 dccparams; /* Device Controller Capability Parameters */ |
| 5800 | + u8 res3[24]; |
| 5801 | + /* Operation register */ |
| 5802 | + u32 usbcmd; /* USB Command Register */ |
| 5803 | + u32 usbsts; /* USB Status Register */ |
| 5804 | + u32 usbintr; /* USB Interrupt Enable Register */ |
| 5805 | + u32 frindex; /* Frame Index Register */ |
| 5806 | + u8 res4[4]; |
| 5807 | + u32 deviceaddr; /* Device Address */ |
| 5808 | + u32 endpointlistaddr; /* Endpoint List Address Register */ |
| 5809 | + u8 res5[4]; |
| 5810 | + u32 burstsize; /* Master Interface Data Burst Size Register */ |
| 5811 | + u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ |
| 5812 | + u8 res6[8]; |
| 5813 | + u32 ulpiview; /* ULPI register access */ |
| 5814 | + u8 res7[12]; |
| 5815 | + u32 configflag; /* Configure Flag Register */ |
| 5816 | + u32 portsc; /* Port 1 Status and Control Register */ |
| 5817 | + u8 res8[28]; |
| 5818 | + u32 otgsc; /* On-The-Go Status and Control */ |
| 5819 | + u32 usbmode; /* USB Mode Register */ |
| 5820 | + u32 endptsetupstat; /* Endpoint Setup Status Register */ |
| 5821 | + u32 endpointprime; /* Endpoint Initialization Register */ |
| 5822 | + u32 endptflush; /* Endpoint Flush Register */ |
| 5823 | + u32 endptstatus; /* Endpoint Status Register */ |
| 5824 | + u32 endptcomplete; /* Endpoint Complete Register */ |
| 5825 | + u32 endptctrl[6]; /* Endpoint Control Registers */ |
| 5826 | + u8 res9[552]; |
| 5827 | + u32 snoop1; |
| 5828 | + u32 snoop2; |
| 5829 | + u32 age_cnt_thresh; /* Age Count Threshold Register */ |
| 5830 | + u32 pri_ctrl; /* Priority Control Register */ |
| 5831 | + u32 si_ctrl; /* System Interface Control Register */ |
| 5832 | + u8 res10[236]; |
| 5833 | + u32 control; /* General Purpose Control Register */ |
| 5834 | +}; |
| 5835 | + |
| 5836 | + |
| 5837 | +struct fsl_otg_timer { |
| 5838 | + unsigned long expires; /* Number of count increase to timeout */ |
| 5839 | + unsigned long count; /* Tick counter */ |
| 5840 | + void (*function)(unsigned long); /* Timeout function */ |
| 5841 | + unsigned long data; /* Data passed to function */ |
| 5842 | + struct list_head list; |
| 5843 | +}; |
| 5844 | + |
| 5845 | +static inline struct fsl_otg_timer *otg_timer_initializer |
| 5846 | +(void (*function)(unsigned long), unsigned long expires, unsigned long data) |
| 5847 | +{ |
| 5848 | + struct fsl_otg_timer *timer; |
| 5849 | + timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL); |
| 5850 | + if (timer == NULL) |
| 5851 | + return NULL; |
| 5852 | + timer->function = function; |
| 5853 | + timer->expires = expires; |
| 5854 | + timer->data = data; |
| 5855 | + return timer; |
| 5856 | +} |
| 5857 | + |
| 5858 | +struct fsl_otg { |
| 5859 | + struct otg_transceiver otg; |
| 5860 | + struct otg_fsm fsm; |
| 5861 | + struct usb_dr_mmap __iomem *dr_mem_map; |
| 5862 | + struct delayed_work otg_event; |
| 5863 | + |
| 5864 | + /* used for usb host */ |
| 5865 | + struct work_struct work_wq; |
| 5866 | + u8 host_working; |
| 5867 | + |
| 5868 | + int irq; |
| 5869 | +}; |
| 5870 | + |
| 5871 | +struct fsl_otg_config { |
| 5872 | + u8 otg_port; |
| 5873 | +}; |
| 5874 | + |
| 5875 | +/*For SRP and HNP handle*/ |
| 5876 | +#define FSL_OTG_MAJOR 66 |
| 5877 | +#define FSL_OTG_NAME "fsl-usb2-otg" |
| 5878 | +/*Command to OTG driver(ioctl)*/ |
| 5879 | +#define OTG_IOCTL_MAGIC FSL_OTG_MAJOR |
| 5880 | +/*if otg work as host,it should return 1,otherwise it return 0*/ |
| 5881 | +#define GET_OTG_STATUS _IOR(OTG_IOCTL_MAGIC, 1, int) |
| 5882 | +#define SET_A_SUSPEND_REQ _IOW(OTG_IOCTL_MAGIC, 2, int) |
| 5883 | +#define SET_A_BUS_DROP _IOW(OTG_IOCTL_MAGIC, 3, int) |
| 5884 | +#define SET_A_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 4, int) |
| 5885 | +#define SET_B_BUS_REQ _IOW(OTG_IOCTL_MAGIC, 5, int) |
| 5886 | +#define GET_A_SUSPEND_REQ _IOR(OTG_IOCTL_MAGIC, 6, int) |
| 5887 | +#define GET_A_BUS_DROP _IOR(OTG_IOCTL_MAGIC, 7, int) |
| 5888 | +#define GET_A_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 8, int) |
| 5889 | +#define GET_B_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 9, int) |
| 5890 | + |
| 5891 | +extern const char *state_string(enum usb_otg_state state); |
| 5892 | +extern int otg_set_resources(struct resource *resources); |
| 5893 | +/* prototype declaration */ |
| 5894 | +extern void fsl_otg_add_timer(void *timer); |
| 5895 | +extern void fsl_otg_del_timer(void *timer); |
| 5896 | --- /dev/null |
| 5897 | +++ b/drivers/usb/otg/otg_fsm.c |
| 5898 | @@ -0,0 +1,371 @@ |
| 5899 | +/* OTG Finite State Machine from OTG spec |
| 5900 | + * |
| 5901 | + * Copyright 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 5902 | + * |
| 5903 | + * Author: Li Yang <LeoLi@freescale.com> |
| 5904 | + * Jerry Huang <Chang-Ming.Huang@freescale.com> |
| 5905 | + * |
| 5906 | + * This program is free software; you can redistribute it and/or modify it |
| 5907 | + * under the terms of the GNU General Public License as published by the |
| 5908 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 5909 | + * option) any later version. |
| 5910 | + * |
| 5911 | + * This program is distributed in the hope that it will be useful, but |
| 5912 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 5913 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 5914 | + * General Public License for more details. |
| 5915 | + * |
| 5916 | + * You should have received a copy of the GNU General Public License along |
| 5917 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 5918 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 5919 | + */ |
| 5920 | + |
| 5921 | +#include <linux/kernel.h> |
| 5922 | +#include <linux/types.h> |
| 5923 | +#include <linux/usb/otg.h> |
| 5924 | +#include <linux/spinlock.h> |
| 5925 | +#include <linux/delay.h> |
| 5926 | +#include <linux/usb.h> |
| 5927 | +#include <linux/usb/gadget.h> |
| 5928 | + |
| 5929 | +#include <linux/types.h> |
| 5930 | +#include "otg_fsm.h" |
| 5931 | + |
| 5932 | + |
| 5933 | +/* Defined by device specific driver, for different timer implementation */ |
| 5934 | +extern void *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, |
| 5935 | + *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr, *a_wait_enum_tmr; |
| 5936 | + |
| 5937 | +const char *state_string(enum usb_otg_state state) |
| 5938 | +{ |
| 5939 | + switch (state) { |
| 5940 | + case OTG_STATE_A_IDLE: return "a_idle"; |
| 5941 | + case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; |
| 5942 | + case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; |
| 5943 | + case OTG_STATE_A_HOST: return "a_host"; |
| 5944 | + case OTG_STATE_A_SUSPEND: return "a_suspend"; |
| 5945 | + case OTG_STATE_A_PERIPHERAL: return "a_peripheral"; |
| 5946 | + case OTG_STATE_A_WAIT_VFALL: return "a_wait_vfall"; |
| 5947 | + case OTG_STATE_A_VBUS_ERR: return "a_vbus_err"; |
| 5948 | + case OTG_STATE_B_IDLE: return "b_idle"; |
| 5949 | + case OTG_STATE_B_SRP_INIT: return "b_srp_init"; |
| 5950 | + case OTG_STATE_B_PERIPHERAL: return "b_peripheral"; |
| 5951 | + case OTG_STATE_B_WAIT_ACON: return "b_wait_acon"; |
| 5952 | + case OTG_STATE_B_HOST: return "b_host"; |
| 5953 | + default: return "UNDEFINED"; |
| 5954 | + } |
| 5955 | +} |
| 5956 | + |
| 5957 | +/* Change USB protocol when there is a protocol change */ |
| 5958 | +static int otg_set_protocol(struct otg_fsm *fsm, int protocol) |
| 5959 | +{ |
| 5960 | + int ret = 0; |
| 5961 | + |
| 5962 | + if (fsm->protocol != protocol) { |
| 5963 | + VDBG("Changing role fsm->protocol= %d; new protocol= %d\n", |
| 5964 | + fsm->protocol, protocol); |
| 5965 | + /* stop old protocol */ |
| 5966 | + if (fsm->protocol == PROTO_HOST) |
| 5967 | + ret = fsm->ops->start_host(fsm, 0); |
| 5968 | + else if (fsm->protocol == PROTO_GADGET) |
| 5969 | + ret = fsm->ops->start_gadget(fsm, 0); |
| 5970 | + if (ret) |
| 5971 | + return ret; |
| 5972 | + |
| 5973 | + /* start new protocol */ |
| 5974 | + if (protocol == PROTO_HOST) |
| 5975 | + ret = fsm->ops->start_host(fsm, 1); |
| 5976 | + else if (protocol == PROTO_GADGET) |
| 5977 | + ret = fsm->ops->start_gadget(fsm, 1); |
| 5978 | + if (ret) |
| 5979 | + return ret; |
| 5980 | + |
| 5981 | + fsm->protocol = protocol; |
| 5982 | + return 0; |
| 5983 | + } |
| 5984 | + |
| 5985 | + return 0; |
| 5986 | +} |
| 5987 | + |
| 5988 | +static int state_changed; |
| 5989 | + |
| 5990 | +/* Called when leaving a state. Do state clean up jobs here */ |
| 5991 | +void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) |
| 5992 | +{ |
| 5993 | + switch (old_state) { |
| 5994 | + case OTG_STATE_B_IDLE: |
| 5995 | + otg_del_timer(fsm, b_se0_srp_tmr); |
| 5996 | + fsm->b_se0_srp = 0; |
| 5997 | + break; |
| 5998 | + case OTG_STATE_B_SRP_INIT: |
| 5999 | + fsm->b_srp_done = 0; |
| 6000 | + break; |
| 6001 | + case OTG_STATE_B_PERIPHERAL: |
| 6002 | + break; |
| 6003 | + case OTG_STATE_B_WAIT_ACON: |
| 6004 | + otg_del_timer(fsm, b_ase0_brst_tmr); |
| 6005 | + fsm->b_ase0_brst_tmout = 0; |
| 6006 | + break; |
| 6007 | + case OTG_STATE_B_HOST: |
| 6008 | + break; |
| 6009 | + case OTG_STATE_A_IDLE: |
| 6010 | + break; |
| 6011 | + case OTG_STATE_A_WAIT_VRISE: |
| 6012 | + otg_del_timer(fsm, a_wait_vrise_tmr); |
| 6013 | + fsm->a_wait_vrise_tmout = 0; |
| 6014 | + break; |
| 6015 | + case OTG_STATE_A_WAIT_BCON: |
| 6016 | + otg_del_timer(fsm, a_wait_bcon_tmr); |
| 6017 | + fsm->a_wait_bcon_tmout = 0; |
| 6018 | + break; |
| 6019 | + case OTG_STATE_A_HOST: |
| 6020 | + otg_del_timer(fsm, a_wait_enum_tmr); |
| 6021 | + break; |
| 6022 | + case OTG_STATE_A_SUSPEND: |
| 6023 | + otg_del_timer(fsm, a_aidl_bdis_tmr); |
| 6024 | + fsm->a_aidl_bdis_tmout = 0; |
| 6025 | + fsm->a_suspend_req = 0; |
| 6026 | + break; |
| 6027 | + case OTG_STATE_A_PERIPHERAL: |
| 6028 | + break; |
| 6029 | + case OTG_STATE_A_WAIT_VFALL: |
| 6030 | + otg_del_timer(fsm, a_wait_vrise_tmr); |
| 6031 | + break; |
| 6032 | + case OTG_STATE_A_VBUS_ERR: |
| 6033 | + break; |
| 6034 | + default: |
| 6035 | + break; |
| 6036 | + } |
| 6037 | +} |
| 6038 | + |
| 6039 | +/* Called when entering a state */ |
| 6040 | +int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) |
| 6041 | +{ |
| 6042 | + state_changed = 1; |
| 6043 | + if (fsm->transceiver->state == new_state) |
| 6044 | + return 0; |
| 6045 | + VDBG("Set state: %s\n", state_string(new_state)); |
| 6046 | + otg_leave_state(fsm, fsm->transceiver->state); |
| 6047 | + switch (new_state) { |
| 6048 | + case OTG_STATE_B_IDLE: |
| 6049 | + otg_drv_vbus(fsm, 0); |
| 6050 | + otg_chrg_vbus(fsm, 0); |
| 6051 | + otg_loc_conn(fsm, 0); |
| 6052 | + otg_loc_sof(fsm, 0); |
| 6053 | + otg_set_protocol(fsm, PROTO_UNDEF); |
| 6054 | + otg_add_timer(fsm, b_se0_srp_tmr); |
| 6055 | + break; |
| 6056 | + case OTG_STATE_B_SRP_INIT: |
| 6057 | + otg_start_pulse(fsm); |
| 6058 | + otg_loc_sof(fsm, 0); |
| 6059 | + otg_set_protocol(fsm, PROTO_UNDEF); |
| 6060 | + otg_add_timer(fsm, b_srp_fail_tmr); |
| 6061 | + break; |
| 6062 | + case OTG_STATE_B_PERIPHERAL: |
| 6063 | + otg_chrg_vbus(fsm, 0); |
| 6064 | + otg_loc_conn(fsm, 1); |
| 6065 | + otg_loc_sof(fsm, 0); |
| 6066 | + otg_set_protocol(fsm, PROTO_GADGET); |
| 6067 | + break; |
| 6068 | + case OTG_STATE_B_WAIT_ACON: |
| 6069 | + otg_chrg_vbus(fsm, 0); |
| 6070 | + otg_loc_conn(fsm, 0); |
| 6071 | + otg_loc_sof(fsm, 0); |
| 6072 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6073 | + otg_add_timer(fsm, b_ase0_brst_tmr); |
| 6074 | + fsm->a_bus_suspend = 0; |
| 6075 | + break; |
| 6076 | + case OTG_STATE_B_HOST: |
| 6077 | + otg_chrg_vbus(fsm, 0); |
| 6078 | + otg_loc_conn(fsm, 0); |
| 6079 | + otg_loc_sof(fsm, 1); |
| 6080 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6081 | + usb_bus_start_enum(fsm->transceiver->host, |
| 6082 | + fsm->transceiver->host->otg_port); |
| 6083 | + break; |
| 6084 | + case OTG_STATE_A_IDLE: |
| 6085 | + otg_drv_vbus(fsm, 0); |
| 6086 | + otg_chrg_vbus(fsm, 0); |
| 6087 | + otg_loc_conn(fsm, 0); |
| 6088 | + otg_loc_sof(fsm, 0); |
| 6089 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6090 | + break; |
| 6091 | + case OTG_STATE_A_WAIT_VRISE: |
| 6092 | + otg_drv_vbus(fsm, 1); |
| 6093 | + otg_loc_conn(fsm, 0); |
| 6094 | + otg_loc_sof(fsm, 0); |
| 6095 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6096 | + otg_add_timer(fsm, a_wait_vrise_tmr); |
| 6097 | + break; |
| 6098 | + case OTG_STATE_A_WAIT_BCON: |
| 6099 | + otg_drv_vbus(fsm, 1); |
| 6100 | + otg_loc_conn(fsm, 0); |
| 6101 | + otg_loc_sof(fsm, 0); |
| 6102 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6103 | + otg_add_timer(fsm, a_wait_bcon_tmr); |
| 6104 | + break; |
| 6105 | + case OTG_STATE_A_HOST: |
| 6106 | + otg_drv_vbus(fsm, 1); |
| 6107 | + otg_loc_conn(fsm, 0); |
| 6108 | + otg_loc_sof(fsm, 1); |
| 6109 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6110 | + /* When HNP is triggered while a_bus_req = 0, a_host will |
| 6111 | + * suspend too fast to complete a_set_b_hnp_en */ |
| 6112 | + if (!fsm->a_bus_req || fsm->a_suspend_req) |
| 6113 | + otg_add_timer(fsm, a_wait_enum_tmr); |
| 6114 | + break; |
| 6115 | + case OTG_STATE_A_SUSPEND: |
| 6116 | + otg_drv_vbus(fsm, 1); |
| 6117 | + otg_loc_conn(fsm, 0); |
| 6118 | + otg_loc_sof(fsm, 0); |
| 6119 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6120 | + otg_add_timer(fsm, a_aidl_bdis_tmr); |
| 6121 | + |
| 6122 | + break; |
| 6123 | + case OTG_STATE_A_PERIPHERAL: |
| 6124 | + otg_loc_conn(fsm, 1); |
| 6125 | + otg_loc_sof(fsm, 0); |
| 6126 | + otg_set_protocol(fsm, PROTO_GADGET); |
| 6127 | + otg_drv_vbus(fsm, 1); |
| 6128 | + break; |
| 6129 | + case OTG_STATE_A_WAIT_VFALL: |
| 6130 | + otg_drv_vbus(fsm, 0); |
| 6131 | + otg_loc_conn(fsm, 0); |
| 6132 | + otg_loc_sof(fsm, 0); |
| 6133 | + otg_set_protocol(fsm, PROTO_HOST); |
| 6134 | + break; |
| 6135 | + case OTG_STATE_A_VBUS_ERR: |
| 6136 | + otg_drv_vbus(fsm, 0); |
| 6137 | + otg_loc_conn(fsm, 0); |
| 6138 | + otg_loc_sof(fsm, 0); |
| 6139 | + otg_set_protocol(fsm, PROTO_UNDEF); |
| 6140 | + break; |
| 6141 | + default: |
| 6142 | + break; |
| 6143 | + } |
| 6144 | + |
| 6145 | + fsm->transceiver->state = new_state; |
| 6146 | + return 0; |
| 6147 | +} |
| 6148 | + |
| 6149 | +/* State change judgement */ |
| 6150 | +int otg_statemachine(struct otg_fsm *fsm) |
| 6151 | +{ |
| 6152 | + enum usb_otg_state state; |
| 6153 | + unsigned long flags; |
| 6154 | + |
| 6155 | + spin_lock_irqsave(&fsm->lock, flags); |
| 6156 | + |
| 6157 | + state = fsm->transceiver->state; |
| 6158 | + state_changed = 0; |
| 6159 | + /* State machine state change judgement */ |
| 6160 | + |
| 6161 | + switch (state) { |
| 6162 | + case OTG_STATE_UNDEFINED: |
| 6163 | + VDBG("fsm->id = %d\n", fsm->id); |
| 6164 | + if (fsm->id) |
| 6165 | + otg_set_state(fsm, OTG_STATE_B_IDLE); |
| 6166 | + else |
| 6167 | + otg_set_state(fsm, OTG_STATE_A_IDLE); |
| 6168 | + break; |
| 6169 | + case OTG_STATE_B_IDLE: |
| 6170 | + if (!fsm->id) |
| 6171 | + otg_set_state(fsm, OTG_STATE_A_IDLE); |
| 6172 | + else if (fsm->b_sess_vld && fsm->transceiver->gadget) |
| 6173 | + otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); |
| 6174 | + else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) |
| 6175 | + otg_set_state(fsm, OTG_STATE_B_SRP_INIT); |
| 6176 | + break; |
| 6177 | + case OTG_STATE_B_SRP_INIT: |
| 6178 | + if (!fsm->id || fsm->b_srp_done) |
| 6179 | + otg_set_state(fsm, OTG_STATE_B_IDLE); |
| 6180 | + break; |
| 6181 | + case OTG_STATE_B_PERIPHERAL: |
| 6182 | + if (!fsm->id || !fsm->b_sess_vld) |
| 6183 | + otg_set_state(fsm, OTG_STATE_B_IDLE); |
| 6184 | + else if (fsm->b_bus_req && fsm->transceiver-> |
| 6185 | + gadget->b_hnp_enable && fsm->a_bus_suspend) |
| 6186 | + otg_set_state(fsm, OTG_STATE_B_WAIT_ACON); |
| 6187 | + break; |
| 6188 | + case OTG_STATE_B_WAIT_ACON: |
| 6189 | + if (fsm->a_conn) |
| 6190 | + otg_set_state(fsm, OTG_STATE_B_HOST); |
| 6191 | + else if (!fsm->id || !fsm->b_sess_vld) |
| 6192 | + otg_set_state(fsm, OTG_STATE_B_IDLE); |
| 6193 | + else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) { |
| 6194 | + fsm->b_ase0_brst_tmout = 0; |
| 6195 | + otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); |
| 6196 | + } |
| 6197 | + break; |
| 6198 | + case OTG_STATE_B_HOST: |
| 6199 | + if (!fsm->id || !fsm->b_sess_vld) |
| 6200 | + otg_set_state(fsm, OTG_STATE_B_IDLE); |
| 6201 | + else if (!fsm->b_bus_req || !fsm->a_conn) |
| 6202 | + otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); |
| 6203 | + break; |
| 6204 | + case OTG_STATE_A_IDLE: |
| 6205 | + if (fsm->id) |
| 6206 | + otg_set_state(fsm, OTG_STATE_B_IDLE); |
| 6207 | + else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det)) |
| 6208 | + otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); |
| 6209 | + break; |
| 6210 | + case OTG_STATE_A_WAIT_VRISE: |
| 6211 | + if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld || |
| 6212 | + fsm->a_wait_vrise_tmout) { |
| 6213 | + otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); |
| 6214 | + } |
| 6215 | + break; |
| 6216 | + case OTG_STATE_A_WAIT_BCON: |
| 6217 | + if (!fsm->a_vbus_vld) |
| 6218 | + otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); |
| 6219 | + else if (fsm->b_conn) |
| 6220 | + otg_set_state(fsm, OTG_STATE_A_HOST); |
| 6221 | + else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout) |
| 6222 | + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); |
| 6223 | + break; |
| 6224 | + case OTG_STATE_A_HOST: |
| 6225 | + if ((!fsm->a_bus_req || fsm->a_suspend_req) && |
| 6226 | + fsm->transceiver->host->b_hnp_enable) |
| 6227 | + otg_set_state(fsm, OTG_STATE_A_SUSPEND); |
| 6228 | + else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) |
| 6229 | + otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); |
| 6230 | + else if (!fsm->a_vbus_vld) |
| 6231 | + otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); |
| 6232 | + break; |
| 6233 | + case OTG_STATE_A_SUSPEND: |
| 6234 | + if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable) |
| 6235 | + otg_set_state(fsm, OTG_STATE_A_PERIPHERAL); |
| 6236 | + else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable) |
| 6237 | + otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); |
| 6238 | + else if (fsm->a_bus_req || fsm->b_bus_resume) |
| 6239 | + otg_set_state(fsm, OTG_STATE_A_HOST); |
| 6240 | + else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout) |
| 6241 | + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); |
| 6242 | + else if (!fsm->a_vbus_vld) |
| 6243 | + otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); |
| 6244 | + break; |
| 6245 | + case OTG_STATE_A_PERIPHERAL: |
| 6246 | + if (fsm->id || fsm->a_bus_drop) |
| 6247 | + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); |
| 6248 | + else if (fsm->b_bus_suspend) |
| 6249 | + otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); |
| 6250 | + else if (!fsm->a_vbus_vld) |
| 6251 | + otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); |
| 6252 | + break; |
| 6253 | + case OTG_STATE_A_WAIT_VFALL: |
| 6254 | + if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld && |
| 6255 | + !fsm->b_conn)) |
| 6256 | + otg_set_state(fsm, OTG_STATE_A_IDLE); |
| 6257 | + break; |
| 6258 | + case OTG_STATE_A_VBUS_ERR: |
| 6259 | + if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err) |
| 6260 | + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); |
| 6261 | + break; |
| 6262 | + default: |
| 6263 | + break; |
| 6264 | + } |
| 6265 | + spin_unlock_irqrestore(&fsm->lock, flags); |
| 6266 | + |
| 6267 | + /*VDBG("quit statemachine, changed = %d\n", state_changed); */ |
| 6268 | + return state_changed; |
| 6269 | +} |
| 6270 | --- /dev/null |
| 6271 | +++ b/drivers/usb/otg/otg_fsm.h |
| 6272 | @@ -0,0 +1,151 @@ |
| 6273 | +/* Copyright 2006-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 6274 | + * |
| 6275 | + * This program is free software; you can redistribute it and/or modify it |
| 6276 | + * under the terms of the GNU General Public License as published by the |
| 6277 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 6278 | + * option) any later version. |
| 6279 | + * |
| 6280 | + * This program is distributed in the hope that it will be useful, but |
| 6281 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 6282 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 6283 | + * General Public License for more details. |
| 6284 | + * |
| 6285 | + * You should have received a copy of the GNU General Public License along |
| 6286 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 6287 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 6288 | + */ |
| 6289 | + |
| 6290 | +#if 0 |
| 6291 | +#define DEBUG 1 |
| 6292 | +#define VERBOSE 1 |
| 6293 | +#endif |
| 6294 | + |
| 6295 | +#ifdef DEBUG |
| 6296 | +#define DBG(fmt, args...) printk(KERN_DEBUG "[%s] " fmt , \ |
| 6297 | + __func__, ## args) |
| 6298 | +#else |
| 6299 | +#define DBG(fmt, args...) do {} while (0) |
| 6300 | +#endif |
| 6301 | + |
| 6302 | +#ifdef VERBOSE |
| 6303 | +#define VDBG DBG |
| 6304 | +#else |
| 6305 | +#define VDBG(stuff...) do {} while (0) |
| 6306 | +#endif |
| 6307 | + |
| 6308 | +#ifdef VERBOSE |
| 6309 | +#define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) |
| 6310 | +#else |
| 6311 | +#define MPC_LOC do {} while (0) |
| 6312 | +#endif |
| 6313 | + |
| 6314 | +#define PROTO_UNDEF (0) |
| 6315 | +#define PROTO_HOST (1) |
| 6316 | +#define PROTO_GADGET (2) |
| 6317 | + |
| 6318 | +/* OTG state machine according to the OTG spec */ |
| 6319 | +struct otg_fsm { |
| 6320 | + /* Input */ |
| 6321 | + int a_bus_resume; |
| 6322 | + int a_bus_suspend; |
| 6323 | + int a_conn; |
| 6324 | + int a_sess_vld; |
| 6325 | + int a_srp_det; |
| 6326 | + int a_vbus_vld; |
| 6327 | + int b_bus_resume; |
| 6328 | + int b_bus_suspend; |
| 6329 | + int b_conn; |
| 6330 | + int b_se0_srp; |
| 6331 | + int b_sess_end; |
| 6332 | + int b_sess_vld; |
| 6333 | + int id; |
| 6334 | + |
| 6335 | + /* Internal variables */ |
| 6336 | + int a_set_b_hnp_en; |
| 6337 | + int b_srp_done; |
| 6338 | + int b_hnp_enable; |
| 6339 | + |
| 6340 | + /* Timeout indicator for timers */ |
| 6341 | + int a_wait_vrise_tmout; |
| 6342 | + int a_wait_bcon_tmout; |
| 6343 | + int a_aidl_bdis_tmout; |
| 6344 | + int b_ase0_brst_tmout; |
| 6345 | + |
| 6346 | + /* Informative variables */ |
| 6347 | + int a_bus_drop; |
| 6348 | + int a_bus_req; |
| 6349 | + int a_clr_err; |
| 6350 | + int a_suspend_req; |
| 6351 | + int b_bus_req; |
| 6352 | + |
| 6353 | + /* Output */ |
| 6354 | + int drv_vbus; |
| 6355 | + int loc_conn; |
| 6356 | + int loc_sof; |
| 6357 | + |
| 6358 | + struct otg_fsm_ops *ops; |
| 6359 | + struct otg_transceiver *transceiver; |
| 6360 | + |
| 6361 | + /* Current usb protocol used: 0:undefine; 1:host; 2:client */ |
| 6362 | + int protocol; |
| 6363 | + spinlock_t lock; |
| 6364 | +}; |
| 6365 | + |
| 6366 | +struct otg_fsm_ops { |
| 6367 | + void (*chrg_vbus)(int on); |
| 6368 | + void (*drv_vbus)(int on); |
| 6369 | + void (*loc_conn)(int on); |
| 6370 | + void (*loc_sof)(int on); |
| 6371 | + void (*start_pulse)(void); |
| 6372 | + void (*add_timer)(void *timer); |
| 6373 | + void (*del_timer)(void *timer); |
| 6374 | + int (*start_host)(struct otg_fsm *fsm, int on); |
| 6375 | + int (*start_gadget)(struct otg_fsm *fsm, int on); |
| 6376 | +}; |
| 6377 | + |
| 6378 | + |
| 6379 | +static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on) |
| 6380 | +{ |
| 6381 | + fsm->ops->chrg_vbus(on); |
| 6382 | +} |
| 6383 | + |
| 6384 | +static inline void otg_drv_vbus(struct otg_fsm *fsm, int on) |
| 6385 | +{ |
| 6386 | + if (fsm->drv_vbus != on) { |
| 6387 | + fsm->drv_vbus = on; |
| 6388 | + fsm->ops->drv_vbus(on); |
| 6389 | + } |
| 6390 | +} |
| 6391 | + |
| 6392 | +static inline void otg_loc_conn(struct otg_fsm *fsm, int on) |
| 6393 | +{ |
| 6394 | + if (fsm->loc_conn != on) { |
| 6395 | + fsm->loc_conn = on; |
| 6396 | + fsm->ops->loc_conn(on); |
| 6397 | + } |
| 6398 | +} |
| 6399 | + |
| 6400 | +static inline void otg_loc_sof(struct otg_fsm *fsm, int on) |
| 6401 | +{ |
| 6402 | + if (fsm->loc_sof != on) { |
| 6403 | + fsm->loc_sof = on; |
| 6404 | + fsm->ops->loc_sof(on); |
| 6405 | + } |
| 6406 | +} |
| 6407 | + |
| 6408 | +static inline void otg_start_pulse(struct otg_fsm *fsm) |
| 6409 | +{ |
| 6410 | + fsm->ops->start_pulse(); |
| 6411 | +} |
| 6412 | + |
| 6413 | +static inline void otg_add_timer(struct otg_fsm *fsm, void *timer) |
| 6414 | +{ |
| 6415 | + fsm->ops->add_timer(timer); |
| 6416 | +} |
| 6417 | + |
| 6418 | +static inline void otg_del_timer(struct otg_fsm *fsm, void *timer) |
| 6419 | +{ |
| 6420 | + fsm->ops->del_timer(timer); |
| 6421 | +} |
| 6422 | + |
| 6423 | +int otg_statemachine(struct otg_fsm *fsm); |
| 6424 | --- /dev/null |
| 6425 | +++ b/drivers/usb/otg/usb.c |
| 6426 | @@ -0,0 +1,76 @@ |
| 6427 | +/* Copyright 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 6428 | + * |
| 6429 | + * Author: Li Yang <LeoLi@freescale.com> |
| 6430 | + * Jerry Huang <Chang-Ming.Huang@freescale.com> |
| 6431 | + * |
| 6432 | + * This program is free software; you can redistribute it and/or modify it |
| 6433 | + * under the terms of the GNU General Public License as published by the |
| 6434 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 6435 | + * option) any later version. |
| 6436 | + * |
| 6437 | + * This program is distributed in the hope that it will be useful, but |
| 6438 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 6439 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 6440 | + * General Public License for more details. |
| 6441 | + * |
| 6442 | + * You should have received a copy of the GNU General Public License along |
| 6443 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 6444 | + * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 6445 | + */ |
| 6446 | + |
| 6447 | +#include <linux/module.h> |
| 6448 | +#include <linux/kernel.h> |
| 6449 | +#include <linux/types.h> |
| 6450 | +#include <linux/errno.h> |
| 6451 | +#include <linux/init.h> |
| 6452 | +#include <linux/device.h> |
| 6453 | +#include <linux/usb/otg.h> |
| 6454 | + |
| 6455 | +#include <linux/io.h> |
| 6456 | +#include <asm/irq.h> |
| 6457 | +#include <asm/system.h> |
| 6458 | + |
| 6459 | + |
| 6460 | +static struct otg_transceiver *transceiver; |
| 6461 | +static struct resource *otg_resources; |
| 6462 | + |
| 6463 | +/* |
| 6464 | + * otg_get_transceiver - find the (single) OTG transceiver driver |
| 6465 | + * |
| 6466 | + * Returns the transceiver driver, after getting a refcount to it; or |
| 6467 | + * null if there is no such transceiver. The caller is responsible for |
| 6468 | + * releasing that count. |
| 6469 | + */ |
| 6470 | +struct otg_transceiver *otg_get_transceiver(void) |
| 6471 | +{ |
| 6472 | + pr_debug("%s transceiver=0x%p\n", __func__, transceiver); |
| 6473 | + if (transceiver) |
| 6474 | + get_device(transceiver->dev); |
| 6475 | + |
| 6476 | + return transceiver; |
| 6477 | +} |
| 6478 | +EXPORT_SYMBOL(otg_get_transceiver); |
| 6479 | + |
| 6480 | +int otg_set_transceiver(struct otg_transceiver *otg) |
| 6481 | +{ |
| 6482 | + if (transceiver && otg) |
| 6483 | + return -EBUSY; |
| 6484 | + |
| 6485 | + transceiver = otg; |
| 6486 | + |
| 6487 | + return 0; |
| 6488 | +} |
| 6489 | +EXPORT_SYMBOL(otg_set_transceiver); |
| 6490 | + |
| 6491 | +struct resource *otg_get_resources(void) |
| 6492 | +{ |
| 6493 | + return otg_resources; |
| 6494 | +} |
| 6495 | +EXPORT_SYMBOL(otg_get_resources); |
| 6496 | + |
| 6497 | +int otg_set_resources(struct resource *resources) |
| 6498 | +{ |
| 6499 | + otg_resources = resources; |
| 6500 | + return 0; |
| 6501 | +} |
| 6502 | +EXPORT_SYMBOL(otg_set_resources); |
| 6503 | --- a/include/linux/fsl_devices.h |
| 6504 | +++ b/include/linux/fsl_devices.h |
| 6505 | @@ -72,6 +72,18 @@ struct fsl_usb2_platform_data { |
| 6506 | void (*exit)(struct platform_device *); |
| 6507 | void __iomem *regs; /* ioremap'd register base */ |
| 6508 | struct clk *clk; |
| 6509 | +#ifdef CONFIG_COLDFIRE |
| 6510 | + u32 xcvr_type; /* PORTSC_PTS_* */ |
| 6511 | + char *name; /* pretty print */ |
| 6512 | + char *transceiver; /* transceiver name */ |
| 6513 | + unsigned power_budget; /* for hcd->power_budget */ |
| 6514 | + struct platform_device *pdev; |
| 6515 | + struct fsl_xcvr_ops *xcvr_ops; |
| 6516 | + |
| 6517 | + int (*gpio_usb_active) (void); |
| 6518 | + void (*gpio_usb_inactive) (void); |
| 6519 | + |
| 6520 | +#endif |
| 6521 | unsigned big_endian_mmio:1; |
| 6522 | unsigned big_endian_desc:1; |
| 6523 | unsigned es:1; /* need USBMODE:ES */ |
| 6524 | @@ -79,6 +91,20 @@ struct fsl_usb2_platform_data { |
| 6525 | unsigned have_sysif_regs:1; |
| 6526 | unsigned invert_drvvbus:1; |
| 6527 | unsigned invert_pwr_fault:1; |
| 6528 | +#ifdef CONFIG_COLDFIRE |
| 6529 | + unsigned suspended:1; |
| 6530 | + unsigned already_suspended:1; |
| 6531 | +#endif |
| 6532 | + /* register save area for suspend/resume */ |
| 6533 | + u32 pm_command; |
| 6534 | + u32 pm_status; |
| 6535 | + u32 pm_intr_enable; |
| 6536 | + u32 pm_frame_index; |
| 6537 | + u32 pm_segment; |
| 6538 | + u32 pm_frame_list; |
| 6539 | + u32 pm_async_next; |
| 6540 | + u32 pm_configured_flag; |
| 6541 | + u32 pm_portsc; |
| 6542 | }; |
| 6543 | |
| 6544 | /* Flags in fsl_usb2_mph_platform_data */ |
| 6545 | --- /dev/null |
| 6546 | +++ b/include/linux/usb/fsl_usb2.h |
| 6547 | @@ -0,0 +1,410 @@ |
| 6548 | +/* |
| 6549 | + * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 6550 | + * |
| 6551 | + * Freescale USB device/endpoint management registers |
| 6552 | + * |
| 6553 | + * This program is free software; you can redistribute it and/or modify it |
| 6554 | + * under the terms of the GNU General Public License as published by the |
| 6555 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 6556 | + * option) any later version. |
| 6557 | + */ |
| 6558 | +#ifndef __FSL_USB2_H |
| 6559 | +#define __FSL_USB2_H |
| 6560 | + |
| 6561 | + |
| 6562 | + /* USB DR device mode registers (Little Endian) */ |
| 6563 | +struct fsl_usb_device_regs { |
| 6564 | + /* Capability register */ |
| 6565 | + u32 id; |
| 6566 | + u32 res1[63]; |
| 6567 | + u16 caplength; /* Capability Register Length */ |
| 6568 | + u16 hciversion; /* Host Controller Interface Version */ |
| 6569 | + u32 hcsparams; /* Host Controller Structual Parameters */ |
| 6570 | + u32 hccparams; /* Host Controller Capability Parameters */ |
| 6571 | + u32 res2[5]; |
| 6572 | + u32 dciversion; /* Device Controller Interface Version */ |
| 6573 | + u32 dccparams; /* Device Controller Capability Parameters */ |
| 6574 | + u32 res3[6]; |
| 6575 | + /* Operation register */ |
| 6576 | + u32 usbcmd; /* USB Command Register */ |
| 6577 | + u32 usbsts; /* USB Status Register */ |
| 6578 | + u32 usbintr; /* USB Interrupt Enable Register */ |
| 6579 | + u32 frindex; /* Frame Index Register */ |
| 6580 | + u32 res4; |
| 6581 | + u32 deviceaddr; /* Device Address */ |
| 6582 | + u32 endpointlistaddr; /* Endpoint List Address Register */ |
| 6583 | + u32 res5; |
| 6584 | + u32 burstsize; /* Master Interface Data Burst Size Register */ |
| 6585 | + u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ |
| 6586 | + u32 res6[2]; |
| 6587 | + u32 ulpiview; |
| 6588 | + u32 res7[3]; |
| 6589 | + u32 configflag; /* Configure Flag Register */ |
| 6590 | + u32 portsc1; /* Port 1 Status and Control Register */ |
| 6591 | + u32 res8[7]; |
| 6592 | + u32 otgsc; /* On-The-Go Status and Control */ |
| 6593 | + u32 usbmode; /* USB Mode Register */ |
| 6594 | + u32 endptsetupstat; /* Endpoint Setup Status Register */ |
| 6595 | + u32 endpointprime; /* Endpoint Initialization Register */ |
| 6596 | + u32 endptflush; /* Endpoint Flush Register */ |
| 6597 | + u32 endptstatus; /* Endpoint Status Register */ |
| 6598 | + u32 endptcomplete; /* Endpoint Complete Register */ |
| 6599 | + /* DCCPARAMS:DEN has the real number of device endpoints. */ |
| 6600 | + u32 endptctrl[16]; /* Endpoint Control Registers */ |
| 6601 | +}; |
| 6602 | + |
| 6603 | + /* USB DR host mode registers (Little Endian) */ |
| 6604 | +struct fsl_usb_host_regs { |
| 6605 | + /* Capability register */ |
| 6606 | + u32 id; |
| 6607 | + u32 res1[63]; |
| 6608 | + u16 caplength; /* Capability Register Length */ |
| 6609 | + u16 hciversion; /* Host Controller Interface Version */ |
| 6610 | + u32 hcsparams; /* Host Controller Structual Parameters */ |
| 6611 | + u32 hccparams; /* Host Controller Capability Parameters */ |
| 6612 | + u32 res2[5]; |
| 6613 | + u32 dciversion; /* Device Controller Interface Version */ |
| 6614 | + u32 dccparams; /* Device Controller Capability Parameters */ |
| 6615 | + u32 res3[6]; |
| 6616 | + /* Operation register */ |
| 6617 | + u32 usbcmd; /* USB Command Register */ |
| 6618 | + u32 usbsts; /* USB Status Register */ |
| 6619 | + u32 usbintr; /* USB Interrupt Enable Register */ |
| 6620 | + u32 frindex; /* Frame Index Register */ |
| 6621 | + u32 res4; |
| 6622 | + u32 periodiclistbase; /* Periodic Frame List Base Address Register */ |
| 6623 | + u32 asynclistaddr; /* Current Asynchronous List Address Register */ |
| 6624 | + u32 res5; |
| 6625 | + u32 burstsize; /* Master Interface Data Burst Size Register */ |
| 6626 | + u32 txttfilltuning; /* Transmit FIFO Tuning Controls Register */ |
| 6627 | + u32 res6[2]; |
| 6628 | + u32 ulpiview; |
| 6629 | + u32 res7[3]; |
| 6630 | + u32 configflag; /* Configure Flag Register */ |
| 6631 | + u32 portsc1; /* Port 1 Status and Control Register */ |
| 6632 | + u32 res8[7]; |
| 6633 | + u32 otgsc; /* On-The-Go Status and Control */ |
| 6634 | + u32 usbmode; /* USB Mode Register */ |
| 6635 | + u32 endptsetupstat; /* Endpoint Setup Status Register */ |
| 6636 | + u32 endpointprime; /* Endpoint Initialization Register */ |
| 6637 | + u32 endptflush; /* Endpoint Flush Register */ |
| 6638 | + u32 endptstatus; /* Endpoint Status Register */ |
| 6639 | + u32 endptcomplete; /* Endpoint Complete Register */ |
| 6640 | + /* DCCPARAMS:DEN has the real number of device endpoints. */ |
| 6641 | + u32 endptctrl[16]; /* Endpoint Control Registers */ |
| 6642 | +}; |
| 6643 | + |
| 6644 | + /* non-EHCI USB system interface registers (Big Endian) */ |
| 6645 | +struct usb_sys_interface { |
| 6646 | + u32 snoop1; |
| 6647 | + u32 snoop2; |
| 6648 | + u32 age_cnt_thresh; /* Age Count Threshold Register */ |
| 6649 | + u32 pri_ctrl; /* Priority Control Register */ |
| 6650 | + u32 si_ctrl; /* System Interface Control Register */ |
| 6651 | + u32 res[59]; |
| 6652 | + u32 control; /* General Purpose Control Register */ |
| 6653 | +}; |
| 6654 | + |
| 6655 | +/* ep0 transfer state */ |
| 6656 | +#define WAIT_FOR_SETUP 0 |
| 6657 | +#define DATA_STATE_XMIT 1 |
| 6658 | +#define DATA_STATE_NEED_ZLP 2 |
| 6659 | +#define WAIT_FOR_OUT_STATUS 3 |
| 6660 | +#define DATA_STATE_RECV 4 |
| 6661 | + |
| 6662 | +/* Frame Index Register Bit Masks */ |
| 6663 | +#define USB_FRINDEX_MASKS 0x3fff |
| 6664 | + |
| 6665 | + |
| 6666 | + |
| 6667 | +/* USBCMD Register Bit Masks */ |
| 6668 | +#define USB_CMD_RUN_STOP 0x00000001 |
| 6669 | +#define USB_CMD_CTRL_RESET 0x00000002 |
| 6670 | +#define USB_CMD_PERIODIC_SCHEDULE_EN 0x00000010 |
| 6671 | +#define USB_CMD_ASYNC_SCHEDULE_EN 0x00000020 |
| 6672 | +#define USB_CMD_INT_AA_DOORBELL 0x00000040 |
| 6673 | +#define USB_CMD_ASP 0x00000300 |
| 6674 | +#define USB_CMD_ASYNC_SCH_PARK_EN 0x00000800 |
| 6675 | +#define USB_CMD_SUTW 0x00002000 |
| 6676 | +#define USB_CMD_ATDTW 0x00004000 |
| 6677 | +#define USB_CMD_ITC 0x00FF0000 |
| 6678 | + |
| 6679 | +/* bit 15,3,2 are frame list size */ |
| 6680 | +#define USB_CMD_FRAME_SIZE_1024 0x00000000 |
| 6681 | +#define USB_CMD_FRAME_SIZE_512 0x00000004 |
| 6682 | +#define USB_CMD_FRAME_SIZE_256 0x00000008 |
| 6683 | +#define USB_CMD_FRAME_SIZE_128 0x0000000C |
| 6684 | +#define USB_CMD_FRAME_SIZE_64 0x00008000 |
| 6685 | +#define USB_CMD_FRAME_SIZE_32 0x00008004 |
| 6686 | +#define USB_CMD_FRAME_SIZE_16 0x00008008 |
| 6687 | +#define USB_CMD_FRAME_SIZE_8 0x0000800C |
| 6688 | + |
| 6689 | +/* bit 9-8 are async schedule park mode count */ |
| 6690 | +#define USB_CMD_ASP_00 0x00000000 |
| 6691 | +#define USB_CMD_ASP_01 0x00000100 |
| 6692 | +#define USB_CMD_ASP_10 0x00000200 |
| 6693 | +#define USB_CMD_ASP_11 0x00000300 |
| 6694 | +#define USB_CMD_ASP_BIT_POS 8 |
| 6695 | + |
| 6696 | +/* bit 23-16 are interrupt threshold control */ |
| 6697 | +#define USB_CMD_ITC_NO_THRESHOLD 0x00000000 |
| 6698 | +#define USB_CMD_ITC_1_MICRO_FRM 0x00010000 |
| 6699 | +#define USB_CMD_ITC_2_MICRO_FRM 0x00020000 |
| 6700 | +#define USB_CMD_ITC_4_MICRO_FRM 0x00040000 |
| 6701 | +#define USB_CMD_ITC_8_MICRO_FRM 0x00080000 |
| 6702 | +#define USB_CMD_ITC_16_MICRO_FRM 0x00100000 |
| 6703 | +#define USB_CMD_ITC_32_MICRO_FRM 0x00200000 |
| 6704 | +#define USB_CMD_ITC_64_MICRO_FRM 0x00400000 |
| 6705 | +#define USB_CMD_ITC_BIT_POS 16 |
| 6706 | + |
| 6707 | + |
| 6708 | + |
| 6709 | + |
| 6710 | +/* USB STS Register Bit Masks */ |
| 6711 | +#define USB_STS_INT 0x00000001 |
| 6712 | +#define USB_STS_ERR 0x00000002 |
| 6713 | +#define USB_STS_PORT_CHANGE 0x00000004 |
| 6714 | +#define USB_STS_FRM_LST_ROLL 0x00000008 |
| 6715 | +#define USB_STS_SYS_ERR 0x00000010 |
| 6716 | +#define USB_STS_IAA 0x00000020 |
| 6717 | +#define USB_STS_RESET 0x00000040 |
| 6718 | +#define USB_STS_SOF 0x00000080 |
| 6719 | +#define USB_STS_SUSPEND 0x00000100 |
| 6720 | +#define USB_STS_HC_HALTED 0x00001000 |
| 6721 | +#define USB_STS_RCL 0x00002000 |
| 6722 | +#define USB_STS_PERIODIC_SCHEDULE 0x00004000 |
| 6723 | +#define USB_STS_ASYNC_SCHEDULE 0x00008000 |
| 6724 | + |
| 6725 | +/* USB INTR Register Bit Masks */ |
| 6726 | +#define USB_INTR_INT_EN 0x00000001 |
| 6727 | +#define USB_INTR_ERR_INT_EN 0x00000002 |
| 6728 | +#define USB_INTR_PTC_DETECT_EN 0x00000004 |
| 6729 | +#define USB_INTR_FRM_LST_ROLL_EN 0x00000008 |
| 6730 | +#define USB_INTR_SYS_ERR_EN 0x00000010 |
| 6731 | +#define USB_INTR_ASYN_ADV_EN 0x00000020 |
| 6732 | +#define USB_INTR_RESET_EN 0x00000040 |
| 6733 | +#define USB_INTR_SOF_EN 0x00000080 |
| 6734 | +#define USB_INTR_DEVICE_SUSPEND 0x00000100 |
| 6735 | + |
| 6736 | +/* Device Address bit masks */ |
| 6737 | +#define USB_DEVICE_ADDRESS_MASK 0xFE000000 |
| 6738 | +#define USB_DEVICE_ADDRESS_BIT_POS 25 |
| 6739 | + |
| 6740 | +/* endpoint list address bit masks */ |
| 6741 | +#define USB_EP_LIST_ADDRESS_MASK 0xfffff800 |
| 6742 | + |
| 6743 | + |
| 6744 | +/* x_PORTSCx */ |
| 6745 | +/* bit 31-30 are port transceiver select */ |
| 6746 | +#define PORTSCX_PTS_MASK (3 << 30) /* parallel xcvr select mask */ |
| 6747 | +#define PORTSCX_PHY_TYPE_SEL PORTSCX_PTS_MASK |
| 6748 | +#define PORTSCX_PTS_UTMI (0 << 30) /* UTMI/UTMI+ */ |
| 6749 | +#define PORTSCX_PTS_PHILIPS (1 << 30) /* Philips classic */ |
| 6750 | +#define PORTSCX_PTS_ULPI (2 << 30) /* ULPI */ |
| 6751 | +#define PORTSCX_PTS_SERIAL (3 << 30) /* serial */ |
| 6752 | +#define PORTSCX_PTS_FSLS PORTSCX_PTS_SERIAL |
| 6753 | +#define PORTSCX_PTS_ONCHIP PORTSCX_PTS_FSLS |
| 6754 | + |
| 6755 | +#define PORTSCX_STS (1 << 29) /* serial xcvr select */ |
| 6756 | + |
| 6757 | +/* bit 28 is parallel transceiver width for UTMI interface */ |
| 6758 | +#define PORTSCX_PTW_8BIT (0 << 28) /* 8 bit parallel xcvr */ |
| 6759 | +#define PORTSCX_PTW_16BIT (1 << 28) /* 16 bi parallel xcvr */ |
| 6760 | + |
| 6761 | +/* bit 27-26 are port speed */ |
| 6762 | +#define PORTSCX_PORT_SPEED_FULL (0 << 26) |
| 6763 | +#define PORTSCX_PORT_SPEED_LOW (1 << 26) |
| 6764 | +#define PORTSCX_PORT_SPEED_HIGH (2 << 26) |
| 6765 | +#define PORTSCX_PORT_SPEED_UNDEF (3 << 26) |
| 6766 | +#define PORTSCX_PORT_SPEED_MASK (3 << 26) |
| 6767 | + |
| 6768 | +/* phy low pwr suspend/clk disable */ |
| 6769 | +#define PORTSCX_PHY_LOW_POWER_SPD (1 << 23) |
| 6770 | + |
| 6771 | +/* bit 19-16 are port test control */ |
| 6772 | +#define PORTSCX_PTC_DISABLE (0 << 16) |
| 6773 | +#define PORTSCX_PTC_JSTATE (1 << 16) |
| 6774 | +#define PORTSCX_PTC_KSTATE (2 << 16) |
| 6775 | +#define PORTSCX_PTC_SEQNAK (3 << 16) /* SE0 (host)/NAK (device)*/ |
| 6776 | +#define PORTSCX_PTC_PACKET (4 << 16) |
| 6777 | +#define PORTSCX_PTC_FORCE_EN_HS (5 << 16) |
| 6778 | +#define PORTSCX_PTC_FORCE_EN_FS (6 << 16) |
| 6779 | +#define PORTSCX_PTC_FORCE_EN_LS (7 << 16) |
| 6780 | + |
| 6781 | + |
| 6782 | +/* bit 15-14 are port indicator control */ |
| 6783 | +#define PORTSCX_PIC_OFF (0 << 14) |
| 6784 | +#define PORTSCX_PIC_AMBER (1 << 14) |
| 6785 | +#define PORTSCX_PIC_GREEN (2 << 14) |
| 6786 | +#define PORTSCX_PIC_UNDEF (3 << 14) |
| 6787 | + |
| 6788 | +#define PORTSCX_PORT_POWER (1 << 12) /* port power */ |
| 6789 | + |
| 6790 | +/* bit 11-10 are line status */ |
| 6791 | +#define PORTSCX_LS_MASK (3 << 10) /* Line State mask */ |
| 6792 | +#define PORTSCX_LS_SE0 (0 << 10) /* SE0 */ |
| 6793 | +#define PORTSCX_LS_K_STATE (1 << 10) /* K-state */ |
| 6794 | +#define PORTSCX_LS_J_STATE (2 << 10) /* J-state */ |
| 6795 | + |
| 6796 | +#define PORTSCX_PORT_RESET (1 << 8) /* Port reset */ |
| 6797 | +#define PORTSCX_PORT_SUSPEND (1 << 7) /* Suspend */ |
| 6798 | +#define PORTSCX_PORT_FORCE_RESUME (1 << 6) /* Force port resume */ |
| 6799 | +#define PORTSCX_OVER_CURRENT_CHG (1 << 5) /* over current change */ |
| 6800 | +#define PORTSCX_OVER_CURRENT_ACT (1 << 4) /* over currrent active */ |
| 6801 | +#define PORTSCX_PORT_EN_DIS_CHANGE (1 << 3) /* port {en,dis}able change*/ |
| 6802 | +#define PORTSCX_PORT_ENABLE (1 << 2) /* port enabled */ |
| 6803 | +#define PORTSCX_CONNECT_STATUS_CHANGE (1 << 1) /* connect status change */ |
| 6804 | +#define PORTSCX_CURRENT_CONNECT_STATUS (1 << 0) /* current connect status */ |
| 6805 | + |
| 6806 | +#define PORTSCX_W1C_BITS \ |
| 6807 | + (PORTSCX_CONNECT_STATUS_CHANGE | \ |
| 6808 | + PORTSCX_PORT_EN_DIS_CHANGE | \ |
| 6809 | + PORTSCX_OVER_CURRENT_CHG) |
| 6810 | + |
| 6811 | + |
| 6812 | + |
| 6813 | +/* UOG_OTGSC Register Bits */ |
| 6814 | +/* control bits: */ |
| 6815 | +#define OTGSC_CTRL_VBUS_DISCHARGE (1 << 0) |
| 6816 | +#define OTGSC_CTRL_VBUS_CHARGE (1 << 1) |
| 6817 | +#define OTGSC_CTRL_OTG_TERM (1 << 3)/* controls DM pulldown */ |
| 6818 | +#define OTGSC_CTRL_DATA_PULSING (1 << 4) |
| 6819 | +#define OTGSC_CTRL_USB_ID_PU (1 << 5) /* enable ID pullup */ |
| 6820 | +/* current status: (R/O) */ |
| 6821 | +#define OTGSC_STS_USB_ID (1 << 8)/* 0=A-device 1=B-device */ |
| 6822 | +#define OTGSC_STS_A_VBUS_VALID (1 << 9) |
| 6823 | +#define OTGSC_STS_A_SESSION_VALID (1 << 10) |
| 6824 | +#define OTGSC_STS_B_SESSION_VALID (1 << 11) |
| 6825 | +#define OTGSC_STS_B_SESSION_END (1 << 12) |
| 6826 | +#define OTGSC_STS_1ms_TIMER (1 << 13) |
| 6827 | +#define OTGSC_STS_DATA_PULSE (1 << 14) |
| 6828 | +/* interrupt status: (write to clear) */ |
| 6829 | +#define OTGSC_INTSTS_MASK (0x7f << 16) |
| 6830 | +#define OTGSC_INTSTS_USB_ID (1 << 16) |
| 6831 | +#define OTGSC_INTSTS_A_VBUS_VALID (1 << 17) |
| 6832 | +#define OTGSC_INTSTS_A_SESSION_VALID (1 << 18) |
| 6833 | +#define OTGSC_INTSTS_B_SESSION_VALID (1 << 19) |
| 6834 | +#define OTGSC_INTSTS_B_SESSION_END (1 << 20) |
| 6835 | +#define OTGSC_INTSTS_1MS_TIMER (1 << 21) |
| 6836 | +#define OTGSC_INTSTS_DATA_PULSE (1 << 22) |
| 6837 | +/* interrupt enables: */ |
| 6838 | +#define OTGSC_IE_MASK (0x7f << 24) |
| 6839 | +#define OTGSC_IE_USB_ID (1 << 24) |
| 6840 | +#define OTGSC_IE_A_VBUS_VALID (1 << 25) |
| 6841 | +#define OTGSC_IE_A_SESSION_VALID (1 << 26) |
| 6842 | +#define OTGSC_IE_B_SESSION_VALID (1 << 27) |
| 6843 | +#define OTGSC_IE_B_SESSION_END (1 << 28) |
| 6844 | +#define OTGSC_IE_1ms_TIMER (1 << 29) |
| 6845 | +#define OTGSC_IE_DATA_PULSE (1 << 30) |
| 6846 | + |
| 6847 | +#if 1 /* DDD FIXME these here for compatibility between my names and Leo's */ |
| 6848 | +/* OTG interrupt enable bit masks */ |
| 6849 | +#define OTGSC_INTERRUPT_ENABLE_BITS_MASK OTGSC_IE_MASK |
| 6850 | + |
| 6851 | +/* OTG interrupt status bit masks */ |
| 6852 | +#define OTGSC_INTERRUPT_STATUS_BITS_MASK OTGSC_INTSTS_MASK |
| 6853 | +#endif |
| 6854 | + |
| 6855 | + |
| 6856 | + |
| 6857 | +/* x_USBMODE */ |
| 6858 | +#undef USBMODE_SDIS /* defined as bit 3 in drivers/usb/host/ehci.h */ |
| 6859 | +#define USBMODE_SDIS (1 << 4) /* stream disable mode */ |
| 6860 | +#define USBMODE_SLOM (1 << 3) /* setup lockout mode */ |
| 6861 | +#define USBMODE_ES (1 << 2) /* (big) endian select */ |
| 6862 | +#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */ |
| 6863 | +#define USBMODE_CM_HOST (3 << 0) /* host */ |
| 6864 | +#define USBMODE_CM_DEVICE (2 << 0) /* device */ |
| 6865 | + |
| 6866 | +/* DDD for compatibility for now */ |
| 6867 | +#define USB_MODE_CTRL_MODE_IDLE USBMODE_CM_IDLE |
| 6868 | +#define USB_MODE_CTRL_MODE_DEVICE USBMODE_CM_DEVICE |
| 6869 | +#define USB_MODE_CTRL_MODE_HOST USBMODE_CM_HOST |
| 6870 | +#define USB_MODE_SETUP_LOCK_OFF USBMODE_SLOM |
| 6871 | +#define USB_MODE_STREAM_DISABLE USBMODE_SDIS |
| 6872 | + |
| 6873 | + |
| 6874 | +/* ULPIVIEW register bits */ |
| 6875 | +#define ULPIVW_WU (1 << 31) /* Wakeup */ |
| 6876 | +#define ULPIVW_RUN (1 << 30) /* read/write run */ |
| 6877 | +#define ULPIVW_WRITE (1 << 29) /* 0=read 1=write */ |
| 6878 | +#define ULPIVW_SS (1 << 27) /* SyncState */ |
| 6879 | +#define ULPIVW_PORT_MASK 0x07 /* Port field */ |
| 6880 | +#define ULPIVW_PORT_SHIFT 24 |
| 6881 | +#define ULPIVW_ADDR_MASK 0xFF /* data address field */ |
| 6882 | +#define ULPIVW_ADDR_SHIFT 16 |
| 6883 | +#define ULPIVW_RDATA_MASK 0xFF /* read data field */ |
| 6884 | +#define ULPIVW_RDATA_SHIFT 8 |
| 6885 | +#define ULPIVW_WDATA_MASK 0xFF /* write data field */ |
| 6886 | +#define ULPIVW_WDATA_SHIFT 0 |
| 6887 | + |
| 6888 | + |
| 6889 | +/* Endpoint Flush Register */ |
| 6890 | +#define EPFLUSH_TX_OFFSET 0x00010000 |
| 6891 | +#define EPFLUSH_RX_OFFSET 0x00000000 |
| 6892 | + |
| 6893 | +/* Endpoint Setup Status bit masks */ |
| 6894 | +#define EP_SETUP_STATUS_MASK 0x0000003F |
| 6895 | +#define EP_SETUP_STATUS_EP0 0x00000001 |
| 6896 | + |
| 6897 | +/* ENDPOINTCTRLx Register Bit Masks */ |
| 6898 | +#define EPCTRL_TX_ENABLE 0x00800000 |
| 6899 | +#define EPCTRL_TX_DATA_TOGGLE_RST 0x00400000 /* Not EP0 */ |
| 6900 | +#define EPCTRL_TX_DATA_TOGGLE_INH 0x00200000 /* Not EP0 */ |
| 6901 | +#define EPCTRL_TX_TYPE 0x000C0000 |
| 6902 | +#define EPCTRL_TX_DATA_SOURCE 0x00020000 /* Not EP0 */ |
| 6903 | +#define EPCTRL_TX_EP_STALL 0x00010000 |
| 6904 | +#define EPCTRL_RX_ENABLE 0x00000080 |
| 6905 | +#define EPCTRL_RX_DATA_TOGGLE_RST 0x00000040 /* Not EP0 */ |
| 6906 | +#define EPCTRL_RX_DATA_TOGGLE_INH 0x00000020 /* Not EP0 */ |
| 6907 | +#define EPCTRL_RX_TYPE 0x0000000C |
| 6908 | +#define EPCTRL_RX_DATA_SINK 0x00000002 /* Not EP0 */ |
| 6909 | +#define EPCTRL_RX_EP_STALL 0x00000001 |
| 6910 | + |
| 6911 | +/* bit 19-18 and 3-2 are endpoint type */ |
| 6912 | +#define EPCTRL_EP_TYPE_CONTROL 0 |
| 6913 | +#define EPCTRL_EP_TYPE_ISO 1 |
| 6914 | +#define EPCTRL_EP_TYPE_BULK 2 |
| 6915 | +#define EPCTRL_EP_TYPE_INTERRUPT 3 |
| 6916 | +#define EPCTRL_TX_EP_TYPE_SHIFT 18 |
| 6917 | +#define EPCTRL_RX_EP_TYPE_SHIFT 2 |
| 6918 | + |
| 6919 | +/* pri_ctrl Register Bit Masks */ |
| 6920 | +#define PRI_CTRL_PRI_LVL1 0x0000000C |
| 6921 | +#define PRI_CTRL_PRI_LVL0 0x00000003 |
| 6922 | + |
| 6923 | +/* si_ctrl Register Bit Masks */ |
| 6924 | +#define SI_CTRL_ERR_DISABLE 0x00000010 |
| 6925 | +#define SI_CTRL_IDRC_DISABLE 0x00000008 |
| 6926 | +#define SI_CTRL_RD_SAFE_EN 0x00000004 |
| 6927 | +#define SI_CTRL_RD_PREFETCH_DISABLE 0x00000002 |
| 6928 | +#define SI_CTRL_RD_PREFEFETCH_VAL 0x00000001 |
| 6929 | + |
| 6930 | + |
| 6931 | +/* control Register Bit Masks */ |
| 6932 | +#define USB_CTRL_IOENB 0x00000004 |
| 6933 | +#define USB_CTRL_ULPI_INT0EN 0x00000001 |
| 6934 | + |
| 6935 | + |
| 6936 | +/* Endpoint Transfer Descriptor bit Masks */ |
| 6937 | +#define DTD_NEXT_TERMINATE 0x00000001 |
| 6938 | +#define DTD_IOC 0x00008000 |
| 6939 | +#define DTD_STATUS_ACTIVE 0x00000080 |
| 6940 | +#define DTD_STATUS_HALTED 0x00000040 |
| 6941 | +#define DTD_STATUS_DATA_BUFF_ERR 0x00000020 |
| 6942 | +#define DTD_STATUS_TRANSACTION_ERR 0x00000008 |
| 6943 | +#define DTD_RESERVED_FIELDS 0x80007300 |
| 6944 | +#define DTD_ADDR_MASK 0xFFFFFFE0 |
| 6945 | +#define DTD_PACKET_SIZE 0x7FFF0000 |
| 6946 | +#define DTD_LENGTH_BIT_POS 16 |
| 6947 | +#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \ |
| 6948 | + DTD_STATUS_DATA_BUFF_ERR | \ |
| 6949 | + DTD_STATUS_TRANSACTION_ERR) |
| 6950 | +/* Alignment requirements; must be a power of two */ |
| 6951 | +#define DTD_ALIGNMENT 0x20 |
| 6952 | +#define QH_ALIGNMENT 2048 |
| 6953 | + |
| 6954 | +/* Controller dma boundary */ |
| 6955 | +#define UDC_DMA_BOUNDARY 0x1000 |
| 6956 | + |
| 6957 | +#endif /* __FSL_USB2_H */ |
| 6958 | --- /dev/null |
| 6959 | +++ b/include/linux/usb/fsl_xcvr.h |
| 6960 | @@ -0,0 +1,36 @@ |
| 6961 | +/* |
| 6962 | + * Copyright 2007-2011 Freescale Semiconductor, Inc. All Rights Reserved. |
| 6963 | + * |
| 6964 | + * This program is free software; you can redistribute it and/or modify it |
| 6965 | + * under the terms of the GNU General Public License as published by the |
| 6966 | + * Free Software Foundation; either version 2 of the License, or (at your |
| 6967 | + * option) any later version. |
| 6968 | + */ |
| 6969 | + |
| 6970 | +/** |
| 6971 | + * struct fsl_xcvr_ops - USB transceiver operations |
| 6972 | + * |
| 6973 | + * @xcvr_type: one of PORTSCX_PTS_{UTMI,SERIAL,ULPI} |
| 6974 | + * @init: transceiver- and board-specific initialization function |
| 6975 | + * @uninit: transceiver- and board-specific uninitialization function |
| 6976 | + * @set_host: |
| 6977 | + * @set_device: |
| 6978 | + * |
| 6979 | + */ |
| 6980 | +struct fsl_xcvr_ops { |
| 6981 | + char *name; |
| 6982 | + u32 xcvr_type; |
| 6983 | + struct fsl_usb2_platform_data *pdata; |
| 6984 | + |
| 6985 | + void (*init)(struct fsl_xcvr_ops *ops); |
| 6986 | + void (*uninit)(struct fsl_xcvr_ops *ops); |
| 6987 | + void (*suspend)(struct fsl_xcvr_ops *ops); |
| 6988 | + void (*set_host)(void); |
| 6989 | + void (*set_device)(void); |
| 6990 | + void (*set_vbus_power)(struct fsl_xcvr_ops *ops, int on); |
| 6991 | + void (*set_remote_wakeup)(u32 *view); |
| 6992 | + void (*pullup)(int on); |
| 6993 | +}; |
| 6994 | + |
| 6995 | +extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops); |
| 6996 | +extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops); |
| 6997 | --- a/include/linux/usb/otg.h |
| 6998 | +++ b/include/linux/usb/otg.h |
| 6999 | @@ -164,7 +164,7 @@ otg_shutdown(struct otg_transceiver *otg |
| 7000 | } |
| 7001 | |
| 7002 | /* for usb host and peripheral controller drivers */ |
| 7003 | -#ifdef CONFIG_USB_OTG_UTILS |
| 7004 | +#if defined(CONFIG_USB_OTG_UTILS) || defined(CONFIG_COLDFIRE) |
| 7005 | extern struct otg_transceiver *otg_get_transceiver(void); |
| 7006 | extern void otg_put_transceiver(struct otg_transceiver *); |
| 7007 | #else |
| 7008 | |