uboot/drivers/usb/gadget/f_rockusb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2017
   4 *
   5 * Eddie Cai <eddie.cai.linux@gmail.com>
   6 */
   7#include <config.h>
   8#include <common.h>
   9#include <env.h>
  10#include <errno.h>
  11#include <malloc.h>
  12#include <memalign.h>
  13#include <linux/usb/ch9.h>
  14#include <linux/usb/gadget.h>
  15#include <linux/usb/composite.h>
  16#include <linux/compiler.h>
  17#include <version.h>
  18#include <g_dnl.h>
  19#include <asm/arch-rockchip/f_rockusb.h>
  20
  21static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)
  22{
  23        return container_of(f, struct f_rockusb, usb_function);
  24}
  25
  26static struct usb_endpoint_descriptor fs_ep_in = {
  27        .bLength            = USB_DT_ENDPOINT_SIZE,
  28        .bDescriptorType    = USB_DT_ENDPOINT,
  29        .bEndpointAddress   = USB_DIR_IN,
  30        .bmAttributes       = USB_ENDPOINT_XFER_BULK,
  31        .wMaxPacketSize     = cpu_to_le16(64),
  32};
  33
  34static struct usb_endpoint_descriptor fs_ep_out = {
  35        .bLength                = USB_DT_ENDPOINT_SIZE,
  36        .bDescriptorType        = USB_DT_ENDPOINT,
  37        .bEndpointAddress       = USB_DIR_OUT,
  38        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
  39        .wMaxPacketSize         = cpu_to_le16(64),
  40};
  41
  42static struct usb_endpoint_descriptor hs_ep_in = {
  43        .bLength                = USB_DT_ENDPOINT_SIZE,
  44        .bDescriptorType        = USB_DT_ENDPOINT,
  45        .bEndpointAddress       = USB_DIR_IN,
  46        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
  47        .wMaxPacketSize         = cpu_to_le16(512),
  48};
  49
  50static struct usb_endpoint_descriptor hs_ep_out = {
  51        .bLength                = USB_DT_ENDPOINT_SIZE,
  52        .bDescriptorType        = USB_DT_ENDPOINT,
  53        .bEndpointAddress       = USB_DIR_OUT,
  54        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
  55        .wMaxPacketSize         = cpu_to_le16(512),
  56};
  57
  58static struct usb_interface_descriptor interface_desc = {
  59        .bLength                = USB_DT_INTERFACE_SIZE,
  60        .bDescriptorType        = USB_DT_INTERFACE,
  61        .bInterfaceNumber       = 0x00,
  62        .bAlternateSetting      = 0x00,
  63        .bNumEndpoints          = 0x02,
  64        .bInterfaceClass        = ROCKUSB_INTERFACE_CLASS,
  65        .bInterfaceSubClass     = ROCKUSB_INTERFACE_SUB_CLASS,
  66        .bInterfaceProtocol     = ROCKUSB_INTERFACE_PROTOCOL,
  67};
  68
  69static struct usb_descriptor_header *rkusb_fs_function[] = {
  70        (struct usb_descriptor_header *)&interface_desc,
  71        (struct usb_descriptor_header *)&fs_ep_in,
  72        (struct usb_descriptor_header *)&fs_ep_out,
  73};
  74
  75static struct usb_descriptor_header *rkusb_hs_function[] = {
  76        (struct usb_descriptor_header *)&interface_desc,
  77        (struct usb_descriptor_header *)&hs_ep_in,
  78        (struct usb_descriptor_header *)&hs_ep_out,
  79        NULL,
  80};
  81
  82static const char rkusb_name[] = "Rockchip Rockusb";
  83
  84static struct usb_string rkusb_string_defs[] = {
  85        [0].s = rkusb_name,
  86        {  }                    /* end of list */
  87};
  88
  89static struct usb_gadget_strings stringtab_rkusb = {
  90        .language       = 0x0409,       /* en-us */
  91        .strings        = rkusb_string_defs,
  92};
  93
  94static struct usb_gadget_strings *rkusb_strings[] = {
  95        &stringtab_rkusb,
  96        NULL,
  97};
  98
  99static struct f_rockusb *rockusb_func;
 100static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
 101static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size);
 102
 103struct f_rockusb *get_rkusb(void)
 104{
 105        struct f_rockusb *f_rkusb = rockusb_func;
 106
 107        if (!f_rkusb) {
 108                f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_rkusb));
 109                if (!f_rkusb)
 110                        return 0;
 111
 112                rockusb_func = f_rkusb;
 113                memset(f_rkusb, 0, sizeof(*f_rkusb));
 114        }
 115
 116        if (!f_rkusb->buf_head) {
 117                f_rkusb->buf_head = memalign(CONFIG_SYS_CACHELINE_SIZE,
 118                                             RKUSB_BUF_SIZE);
 119                if (!f_rkusb->buf_head)
 120                        return 0;
 121
 122                f_rkusb->buf = f_rkusb->buf_head;
 123                memset(f_rkusb->buf_head, 0, RKUSB_BUF_SIZE);
 124        }
 125        return f_rkusb;
 126}
 127
 128static struct usb_endpoint_descriptor *rkusb_ep_desc(
 129struct usb_gadget *g,
 130struct usb_endpoint_descriptor *fs,
 131struct usb_endpoint_descriptor *hs)
 132{
 133        if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 134                return hs;
 135        return fs;
 136}
 137
 138static void rockusb_complete(struct usb_ep *ep, struct usb_request *req)
 139{
 140        int status = req->status;
 141
 142        if (!status)
 143                return;
 144        debug("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual);
 145}
 146
 147/* config the rockusb device*/
 148static int rockusb_bind(struct usb_configuration *c, struct usb_function *f)
 149{
 150        int id;
 151        struct usb_gadget *gadget = c->cdev->gadget;
 152        struct f_rockusb *f_rkusb = func_to_rockusb(f);
 153        const char *s;
 154
 155        id = usb_interface_id(c, f);
 156        if (id < 0)
 157                return id;
 158        interface_desc.bInterfaceNumber = id;
 159
 160        id = usb_string_id(c->cdev);
 161        if (id < 0)
 162                return id;
 163
 164        rkusb_string_defs[0].id = id;
 165        interface_desc.iInterface = id;
 166
 167        f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
 168        if (!f_rkusb->in_ep)
 169                return -ENODEV;
 170        f_rkusb->in_ep->driver_data = c->cdev;
 171
 172        f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
 173        if (!f_rkusb->out_ep)
 174                return -ENODEV;
 175        f_rkusb->out_ep->driver_data = c->cdev;
 176
 177        f->descriptors = rkusb_fs_function;
 178
 179        if (gadget_is_dualspeed(gadget)) {
 180                hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
 181                hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
 182                f->hs_descriptors = rkusb_hs_function;
 183        }
 184
 185        s = env_get("serial#");
 186        if (s)
 187                g_dnl_set_serialnumber((char *)s);
 188
 189        return 0;
 190}
 191
 192static void rockusb_unbind(struct usb_configuration *c, struct usb_function *f)
 193{
 194        /* clear the configuration*/
 195        memset(rockusb_func, 0, sizeof(*rockusb_func));
 196}
 197
 198static void rockusb_disable(struct usb_function *f)
 199{
 200        struct f_rockusb *f_rkusb = func_to_rockusb(f);
 201
 202        usb_ep_disable(f_rkusb->out_ep);
 203        usb_ep_disable(f_rkusb->in_ep);
 204
 205        if (f_rkusb->out_req) {
 206                free(f_rkusb->out_req->buf);
 207                usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req);
 208                f_rkusb->out_req = NULL;
 209        }
 210        if (f_rkusb->in_req) {
 211                free(f_rkusb->in_req->buf);
 212                usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);
 213                f_rkusb->in_req = NULL;
 214        }
 215        if (f_rkusb->buf_head) {
 216                free(f_rkusb->buf_head);
 217                f_rkusb->buf_head = NULL;
 218                f_rkusb->buf = NULL;
 219        }
 220}
 221
 222static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
 223{
 224        struct usb_request *req;
 225
 226        req = usb_ep_alloc_request(ep, 0);
 227        if (!req)
 228                return NULL;
 229
 230        req->length = EP_BUFFER_SIZE;
 231        req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
 232        if (!req->buf) {
 233                usb_ep_free_request(ep, req);
 234                return NULL;
 235        }
 236        memset(req->buf, 0, req->length);
 237
 238        return req;
 239}
 240
 241static int rockusb_set_alt(struct usb_function *f, unsigned int interface,
 242                           unsigned int alt)
 243{
 244        int ret;
 245        struct usb_composite_dev *cdev = f->config->cdev;
 246        struct usb_gadget *gadget = cdev->gadget;
 247        struct f_rockusb *f_rkusb = func_to_rockusb(f);
 248        const struct usb_endpoint_descriptor *d;
 249
 250        debug("%s: func: %s intf: %d alt: %d\n",
 251              __func__, f->name, interface, alt);
 252
 253        d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
 254        ret = usb_ep_enable(f_rkusb->out_ep, d);
 255        if (ret) {
 256                printf("failed to enable out ep\n");
 257                return ret;
 258        }
 259
 260        f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
 261        if (!f_rkusb->out_req) {
 262                printf("failed to alloc out req\n");
 263                ret = -EINVAL;
 264                goto err;
 265        }
 266        f_rkusb->out_req->complete = rx_handler_command;
 267
 268        d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
 269        ret = usb_ep_enable(f_rkusb->in_ep, d);
 270        if (ret) {
 271                printf("failed to enable in ep\n");
 272                goto err;
 273        }
 274
 275        f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
 276        if (!f_rkusb->in_req) {
 277                printf("failed alloc req in\n");
 278                ret = -EINVAL;
 279                goto err;
 280        }
 281        f_rkusb->in_req->complete = rockusb_complete;
 282
 283        ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
 284        if (ret)
 285                goto err;
 286
 287        return 0;
 288err:
 289        rockusb_disable(f);
 290        return ret;
 291}
 292
 293static int rockusb_add(struct usb_configuration *c)
 294{
 295        struct f_rockusb *f_rkusb = get_rkusb();
 296        int status;
 297
 298        debug("%s: cdev: 0x%p\n", __func__, c->cdev);
 299
 300        f_rkusb->usb_function.name = "f_rockusb";
 301        f_rkusb->usb_function.bind = rockusb_bind;
 302        f_rkusb->usb_function.unbind = rockusb_unbind;
 303        f_rkusb->usb_function.set_alt = rockusb_set_alt;
 304        f_rkusb->usb_function.disable = rockusb_disable;
 305        f_rkusb->usb_function.strings = rkusb_strings;
 306
 307        status = usb_add_function(c, &f_rkusb->usb_function);
 308        if (status) {
 309                free(f_rkusb);
 310                rockusb_func = f_rkusb;
 311        }
 312        return status;
 313}
 314
 315void rockusb_dev_init(char *dev_type, int dev_index)
 316{
 317        struct f_rockusb *f_rkusb = get_rkusb();
 318
 319        f_rkusb->dev_type = dev_type;
 320        f_rkusb->dev_index = dev_index;
 321}
 322
 323DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
 324
 325static int rockusb_tx_write(const char *buffer, unsigned int buffer_size)
 326{
 327        struct usb_request *in_req = rockusb_func->in_req;
 328        int ret;
 329
 330        memcpy(in_req->buf, buffer, buffer_size);
 331        in_req->length = buffer_size;
 332        debug("Transferring 0x%x bytes\n", buffer_size);
 333        usb_ep_dequeue(rockusb_func->in_ep, in_req);
 334        ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
 335        if (ret)
 336                printf("Error %d on queue\n", ret);
 337        return 0;
 338}
 339
 340static int rockusb_tx_write_str(const char *buffer)
 341{
 342        return rockusb_tx_write(buffer, strlen(buffer));
 343}
 344
 345#ifdef DEBUG
 346static void printcbw(char *buf)
 347{
 348        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 349                                 sizeof(struct fsg_bulk_cb_wrap));
 350
 351        memcpy((char *)cbw, buf, USB_BULK_CB_WRAP_LEN);
 352
 353        debug("cbw: signature:%x\n", cbw->signature);
 354        debug("cbw: tag=%x\n", cbw->tag);
 355        debug("cbw: data_transfer_length=%d\n", cbw->data_transfer_length);
 356        debug("cbw: flags=%x\n", cbw->flags);
 357        debug("cbw: lun=%d\n", cbw->lun);
 358        debug("cbw: length=%d\n", cbw->length);
 359        debug("cbw: ucOperCode=%x\n", cbw->CDB[0]);
 360        debug("cbw: ucReserved=%x\n", cbw->CDB[1]);
 361        debug("cbw: dwAddress:%x %x %x %x\n", cbw->CDB[5], cbw->CDB[4],
 362              cbw->CDB[3], cbw->CDB[2]);
 363        debug("cbw: ucReserved2=%x\n", cbw->CDB[6]);
 364        debug("cbw: uslength:%x %x\n", cbw->CDB[8], cbw->CDB[7]);
 365}
 366
 367static void printcsw(char *buf)
 368{
 369        ALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw,
 370                                 sizeof(struct bulk_cs_wrap));
 371        memcpy((char *)csw, buf, USB_BULK_CS_WRAP_LEN);
 372        debug("csw: signature:%x\n", csw->signature);
 373        debug("csw: tag:%x\n", csw->tag);
 374        debug("csw: residue:%x\n", csw->residue);
 375        debug("csw: status:%x\n", csw->status);
 376}
 377#endif
 378
 379static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size)
 380{
 381        ALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw,
 382                                 sizeof(struct bulk_cs_wrap));
 383        csw->signature = cpu_to_le32(USB_BULK_CS_SIG);
 384        csw->tag = tag;
 385        csw->residue = cpu_to_be32(residue);
 386        csw->status = status;
 387#ifdef DEBUG
 388        printcsw((char *)csw);
 389#endif
 390        return rockusb_tx_write((char *)csw, size);
 391}
 392
 393static void tx_handler_send_csw(struct usb_ep *ep, struct usb_request *req)
 394{
 395        struct f_rockusb *f_rkusb = get_rkusb();
 396        int status = req->status;
 397
 398        if (status)
 399                debug("status: %d ep '%s' trans: %d\n",
 400                      status, ep->name, req->actual);
 401
 402        /* Return back to default in_req complete function after sending CSW */
 403        req->complete = rockusb_complete;
 404        rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD, USB_BULK_CS_WRAP_LEN);
 405}
 406
 407static unsigned int rx_bytes_expected(struct usb_ep *ep)
 408{
 409        struct f_rockusb *f_rkusb = get_rkusb();
 410        int rx_remain = f_rkusb->dl_size - f_rkusb->dl_bytes;
 411        unsigned int rem;
 412        unsigned int maxpacket = ep->maxpacket;
 413
 414        if (rx_remain <= 0)
 415                return 0;
 416        else if (rx_remain > EP_BUFFER_SIZE)
 417                return EP_BUFFER_SIZE;
 418
 419        rem = rx_remain % maxpacket;
 420        if (rem > 0)
 421                rx_remain = rx_remain + (maxpacket - rem);
 422
 423        return rx_remain;
 424}
 425
 426/* usb_request complete call back to handle upload image */
 427static void tx_handler_ul_image(struct usb_ep *ep, struct usb_request *req)
 428{
 429        ALLOC_CACHE_ALIGN_BUFFER(char, rbuffer, RKBLOCK_BUF_SIZE);
 430        struct f_rockusb *f_rkusb = get_rkusb();
 431        struct usb_request *in_req = rockusb_func->in_req;
 432        int ret;
 433
 434        /* Print error status of previous transfer */
 435        if (req->status)
 436                debug("status: %d ep '%s' trans: %d len %d\n", req->status,
 437                      ep->name, req->actual, req->length);
 438
 439        /* On transfer complete reset in_req and feedback host with CSW_GOOD */
 440        if (f_rkusb->ul_bytes >= f_rkusb->ul_size) {
 441                in_req->length = 0;
 442                in_req->complete = rockusb_complete;
 443
 444                rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD,
 445                                     USB_BULK_CS_WRAP_LEN);
 446                return;
 447        }
 448
 449        /* Proceed with current chunk */
 450        unsigned int transfer_size = f_rkusb->ul_size - f_rkusb->ul_bytes;
 451
 452        if (transfer_size > RKBLOCK_BUF_SIZE)
 453                transfer_size = RKBLOCK_BUF_SIZE;
 454        /* Read at least one block */
 455        unsigned int blkcount = (transfer_size + f_rkusb->desc->blksz - 1) /
 456                                f_rkusb->desc->blksz;
 457
 458        debug("ul %x bytes, %x blks, read lba %x, ul_size:%x, ul_bytes:%x, ",
 459              transfer_size, blkcount, f_rkusb->lba,
 460              f_rkusb->ul_size, f_rkusb->ul_bytes);
 461
 462        int blks = blk_dread(f_rkusb->desc, f_rkusb->lba, blkcount, rbuffer);
 463
 464        if (blks != blkcount) {
 465                printf("failed reading from device %s: %d\n",
 466                       f_rkusb->dev_type, f_rkusb->dev_index);
 467                rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
 468                                     USB_BULK_CS_WRAP_LEN);
 469                return;
 470        }
 471        f_rkusb->lba += blkcount;
 472        f_rkusb->ul_bytes += transfer_size;
 473
 474        /* Proceed with USB request */
 475        memcpy(in_req->buf, rbuffer, transfer_size);
 476        in_req->length = transfer_size;
 477        in_req->complete = tx_handler_ul_image;
 478        debug("Uploading 0x%x bytes\n", transfer_size);
 479        usb_ep_dequeue(rockusb_func->in_ep, in_req);
 480        ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
 481        if (ret)
 482                printf("Error %d on queue\n", ret);
 483}
 484
 485/* usb_request complete call back to handle down load image */
 486static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
 487{
 488        struct f_rockusb *f_rkusb = get_rkusb();
 489        unsigned int transfer_size = 0;
 490        const unsigned char *buffer = req->buf;
 491        unsigned int buffer_size = req->actual;
 492
 493        transfer_size = f_rkusb->dl_size - f_rkusb->dl_bytes;
 494
 495        if (req->status != 0) {
 496                printf("Bad status: %d\n", req->status);
 497                rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
 498                                     USB_BULK_CS_WRAP_LEN);
 499                return;
 500        }
 501
 502        if (buffer_size < transfer_size)
 503                transfer_size = buffer_size;
 504
 505        memcpy((void *)f_rkusb->buf, buffer, transfer_size);
 506        f_rkusb->dl_bytes += transfer_size;
 507        int blks = 0, blkcnt = transfer_size  / f_rkusb->desc->blksz;
 508
 509        debug("dl %x bytes, %x blks, write lba %x, dl_size:%x, dl_bytes:%x, ",
 510              transfer_size, blkcnt, f_rkusb->lba, f_rkusb->dl_size,
 511              f_rkusb->dl_bytes);
 512        blks = blk_dwrite(f_rkusb->desc, f_rkusb->lba, blkcnt, f_rkusb->buf);
 513        if (blks != blkcnt) {
 514                printf("failed writing to device %s: %d\n", f_rkusb->dev_type,
 515                       f_rkusb->dev_index);
 516                rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
 517                                     USB_BULK_CS_WRAP_LEN);
 518                return;
 519        }
 520        f_rkusb->lba += blkcnt;
 521
 522        /* Check if transfer is done */
 523        if (f_rkusb->dl_bytes >= f_rkusb->dl_size) {
 524                req->complete = rx_handler_command;
 525                req->length = EP_BUFFER_SIZE;
 526                f_rkusb->buf = f_rkusb->buf_head;
 527                debug("transfer 0x%x bytes done\n", f_rkusb->dl_size);
 528                f_rkusb->dl_size = 0;
 529                rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD,
 530                                     USB_BULK_CS_WRAP_LEN);
 531        } else {
 532                req->length = rx_bytes_expected(ep);
 533                if (f_rkusb->buf == f_rkusb->buf_head)
 534                        f_rkusb->buf = f_rkusb->buf_head + EP_BUFFER_SIZE;
 535                else
 536                        f_rkusb->buf = f_rkusb->buf_head;
 537
 538                debug("remain %x bytes, %lx sectors\n", req->length,
 539                      req->length / f_rkusb->desc->blksz);
 540        }
 541
 542        req->actual = 0;
 543        usb_ep_queue(ep, req, 0);
 544}
 545
 546static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request *req)
 547{
 548        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 549                                 sizeof(struct fsg_bulk_cb_wrap));
 550
 551        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 552
 553        rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,
 554                             CSW_GOOD, USB_BULK_CS_WRAP_LEN);
 555}
 556
 557static void cb_read_storage_id(struct usb_ep *ep, struct usb_request *req)
 558{
 559        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 560                                 sizeof(struct fsg_bulk_cb_wrap));
 561        struct f_rockusb *f_rkusb = get_rkusb();
 562        char emmc_id[] = "EMMC ";
 563
 564        printf("read storage id\n");
 565        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 566
 567        /* Prepare for sending subsequent CSW_GOOD */
 568        f_rkusb->tag = cbw->tag;
 569        f_rkusb->in_req->complete = tx_handler_send_csw;
 570
 571        rockusb_tx_write_str(emmc_id);
 572}
 573
 574int __weak rk_get_bootrom_chip_version(unsigned int *chip_info, int size)
 575{
 576        return 0;
 577}
 578
 579static void cb_get_chip_version(struct usb_ep *ep, struct usb_request *req)
 580{
 581        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 582                                 sizeof(struct fsg_bulk_cb_wrap));
 583        struct f_rockusb *f_rkusb = get_rkusb();
 584        unsigned int chip_info[4], i;
 585
 586        memset(chip_info, 0, sizeof(chip_info));
 587        rk_get_bootrom_chip_version(chip_info, 4);
 588
 589        /*
 590         * Chip Version is a string saved in BOOTROM address space Little Endian
 591         *
 592         * Ex for rk3288: 0x33323041 0x32303134 0x30383133 0x56323030
 593         * which brings:  320A20140813V200
 594         *
 595         * Note that memory version do invert MSB/LSB so printing the char
 596         * buffer will show: A02341023180002V
 597         */
 598        printf("read chip version: ");
 599        for (i = 0; i < 4; i++) {
 600                printf("%c%c%c%c",
 601                       (chip_info[i] >> 24) & 0xFF,
 602                       (chip_info[i] >> 16) & 0xFF,
 603                       (chip_info[i] >>  8) & 0xFF,
 604                       (chip_info[i] >>  0) & 0xFF);
 605        }
 606        printf("\n");
 607        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 608
 609        /* Prepare for sending subsequent CSW_GOOD */
 610        f_rkusb->tag = cbw->tag;
 611        f_rkusb->in_req->complete = tx_handler_send_csw;
 612
 613        rockusb_tx_write((char *)chip_info, sizeof(chip_info));
 614}
 615
 616static void cb_read_lba(struct usb_ep *ep, struct usb_request *req)
 617{
 618        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 619                                 sizeof(struct fsg_bulk_cb_wrap));
 620        struct f_rockusb *f_rkusb = get_rkusb();
 621        int sector_count;
 622
 623        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 624        sector_count = (int)get_unaligned_be16(&cbw->CDB[7]);
 625        f_rkusb->tag = cbw->tag;
 626
 627        if (!f_rkusb->desc) {
 628                char *type = f_rkusb->dev_type;
 629                int index = f_rkusb->dev_index;
 630
 631                f_rkusb->desc = blk_get_dev(type, index);
 632                if (!f_rkusb->desc ||
 633                    f_rkusb->desc->type == DEV_TYPE_UNKNOWN) {
 634                        printf("invalid device \"%s\", %d\n", type, index);
 635                        rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
 636                                             USB_BULK_CS_WRAP_LEN);
 637                        return;
 638                }
 639        }
 640
 641        f_rkusb->lba = get_unaligned_be32(&cbw->CDB[2]);
 642        f_rkusb->ul_size = sector_count * f_rkusb->desc->blksz;
 643        f_rkusb->ul_bytes = 0;
 644
 645        debug("require read %x bytes, %x sectors from lba %x\n",
 646              f_rkusb->ul_size, sector_count, f_rkusb->lba);
 647
 648        if (f_rkusb->ul_size == 0)  {
 649                rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,
 650                                     CSW_FAIL, USB_BULK_CS_WRAP_LEN);
 651                return;
 652        }
 653
 654        /* Start right now sending first chunk */
 655        tx_handler_ul_image(ep, req);
 656}
 657
 658static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)
 659{
 660        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 661                                 sizeof(struct fsg_bulk_cb_wrap));
 662        struct f_rockusb *f_rkusb = get_rkusb();
 663        int sector_count;
 664
 665        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 666        sector_count = (int)get_unaligned_be16(&cbw->CDB[7]);
 667        f_rkusb->tag = cbw->tag;
 668
 669        if (!f_rkusb->desc) {
 670                char *type = f_rkusb->dev_type;
 671                int index = f_rkusb->dev_index;
 672
 673                f_rkusb->desc = blk_get_dev(type, index);
 674                if (!f_rkusb->desc ||
 675                    f_rkusb->desc->type == DEV_TYPE_UNKNOWN) {
 676                        printf("invalid device \"%s\", %d\n", type, index);
 677                        rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
 678                                             USB_BULK_CS_WRAP_LEN);
 679                        return;
 680                }
 681        }
 682
 683        f_rkusb->lba = get_unaligned_be32(&cbw->CDB[2]);
 684        f_rkusb->dl_size = sector_count * f_rkusb->desc->blksz;
 685        f_rkusb->dl_bytes = 0;
 686
 687        debug("require write %x bytes, %x sectors to lba %x\n",
 688              f_rkusb->dl_size, sector_count, f_rkusb->lba);
 689
 690        if (f_rkusb->dl_size == 0)  {
 691                rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,
 692                                     CSW_FAIL, USB_BULK_CS_WRAP_LEN);
 693        } else {
 694                req->complete = rx_handler_dl_image;
 695                req->length = rx_bytes_expected(ep);
 696        }
 697}
 698
 699static void cb_erase_lba(struct usb_ep *ep, struct usb_request *req)
 700{
 701        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 702                                 sizeof(struct fsg_bulk_cb_wrap));
 703        struct f_rockusb *f_rkusb = get_rkusb();
 704        int sector_count, lba, blks;
 705
 706        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 707        sector_count = (int)get_unaligned_be16(&cbw->CDB[7]);
 708        f_rkusb->tag = cbw->tag;
 709
 710        if (!f_rkusb->desc) {
 711                char *type = f_rkusb->dev_type;
 712                int index = f_rkusb->dev_index;
 713
 714                f_rkusb->desc = blk_get_dev(type, index);
 715                if (!f_rkusb->desc ||
 716                    f_rkusb->desc->type == DEV_TYPE_UNKNOWN) {
 717                        printf("invalid device \"%s\", %d\n", type, index);
 718                        rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
 719                                             USB_BULK_CS_WRAP_LEN);
 720                        return;
 721                }
 722        }
 723
 724        lba = get_unaligned_be32(&cbw->CDB[2]);
 725
 726        debug("require erase %x sectors from lba %x\n",
 727              sector_count, lba);
 728
 729        blks = blk_derase(f_rkusb->desc, lba, sector_count);
 730        if (blks != sector_count) {
 731                printf("failed erasing device %s: %d\n", f_rkusb->dev_type,
 732                       f_rkusb->dev_index);
 733                rockusb_tx_write_csw(f_rkusb->tag,
 734                                     cbw->data_transfer_length, CSW_FAIL,
 735                                     USB_BULK_CS_WRAP_LEN);
 736                return;
 737        }
 738
 739        rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD,
 740                             USB_BULK_CS_WRAP_LEN);
 741}
 742
 743void __weak rkusb_set_reboot_flag(int flag)
 744{
 745        struct f_rockusb *f_rkusb = get_rkusb();
 746
 747        printf("rockkusb set reboot flag: %d\n", f_rkusb->reboot_flag);
 748}
 749
 750static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
 751{
 752        struct f_rockusb *f_rkusb = get_rkusb();
 753
 754        rkusb_set_reboot_flag(f_rkusb->reboot_flag);
 755        do_reset(NULL, 0, 0, NULL);
 756}
 757
 758static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
 759{
 760        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 761                                 sizeof(struct fsg_bulk_cb_wrap));
 762        struct f_rockusb *f_rkusb = get_rkusb();
 763
 764        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 765        f_rkusb->reboot_flag = cbw->CDB[1];
 766        rockusb_func->in_req->complete = compl_do_reset;
 767        rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD,
 768                             USB_BULK_CS_WRAP_LEN);
 769}
 770
 771static void cb_not_support(struct usb_ep *ep, struct usb_request *req)
 772{
 773        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 774                                 sizeof(struct fsg_bulk_cb_wrap));
 775
 776        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 777        printf("Rockusb command %x not support yet\n", cbw->CDB[0]);
 778        rockusb_tx_write_csw(cbw->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN);
 779}
 780
 781static const struct cmd_dispatch_info cmd_dispatch_info[] = {
 782        {
 783                .cmd = K_FW_TEST_UNIT_READY,
 784                .cb = cb_test_unit_ready,
 785        },
 786        {
 787                .cmd = K_FW_READ_FLASH_ID,
 788                .cb = cb_read_storage_id,
 789        },
 790        {
 791                .cmd = K_FW_SET_DEVICE_ID,
 792                .cb = cb_not_support,
 793        },
 794        {
 795                .cmd = K_FW_TEST_BAD_BLOCK,
 796                .cb = cb_not_support,
 797        },
 798        {
 799                .cmd = K_FW_READ_10,
 800                .cb = cb_not_support,
 801        },
 802        {
 803                .cmd = K_FW_WRITE_10,
 804                .cb = cb_not_support,
 805        },
 806        {
 807                .cmd = K_FW_ERASE_10,
 808                .cb = cb_not_support,
 809        },
 810        {
 811                .cmd = K_FW_WRITE_SPARE,
 812                .cb = cb_not_support,
 813        },
 814        {
 815                .cmd = K_FW_READ_SPARE,
 816                .cb = cb_not_support,
 817        },
 818        {
 819                .cmd = K_FW_ERASE_10_FORCE,
 820                .cb = cb_not_support,
 821        },
 822        {
 823                .cmd = K_FW_GET_VERSION,
 824                .cb = cb_not_support,
 825        },
 826        {
 827                .cmd = K_FW_LBA_READ_10,
 828                .cb = cb_read_lba,
 829        },
 830        {
 831                .cmd = K_FW_LBA_WRITE_10,
 832                .cb = cb_write_lba,
 833        },
 834        {
 835                .cmd = K_FW_ERASE_SYS_DISK,
 836                .cb = cb_not_support,
 837        },
 838        {
 839                .cmd = K_FW_SDRAM_READ_10,
 840                .cb = cb_not_support,
 841        },
 842        {
 843                .cmd = K_FW_SDRAM_WRITE_10,
 844                .cb = cb_not_support,
 845        },
 846        {
 847                .cmd = K_FW_SDRAM_EXECUTE,
 848                .cb = cb_not_support,
 849        },
 850        {
 851                .cmd = K_FW_READ_FLASH_INFO,
 852                .cb = cb_not_support,
 853        },
 854        {
 855                .cmd = K_FW_GET_CHIP_VER,
 856                .cb = cb_get_chip_version,
 857        },
 858        {
 859                .cmd = K_FW_LOW_FORMAT,
 860                .cb = cb_not_support,
 861        },
 862        {
 863                .cmd = K_FW_SET_RESET_FLAG,
 864                .cb = cb_not_support,
 865        },
 866        {
 867                .cmd = K_FW_SPI_READ_10,
 868                .cb = cb_not_support,
 869        },
 870        {
 871                .cmd = K_FW_SPI_WRITE_10,
 872                .cb = cb_not_support,
 873        },
 874        {
 875                .cmd = K_FW_LBA_ERASE_10,
 876                .cb = cb_erase_lba,
 877        },
 878        {
 879                .cmd = K_FW_SESSION,
 880                .cb = cb_not_support,
 881        },
 882        {
 883                .cmd = K_FW_RESET,
 884                .cb = cb_reboot,
 885        },
 886};
 887
 888static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
 889{
 890        void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
 891
 892        ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
 893                                 sizeof(struct fsg_bulk_cb_wrap));
 894        char *cmdbuf = req->buf;
 895        int i;
 896
 897        if (req->status || req->length == 0)
 898                return;
 899
 900        memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
 901#ifdef DEBUG
 902        printcbw(req->buf);
 903#endif
 904
 905        for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
 906                if (cmd_dispatch_info[i].cmd == cbw->CDB[0]) {
 907                        func_cb = cmd_dispatch_info[i].cb;
 908                        break;
 909                }
 910        }
 911
 912        if (!func_cb) {
 913                printf("unknown command: %s\n", (char *)req->buf);
 914                rockusb_tx_write_str("FAILunknown command");
 915        } else {
 916                if (req->actual < req->length) {
 917                        u8 *buf = (u8 *)req->buf;
 918
 919                        buf[req->actual] = 0;
 920                        func_cb(ep, req);
 921                } else {
 922                        puts("buffer overflow\n");
 923                        rockusb_tx_write_str("FAILbuffer overflow");
 924                }
 925        }
 926
 927        *cmdbuf = '\0';
 928        req->actual = 0;
 929        usb_ep_queue(ep, req, 0);
 930}
 931