uboot/drivers/usb/musb-new/musb_uboot.c
<<
>>
Prefs
   1#include <common.h>
   2#include <console.h>
   3#include <watchdog.h>
   4#ifdef CONFIG_ARCH_SUNXI
   5#include <asm/arch/usb_phy.h>
   6#endif
   7#include <asm/errno.h>
   8#include <linux/usb/ch9.h>
   9#include <linux/usb/gadget.h>
  10
  11#include <usb.h>
  12#include "linux-compat.h"
  13#include "usb-compat.h"
  14#include "musb_core.h"
  15#include "musb_host.h"
  16#include "musb_gadget.h"
  17#include "musb_uboot.h"
  18
  19#ifdef CONFIG_USB_MUSB_HOST
  20struct int_queue {
  21        struct usb_host_endpoint hep;
  22        struct urb urb;
  23};
  24
  25#ifndef CONFIG_DM_USB
  26struct musb_host_data musb_host;
  27#endif
  28
  29static void musb_host_complete_urb(struct urb *urb)
  30{
  31        urb->dev->status &= ~USB_ST_NOT_PROC;
  32        urb->dev->act_len = urb->actual_length;
  33}
  34
  35static void construct_urb(struct urb *urb, struct usb_host_endpoint *hep,
  36                          struct usb_device *dev, int endpoint_type,
  37                          unsigned long pipe, void *buffer, int len,
  38                          struct devrequest *setup, int interval)
  39{
  40        int epnum = usb_pipeendpoint(pipe);
  41        int is_in = usb_pipein(pipe);
  42
  43        memset(urb, 0, sizeof(struct urb));
  44        memset(hep, 0, sizeof(struct usb_host_endpoint));
  45        INIT_LIST_HEAD(&hep->urb_list);
  46        INIT_LIST_HEAD(&urb->urb_list);
  47        urb->ep = hep;
  48        urb->complete = musb_host_complete_urb;
  49        urb->status = -EINPROGRESS;
  50        urb->dev = dev;
  51        urb->pipe = pipe;
  52        urb->transfer_buffer = buffer;
  53        urb->transfer_dma = (unsigned long)buffer;
  54        urb->transfer_buffer_length = len;
  55        urb->setup_packet = (unsigned char *)setup;
  56
  57        urb->ep->desc.wMaxPacketSize =
  58                __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] :
  59                                dev->epmaxpacketout[epnum]);
  60        urb->ep->desc.bmAttributes = endpoint_type;
  61        urb->ep->desc.bEndpointAddress =
  62                (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum;
  63        urb->ep->desc.bInterval = interval;
  64}
  65
  66static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
  67{
  68        struct musb *host = hcd->hcd_priv;
  69        int ret;
  70        unsigned long timeout;
  71
  72        ret = musb_urb_enqueue(hcd, urb, 0);
  73        if (ret < 0) {
  74                printf("Failed to enqueue URB to controller\n");
  75                return ret;
  76        }
  77
  78        timeout = get_timer(0) + USB_TIMEOUT_MS(urb->pipe);
  79        do {
  80                if (ctrlc())
  81                        return -EIO;
  82                host->isr(0, host);
  83        } while (urb->status == -EINPROGRESS &&
  84                 get_timer(0) < timeout);
  85
  86        if (urb->status == -EINPROGRESS)
  87                musb_urb_dequeue(hcd, urb, -ETIME);
  88
  89        return urb->status;
  90}
  91
  92static int _musb_submit_control_msg(struct musb_host_data *host,
  93        struct usb_device *dev, unsigned long pipe,
  94        void *buffer, int len, struct devrequest *setup)
  95{
  96        construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_CONTROL,
  97                      pipe, buffer, len, setup, 0);
  98
  99        /* Fix speed for non hub-attached devices */
 100        if (!usb_dev_get_parent(dev))
 101                dev->speed = host->host_speed;
 102
 103        return submit_urb(&host->hcd, &host->urb);
 104}
 105
 106static int _musb_submit_bulk_msg(struct musb_host_data *host,
 107        struct usb_device *dev, unsigned long pipe, void *buffer, int len)
 108{
 109        construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_BULK,
 110                      pipe, buffer, len, NULL, 0);
 111        return submit_urb(&host->hcd, &host->urb);
 112}
 113
 114static int _musb_submit_int_msg(struct musb_host_data *host,
 115        struct usb_device *dev, unsigned long pipe,
 116        void *buffer, int len, int interval)
 117{
 118        construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_INT, pipe,
 119                      buffer, len, NULL, interval);
 120        return submit_urb(&host->hcd, &host->urb);
 121}
 122
 123static struct int_queue *_musb_create_int_queue(struct musb_host_data *host,
 124        struct usb_device *dev, unsigned long pipe, int queuesize,
 125        int elementsize, void *buffer, int interval)
 126{
 127        struct int_queue *queue;
 128        int ret, index = usb_pipein(pipe) * 16 + usb_pipeendpoint(pipe);
 129
 130        if (queuesize != 1) {
 131                printf("ERROR musb int-queues only support queuesize 1\n");
 132                return NULL;
 133        }
 134
 135        if (dev->int_pending & (1 << index)) {
 136                printf("ERROR int-urb is already pending on pipe %lx\n", pipe);
 137                return NULL;
 138        }
 139
 140        queue = malloc(sizeof(*queue));
 141        if (!queue)
 142                return NULL;
 143
 144        construct_urb(&queue->urb, &queue->hep, dev, USB_ENDPOINT_XFER_INT,
 145                      pipe, buffer, elementsize, NULL, interval);
 146
 147        ret = musb_urb_enqueue(&host->hcd, &queue->urb, 0);
 148        if (ret < 0) {
 149                printf("Failed to enqueue URB to controller\n");
 150                free(queue);
 151                return NULL;
 152        }
 153
 154        dev->int_pending |= 1 << index;
 155        return queue;
 156}
 157
 158static int _musb_destroy_int_queue(struct musb_host_data *host,
 159        struct usb_device *dev, struct int_queue *queue)
 160{
 161        int index = usb_pipein(queue->urb.pipe) * 16 + 
 162                    usb_pipeendpoint(queue->urb.pipe);
 163
 164        if (queue->urb.status == -EINPROGRESS)
 165                musb_urb_dequeue(&host->hcd, &queue->urb, -ETIME);
 166
 167        dev->int_pending &= ~(1 << index);
 168        free(queue);
 169        return 0;
 170}
 171
 172static void *_musb_poll_int_queue(struct musb_host_data *host,
 173        struct usb_device *dev, struct int_queue *queue)
 174{
 175        if (queue->urb.status != -EINPROGRESS)
 176                return NULL; /* URB has already completed in a prev. poll */
 177
 178        host->host->isr(0, host->host);
 179
 180        if (queue->urb.status != -EINPROGRESS)
 181                return queue->urb.transfer_buffer; /* Done */
 182
 183        return NULL; /* URB still pending */
 184}
 185
 186static int _musb_reset_root_port(struct musb_host_data *host,
 187        struct usb_device *dev)
 188{
 189        void *mbase = host->host->mregs;
 190        u8 power;
 191
 192        power = musb_readb(mbase, MUSB_POWER);
 193        power &= 0xf0;
 194        musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
 195        mdelay(50);
 196#ifdef CONFIG_ARCH_SUNXI
 197        /*
 198         * sunxi phy has a bug and it will wrongly detect high speed squelch
 199         * when clearing reset on low-speed devices, temporary disable
 200         * squelch detection to work around this.
 201         */
 202        sunxi_usb_phy_enable_squelch_detect(0, 0);
 203#endif
 204        power = musb_readb(mbase, MUSB_POWER);
 205        musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
 206#ifdef CONFIG_ARCH_SUNXI
 207        sunxi_usb_phy_enable_squelch_detect(0, 1);
 208#endif
 209        host->host->isr(0, host->host);
 210        host->host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
 211                        USB_SPEED_HIGH :
 212                        (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
 213                        USB_SPEED_FULL : USB_SPEED_LOW;
 214        mdelay((host->host_speed == USB_SPEED_LOW) ? 200 : 50);
 215
 216        return 0;
 217}
 218
 219int musb_lowlevel_init(struct musb_host_data *host)
 220{
 221        void *mbase;
 222        /* USB spec says it may take up to 1 second for a device to connect */
 223        unsigned long timeout = get_timer(0) + 1000;
 224        int ret;
 225
 226        if (!host->host) {
 227                printf("MUSB host is not registered\n");
 228                return -ENODEV;
 229        }
 230
 231        ret = musb_start(host->host);
 232        if (ret)
 233                return ret;
 234
 235        mbase = host->host->mregs;
 236        do {
 237                if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
 238                        break;
 239        } while (get_timer(0) < timeout);
 240        if (get_timer(0) >= timeout)
 241                return -ENODEV;
 242
 243        _musb_reset_root_port(host, NULL);
 244        host->host->is_active = 1;
 245        host->hcd.hcd_priv = host->host;
 246
 247        return 0;
 248}
 249
 250#ifndef CONFIG_DM_USB
 251int usb_lowlevel_stop(int index)
 252{
 253        if (!musb_host.host) {
 254                printf("MUSB host is not registered\n");
 255                return -ENODEV;
 256        }
 257
 258        musb_stop(musb_host.host);
 259        return 0;
 260}
 261
 262int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 263                            void *buffer, int length)
 264{
 265        return _musb_submit_bulk_msg(&musb_host, dev, pipe, buffer, length);
 266}
 267
 268int submit_control_msg(struct usb_device *dev, unsigned long pipe,
 269                       void *buffer, int length, struct devrequest *setup)
 270{
 271        return _musb_submit_control_msg(&musb_host, dev, pipe, buffer, length, setup);
 272}
 273
 274int submit_int_msg(struct usb_device *dev, unsigned long pipe,
 275                   void *buffer, int length, int interval)
 276{
 277        return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, interval);
 278}
 279
 280struct int_queue *create_int_queue(struct usb_device *dev,
 281                unsigned long pipe, int queuesize, int elementsize,
 282                void *buffer, int interval)
 283{
 284        return _musb_create_int_queue(&musb_host, dev, pipe, queuesize, elementsize,
 285                                      buffer, interval);
 286}
 287
 288void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
 289{
 290        return _musb_poll_int_queue(&musb_host, dev, queue);
 291}
 292
 293int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 294{
 295        return _musb_destroy_int_queue(&musb_host, dev, queue);
 296}
 297
 298int usb_reset_root_port(struct usb_device *dev)
 299{
 300        return _musb_reset_root_port(&musb_host, dev);
 301}
 302
 303int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 304{
 305        return musb_lowlevel_init(&musb_host);
 306}
 307#endif /* !CONFIG_DM_USB */
 308
 309#ifdef CONFIG_DM_USB
 310static int musb_submit_control_msg(struct udevice *dev, struct usb_device *udev,
 311                                   unsigned long pipe, void *buffer, int length,
 312                                   struct devrequest *setup)
 313{
 314        struct musb_host_data *host = dev_get_priv(dev);
 315        return _musb_submit_control_msg(host, udev, pipe, buffer, length, setup);
 316}
 317
 318static int musb_submit_bulk_msg(struct udevice *dev, struct usb_device *udev,
 319                                unsigned long pipe, void *buffer, int length)
 320{
 321        struct musb_host_data *host = dev_get_priv(dev);
 322        return _musb_submit_bulk_msg(host, udev, pipe, buffer, length);
 323}
 324
 325static int musb_submit_int_msg(struct udevice *dev, struct usb_device *udev,
 326                               unsigned long pipe, void *buffer, int length,
 327                               int interval)
 328{
 329        struct musb_host_data *host = dev_get_priv(dev);
 330        return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval);
 331}
 332
 333static struct int_queue *musb_create_int_queue(struct udevice *dev,
 334                struct usb_device *udev, unsigned long pipe, int queuesize,
 335                int elementsize, void *buffer, int interval)
 336{
 337        struct musb_host_data *host = dev_get_priv(dev);
 338        return _musb_create_int_queue(host, udev, pipe, queuesize, elementsize,
 339                                      buffer, interval);
 340}
 341
 342static void *musb_poll_int_queue(struct udevice *dev, struct usb_device *udev,
 343                                 struct int_queue *queue)
 344{
 345        struct musb_host_data *host = dev_get_priv(dev);
 346        return _musb_poll_int_queue(host, udev, queue);
 347}
 348
 349static int musb_destroy_int_queue(struct udevice *dev, struct usb_device *udev,
 350                                  struct int_queue *queue)
 351{
 352        struct musb_host_data *host = dev_get_priv(dev);
 353        return _musb_destroy_int_queue(host, udev, queue);
 354}
 355
 356static int musb_reset_root_port(struct udevice *dev, struct usb_device *udev)
 357{
 358        struct musb_host_data *host = dev_get_priv(dev);
 359        return _musb_reset_root_port(host, udev);
 360}
 361
 362struct dm_usb_ops musb_usb_ops = {
 363        .control = musb_submit_control_msg,
 364        .bulk = musb_submit_bulk_msg,
 365        .interrupt = musb_submit_int_msg,
 366        .create_int_queue = musb_create_int_queue,
 367        .poll_int_queue = musb_poll_int_queue,
 368        .destroy_int_queue = musb_destroy_int_queue,
 369        .reset_root_port = musb_reset_root_port,
 370};
 371#endif /* CONFIG_DM_USB */
 372#endif /* CONFIG_USB_MUSB_HOST */
 373
 374#ifdef CONFIG_USB_MUSB_GADGET
 375static struct musb *gadget;
 376
 377int usb_gadget_handle_interrupts(int index)
 378{
 379        WATCHDOG_RESET();
 380        if (!gadget || !gadget->isr)
 381                return -EINVAL;
 382
 383        return gadget->isr(0, gadget);
 384}
 385
 386int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 387{
 388        int ret;
 389
 390        if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind ||
 391            !driver->setup) {
 392                printf("bad parameter.\n");
 393                return -EINVAL;
 394        }
 395
 396        if (!gadget) {
 397                printf("Controller uninitialized\n");
 398                return -ENXIO;
 399        }
 400
 401        ret = musb_gadget_start(&gadget->g, driver);
 402        if (ret < 0) {
 403                printf("gadget_start failed with %d\n", ret);
 404                return ret;
 405        }
 406
 407        ret = driver->bind(&gadget->g);
 408        if (ret < 0) {
 409                printf("bind failed with %d\n", ret);
 410                return ret;
 411        }
 412
 413        return 0;
 414}
 415
 416int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 417{
 418        if (driver->disconnect)
 419                driver->disconnect(&gadget->g);
 420        if (driver->unbind)
 421                driver->unbind(&gadget->g);
 422        return 0;
 423}
 424#endif /* CONFIG_USB_MUSB_GADGET */
 425
 426int musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
 427                        void *ctl_regs)
 428{
 429        struct musb **musbp;
 430
 431        switch (plat->mode) {
 432#if defined(CONFIG_USB_MUSB_HOST) && !defined(CONFIG_DM_USB)
 433        case MUSB_HOST:
 434                musbp = &musb_host.host;
 435                break;
 436#endif
 437#ifdef CONFIG_USB_MUSB_GADGET
 438        case MUSB_PERIPHERAL:
 439                musbp = &gadget;
 440                break;
 441#endif
 442        default:
 443                return -EINVAL;
 444        }
 445
 446        *musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs);
 447        if (!musbp) {
 448                printf("Failed to init the controller\n");
 449                return -EIO;
 450        }
 451
 452        return 0;
 453}
 454