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 <linux/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                musb_stop(host->host);
 242                return -ENODEV;
 243        }
 244
 245        _musb_reset_root_port(host, NULL);
 246        host->host->is_active = 1;
 247        host->hcd.hcd_priv = host->host;
 248
 249        return 0;
 250}
 251
 252#ifndef CONFIG_DM_USB
 253int usb_lowlevel_stop(int index)
 254{
 255        if (!musb_host.host) {
 256                printf("MUSB host is not registered\n");
 257                return -ENODEV;
 258        }
 259
 260        musb_stop(musb_host.host);
 261        return 0;
 262}
 263
 264int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 265                            void *buffer, int length)
 266{
 267        return _musb_submit_bulk_msg(&musb_host, dev, pipe, buffer, length);
 268}
 269
 270int submit_control_msg(struct usb_device *dev, unsigned long pipe,
 271                       void *buffer, int length, struct devrequest *setup)
 272{
 273        return _musb_submit_control_msg(&musb_host, dev, pipe, buffer, length, setup);
 274}
 275
 276int submit_int_msg(struct usb_device *dev, unsigned long pipe,
 277                   void *buffer, int length, int interval)
 278{
 279        return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, interval);
 280}
 281
 282struct int_queue *create_int_queue(struct usb_device *dev,
 283                unsigned long pipe, int queuesize, int elementsize,
 284                void *buffer, int interval)
 285{
 286        return _musb_create_int_queue(&musb_host, dev, pipe, queuesize, elementsize,
 287                                      buffer, interval);
 288}
 289
 290void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
 291{
 292        return _musb_poll_int_queue(&musb_host, dev, queue);
 293}
 294
 295int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 296{
 297        return _musb_destroy_int_queue(&musb_host, dev, queue);
 298}
 299
 300int usb_reset_root_port(struct usb_device *dev)
 301{
 302        return _musb_reset_root_port(&musb_host, dev);
 303}
 304
 305int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 306{
 307        return musb_lowlevel_init(&musb_host);
 308}
 309#endif /* !CONFIG_DM_USB */
 310
 311#ifdef CONFIG_DM_USB
 312static int musb_submit_control_msg(struct udevice *dev, struct usb_device *udev,
 313                                   unsigned long pipe, void *buffer, int length,
 314                                   struct devrequest *setup)
 315{
 316        struct musb_host_data *host = dev_get_priv(dev);
 317        return _musb_submit_control_msg(host, udev, pipe, buffer, length, setup);
 318}
 319
 320static int musb_submit_bulk_msg(struct udevice *dev, struct usb_device *udev,
 321                                unsigned long pipe, void *buffer, int length)
 322{
 323        struct musb_host_data *host = dev_get_priv(dev);
 324        return _musb_submit_bulk_msg(host, udev, pipe, buffer, length);
 325}
 326
 327static int musb_submit_int_msg(struct udevice *dev, struct usb_device *udev,
 328                               unsigned long pipe, void *buffer, int length,
 329                               int interval)
 330{
 331        struct musb_host_data *host = dev_get_priv(dev);
 332        return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval);
 333}
 334
 335static struct int_queue *musb_create_int_queue(struct udevice *dev,
 336                struct usb_device *udev, unsigned long pipe, int queuesize,
 337                int elementsize, void *buffer, int interval)
 338{
 339        struct musb_host_data *host = dev_get_priv(dev);
 340        return _musb_create_int_queue(host, udev, pipe, queuesize, elementsize,
 341                                      buffer, interval);
 342}
 343
 344static void *musb_poll_int_queue(struct udevice *dev, struct usb_device *udev,
 345                                 struct int_queue *queue)
 346{
 347        struct musb_host_data *host = dev_get_priv(dev);
 348        return _musb_poll_int_queue(host, udev, queue);
 349}
 350
 351static int musb_destroy_int_queue(struct udevice *dev, struct usb_device *udev,
 352                                  struct int_queue *queue)
 353{
 354        struct musb_host_data *host = dev_get_priv(dev);
 355        return _musb_destroy_int_queue(host, udev, queue);
 356}
 357
 358static int musb_reset_root_port(struct udevice *dev, struct usb_device *udev)
 359{
 360        struct musb_host_data *host = dev_get_priv(dev);
 361        return _musb_reset_root_port(host, udev);
 362}
 363
 364struct dm_usb_ops musb_usb_ops = {
 365        .control = musb_submit_control_msg,
 366        .bulk = musb_submit_bulk_msg,
 367        .interrupt = musb_submit_int_msg,
 368        .create_int_queue = musb_create_int_queue,
 369        .poll_int_queue = musb_poll_int_queue,
 370        .destroy_int_queue = musb_destroy_int_queue,
 371        .reset_root_port = musb_reset_root_port,
 372};
 373#endif /* CONFIG_DM_USB */
 374#endif /* CONFIG_USB_MUSB_HOST */
 375
 376#ifdef CONFIG_USB_MUSB_GADGET
 377static struct musb *gadget;
 378
 379int usb_gadget_handle_interrupts(int index)
 380{
 381        WATCHDOG_RESET();
 382        if (!gadget || !gadget->isr)
 383                return -EINVAL;
 384
 385        return gadget->isr(0, gadget);
 386}
 387
 388int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 389{
 390        int ret;
 391
 392        if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind ||
 393            !driver->setup) {
 394                printf("bad parameter.\n");
 395                return -EINVAL;
 396        }
 397
 398        if (!gadget) {
 399                printf("Controller uninitialized\n");
 400                return -ENXIO;
 401        }
 402
 403        ret = musb_gadget_start(&gadget->g, driver);
 404        if (ret < 0) {
 405                printf("gadget_start failed with %d\n", ret);
 406                return ret;
 407        }
 408
 409        ret = driver->bind(&gadget->g);
 410        if (ret < 0) {
 411                printf("bind failed with %d\n", ret);
 412                return ret;
 413        }
 414
 415        return 0;
 416}
 417
 418int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 419{
 420        if (driver->disconnect)
 421                driver->disconnect(&gadget->g);
 422        if (driver->unbind)
 423                driver->unbind(&gadget->g);
 424        return 0;
 425}
 426#endif /* CONFIG_USB_MUSB_GADGET */
 427
 428int musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
 429                        void *ctl_regs)
 430{
 431        struct musb **musbp;
 432
 433        switch (plat->mode) {
 434#if defined(CONFIG_USB_MUSB_HOST) && !defined(CONFIG_DM_USB)
 435        case MUSB_HOST:
 436                musbp = &musb_host.host;
 437                break;
 438#endif
 439#ifdef CONFIG_USB_MUSB_GADGET
 440        case MUSB_PERIPHERAL:
 441                musbp = &gadget;
 442                break;
 443#endif
 444        default:
 445                return -EINVAL;
 446        }
 447
 448        *musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs);
 449        if (!*musbp) {
 450                printf("Failed to init the controller\n");
 451                return -EIO;
 452        }
 453
 454        return 0;
 455}
 456