1f16e43f8SFrank Wang /* 2f16e43f8SFrank Wang * Copyright 2017 Rockchip Electronics Co., Ltd 3f16e43f8SFrank Wang * Frank Wang <frank.wang@rock-chips.com> 4f16e43f8SFrank Wang * 5f16e43f8SFrank Wang * SPDX-License-Identifier: GPL-2.0+ 6f16e43f8SFrank Wang */ 7f16e43f8SFrank Wang 8866d7966SJoseph Chen #include <asm/io.h> 9866d7966SJoseph Chen #include <asm/arch/boot_mode.h> 10829f2b85SFrank Wang #include <asm/arch/chip_info.h> 116f0347c8Stony.xu #include <optee_include/OpteeClientInterface.h> 120d0c3248SFrank Wang 130d0c3248SFrank Wang #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 140d0c3248SFrank Wang #include <asm/arch/vendor.h> 150d0c3248SFrank Wang #endif 160d0c3248SFrank Wang 17f16e43f8SFrank Wang #include <rockusb.h> 18f16e43f8SFrank Wang 19f16e43f8SFrank Wang #define ROCKUSB_INTERFACE_CLASS 0xff 20f16e43f8SFrank Wang #define ROCKUSB_INTERFACE_SUB_CLASS 0x06 21f16e43f8SFrank Wang #define ROCKUSB_INTERFACE_PROTOCOL 0x05 22f16e43f8SFrank Wang 23f16e43f8SFrank Wang static struct usb_interface_descriptor rkusb_intf_desc = { 24f16e43f8SFrank Wang .bLength = USB_DT_INTERFACE_SIZE, 25f16e43f8SFrank Wang .bDescriptorType = USB_DT_INTERFACE, 26f16e43f8SFrank Wang .bInterfaceNumber = 0x00, 27f16e43f8SFrank Wang .bAlternateSetting = 0x00, 28f16e43f8SFrank Wang .bNumEndpoints = 0x02, 29f16e43f8SFrank Wang .bInterfaceClass = ROCKUSB_INTERFACE_CLASS, 30f16e43f8SFrank Wang .bInterfaceSubClass = ROCKUSB_INTERFACE_SUB_CLASS, 31f16e43f8SFrank Wang .bInterfaceProtocol = ROCKUSB_INTERFACE_PROTOCOL, 32f16e43f8SFrank Wang }; 33f16e43f8SFrank Wang 34f16e43f8SFrank Wang static struct usb_descriptor_header *rkusb_fs_function[] = { 35f16e43f8SFrank Wang (struct usb_descriptor_header *)&rkusb_intf_desc, 36f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_fs_bulk_in_desc, 37f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_fs_bulk_out_desc, 38f16e43f8SFrank Wang NULL, 39f16e43f8SFrank Wang }; 40f16e43f8SFrank Wang 41f16e43f8SFrank Wang static struct usb_descriptor_header *rkusb_hs_function[] = { 42f16e43f8SFrank Wang (struct usb_descriptor_header *)&rkusb_intf_desc, 43f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_hs_bulk_in_desc, 44f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_hs_bulk_out_desc, 45f16e43f8SFrank Wang NULL, 46f16e43f8SFrank Wang }; 47f16e43f8SFrank Wang 48f16e43f8SFrank Wang struct rk_flash_info { 49f16e43f8SFrank Wang u32 flash_size; 50f16e43f8SFrank Wang u16 block_size; 51f16e43f8SFrank Wang u8 page_size; 52f16e43f8SFrank Wang u8 ecc_bits; 53f16e43f8SFrank Wang u8 access_time; 54f16e43f8SFrank Wang u8 manufacturer; 55f16e43f8SFrank Wang u8 flash_mask; 56f16e43f8SFrank Wang } __packed; 57f16e43f8SFrank Wang 585b081643SFrank Wang static int rkusb_rst_code; /* The subcode in reset command (0xFF) */ 595b081643SFrank Wang 60f16e43f8SFrank Wang int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) 61f16e43f8SFrank Wang { 62ba437c8cSFrank Wang if (IS_RKUSB_UMS_DNL(name)) { 63c0acb0f2SFrank Wang /* Fix to Rockchip's VID and PID */ 64ba437c8cSFrank Wang dev->idVendor = __constant_cpu_to_le16(0x2207); 65ba437c8cSFrank Wang dev->idProduct = __constant_cpu_to_le16(CONFIG_ROCKUSB_G_DNL_PID); 66ba437c8cSFrank Wang 67f16e43f8SFrank Wang /* Enumerate as a loader device */ 68f16e43f8SFrank Wang dev->bcdUSB = cpu_to_le16(0x0201); 69c0acb0f2SFrank Wang } else if (!strncmp(name, "usb_dnl_fastboot", 16)) { 70c0acb0f2SFrank Wang /* Fix to Google's VID and PID */ 71c0acb0f2SFrank Wang dev->idVendor = __constant_cpu_to_le16(0x18d1); 72c0acb0f2SFrank Wang dev->idProduct = __constant_cpu_to_le16(0xd00d); 73ba437c8cSFrank Wang } 74f16e43f8SFrank Wang 75f16e43f8SFrank Wang return 0; 76f16e43f8SFrank Wang } 77f16e43f8SFrank Wang 78f16e43f8SFrank Wang __maybe_unused 79f16e43f8SFrank Wang static inline void dump_cbw(struct fsg_bulk_cb_wrap *cbw) 80f16e43f8SFrank Wang { 81f16e43f8SFrank Wang assert(!cbw); 82f16e43f8SFrank Wang 83f16e43f8SFrank Wang debug("%s:\n", __func__); 84f16e43f8SFrank Wang debug("Signature %x\n", cbw->Signature); 85f16e43f8SFrank Wang debug("Tag %x\n", cbw->Tag); 86f16e43f8SFrank Wang debug("DataTransferLength %x\n", cbw->DataTransferLength); 87f16e43f8SFrank Wang debug("Flags %x\n", cbw->Flags); 88f16e43f8SFrank Wang debug("LUN %x\n", cbw->Lun); 89f16e43f8SFrank Wang debug("Length %x\n", cbw->Length); 90f16e43f8SFrank Wang debug("OptionCode %x\n", cbw->CDB[0]); 91f16e43f8SFrank Wang debug("SubCode %x\n", cbw->CDB[1]); 92f16e43f8SFrank Wang debug("SectorAddr %x\n", get_unaligned_be32(&cbw->CDB[2])); 93f16e43f8SFrank Wang debug("BlkSectors %x\n\n", get_unaligned_be16(&cbw->CDB[7])); 94f16e43f8SFrank Wang } 95f16e43f8SFrank Wang 96f16e43f8SFrank Wang static int rkusb_check_lun(struct fsg_common *common) 97f16e43f8SFrank Wang { 98f16e43f8SFrank Wang struct fsg_lun *curlun; 99f16e43f8SFrank Wang 100f16e43f8SFrank Wang /* Check the LUN */ 101f16e43f8SFrank Wang if (common->lun >= 0 && common->lun < common->nluns) { 102f16e43f8SFrank Wang curlun = &common->luns[common->lun]; 103f16e43f8SFrank Wang if (common->cmnd[0] != SC_REQUEST_SENSE) { 104f16e43f8SFrank Wang curlun->sense_data = SS_NO_SENSE; 105f16e43f8SFrank Wang curlun->info_valid = 0; 106f16e43f8SFrank Wang } 107f16e43f8SFrank Wang } else { 108f16e43f8SFrank Wang curlun = NULL; 109f16e43f8SFrank Wang common->bad_lun_okay = 0; 110f16e43f8SFrank Wang 111f16e43f8SFrank Wang /* 112f16e43f8SFrank Wang * INQUIRY and REQUEST SENSE commands are explicitly allowed 113f16e43f8SFrank Wang * to use unsupported LUNs; all others may not. 114f16e43f8SFrank Wang */ 115f16e43f8SFrank Wang if (common->cmnd[0] != SC_INQUIRY && 116f16e43f8SFrank Wang common->cmnd[0] != SC_REQUEST_SENSE) { 117f16e43f8SFrank Wang debug("unsupported LUN %d\n", common->lun); 118f16e43f8SFrank Wang return -EINVAL; 119f16e43f8SFrank Wang } 120f16e43f8SFrank Wang } 121f16e43f8SFrank Wang 122f16e43f8SFrank Wang return 0; 123f16e43f8SFrank Wang } 124f16e43f8SFrank Wang 125f16e43f8SFrank Wang static void __do_reset(struct usb_ep *ep, struct usb_request *req) 126f16e43f8SFrank Wang { 1275b081643SFrank Wang u32 boot_flag = BOOT_NORMAL; 1285b081643SFrank Wang 1295b081643SFrank Wang if (rkusb_rst_code == 0x03) 1305b081643SFrank Wang boot_flag = BOOT_BROM_DOWNLOAD; 1315b081643SFrank Wang 1325b081643SFrank Wang rkusb_rst_code = 0; /* restore to default */ 1335b081643SFrank Wang writel(boot_flag, (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG); 134866d7966SJoseph Chen 135f16e43f8SFrank Wang do_reset(NULL, 0, 0, NULL); 136f16e43f8SFrank Wang } 137f16e43f8SFrank Wang 138f16e43f8SFrank Wang static int rkusb_do_reset(struct fsg_common *common, 139f16e43f8SFrank Wang struct fsg_buffhd *bh) 140f16e43f8SFrank Wang { 141f16e43f8SFrank Wang common->data_size_from_cmnd = common->cmnd[4]; 142f16e43f8SFrank Wang common->residue = 0; 143f16e43f8SFrank Wang bh->inreq->complete = __do_reset; 144f16e43f8SFrank Wang bh->state = BUF_STATE_EMPTY; 145f16e43f8SFrank Wang 1465b081643SFrank Wang rkusb_rst_code = !common->cmnd[1] ? 0xff : common->cmnd[1]; 147f16e43f8SFrank Wang return 0; 148f16e43f8SFrank Wang } 149f16e43f8SFrank Wang 150f16e43f8SFrank Wang static int rkusb_do_test_unit_ready(struct fsg_common *common, 151f16e43f8SFrank Wang struct fsg_buffhd *bh) 152f16e43f8SFrank Wang { 153f16e43f8SFrank Wang common->residue = 0x06 << 24; /* Max block xfer support from host */ 154f16e43f8SFrank Wang common->data_dir = DATA_DIR_NONE; 155f16e43f8SFrank Wang bh->state = BUF_STATE_EMPTY; 156f16e43f8SFrank Wang 157f16e43f8SFrank Wang return 0; 158f16e43f8SFrank Wang } 159f16e43f8SFrank Wang 160f16e43f8SFrank Wang static int rkusb_do_read_flash_id(struct fsg_common *common, 161f16e43f8SFrank Wang struct fsg_buffhd *bh) 162f16e43f8SFrank Wang { 163f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 164e0023032SKever Yang u32 len = 5; 165d7386f60SFrank Wang enum if_type type = ums[common->lun].block_dev.if_type; 166f16e43f8SFrank Wang 167d7386f60SFrank Wang if (type == IF_TYPE_MMC) 168f16e43f8SFrank Wang memcpy((void *)&buf[0], "EMMC ", 5); 169d7386f60SFrank Wang else if (type == IF_TYPE_RKNAND) 170d7386f60SFrank Wang memcpy((void *)&buf[0], "NAND ", 5); 171d7386f60SFrank Wang else 172d7386f60SFrank Wang memcpy((void *)&buf[0], "UNKN ", 5); /* unknown */ 173f16e43f8SFrank Wang 174f16e43f8SFrank Wang /* Set data xfer size */ 175f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 176e0023032SKever Yang common->data_size = len; 177f16e43f8SFrank Wang 178f16e43f8SFrank Wang return len; 179f16e43f8SFrank Wang } 180f16e43f8SFrank Wang 181f16e43f8SFrank Wang static int rkusb_do_test_bad_block(struct fsg_common *common, 182f16e43f8SFrank Wang struct fsg_buffhd *bh) 183f16e43f8SFrank Wang { 184f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 185e0023032SKever Yang u32 len = 64; 186f16e43f8SFrank Wang 187f16e43f8SFrank Wang memset((void *)&buf[0], 0, len); 188f16e43f8SFrank Wang 189f16e43f8SFrank Wang /* Set data xfer size */ 190f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 191e0023032SKever Yang common->data_size = len; 192f16e43f8SFrank Wang 193f16e43f8SFrank Wang return len; 194f16e43f8SFrank Wang } 195f16e43f8SFrank Wang 196f16e43f8SFrank Wang static int rkusb_do_read_flash_info(struct fsg_common *common, 197f16e43f8SFrank Wang struct fsg_buffhd *bh) 198f16e43f8SFrank Wang { 199f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 200d23ec8c4SKever Yang u32 len = sizeof(struct rk_flash_info); 201f16e43f8SFrank Wang struct rk_flash_info finfo = { 202f16e43f8SFrank Wang .block_size = 1024, 203f16e43f8SFrank Wang .ecc_bits = 0, 204f16e43f8SFrank Wang .page_size = 4, 205f16e43f8SFrank Wang .access_time = 40, 206f16e43f8SFrank Wang .manufacturer = 0, 207f16e43f8SFrank Wang .flash_mask = 0 208f16e43f8SFrank Wang }; 209f16e43f8SFrank Wang 210f16e43f8SFrank Wang finfo.flash_size = (u32)ums[common->lun].block_dev.lba; 211f16e43f8SFrank Wang if (finfo.flash_size) 212f16e43f8SFrank Wang finfo.flash_mask = 1; 213f16e43f8SFrank Wang 214f16e43f8SFrank Wang memset((void *)&buf[0], 0, len); 215f16e43f8SFrank Wang memcpy((void *)&buf[0], (void *)&finfo, len); 216f16e43f8SFrank Wang 217f16e43f8SFrank Wang /* Set data xfer size */ 218f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 219d23ec8c4SKever Yang /* legacy upgrade_tool does not set correct transfer size */ 220d23ec8c4SKever Yang common->data_size = len; 221f16e43f8SFrank Wang 222f16e43f8SFrank Wang return len; 223f16e43f8SFrank Wang } 224f16e43f8SFrank Wang 225829f2b85SFrank Wang static int rkusb_do_get_chip_info(struct fsg_common *common, 226829f2b85SFrank Wang struct fsg_buffhd *bh) 227829f2b85SFrank Wang { 228829f2b85SFrank Wang u8 *buf = (u8 *)bh->buf; 229829f2b85SFrank Wang u32 len = common->data_size; 230829f2b85SFrank Wang u32 chip_info[4]; 231829f2b85SFrank Wang 232829f2b85SFrank Wang memset((void *)chip_info, 0, sizeof(chip_info)); 233829f2b85SFrank Wang rockchip_rockusb_get_chip_info(chip_info); 234829f2b85SFrank Wang 235829f2b85SFrank Wang memset((void *)&buf[0], 0, len); 236829f2b85SFrank Wang memcpy((void *)&buf[0], (void *)chip_info, len); 237829f2b85SFrank Wang 238829f2b85SFrank Wang /* Set data xfer size */ 239829f2b85SFrank Wang common->residue = common->data_size_from_cmnd = len; 240829f2b85SFrank Wang 241829f2b85SFrank Wang return len; 242829f2b85SFrank Wang } 243829f2b85SFrank Wang 244f16e43f8SFrank Wang static int rkusb_do_lba_erase(struct fsg_common *common, 245f16e43f8SFrank Wang struct fsg_buffhd *bh) 246f16e43f8SFrank Wang { 247f16e43f8SFrank Wang struct fsg_lun *curlun = &common->luns[common->lun]; 248f16e43f8SFrank Wang u32 lba, amount; 249f16e43f8SFrank Wang loff_t file_offset; 250f16e43f8SFrank Wang int rc; 251f16e43f8SFrank Wang 252f16e43f8SFrank Wang lba = get_unaligned_be32(&common->cmnd[2]); 253f16e43f8SFrank Wang if (lba >= curlun->num_sectors) { 254f16e43f8SFrank Wang curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 255f16e43f8SFrank Wang rc = -EINVAL; 256f16e43f8SFrank Wang goto out; 257f16e43f8SFrank Wang } 258f16e43f8SFrank Wang 259f16e43f8SFrank Wang file_offset = ((loff_t) lba) << 9; 260f16e43f8SFrank Wang amount = get_unaligned_be16(&common->cmnd[7]) << 9; 261f16e43f8SFrank Wang if (unlikely(amount == 0)) { 262f16e43f8SFrank Wang curlun->sense_data = SS_INVALID_FIELD_IN_CDB; 263f16e43f8SFrank Wang rc = -EIO; 264f16e43f8SFrank Wang goto out; 265f16e43f8SFrank Wang } 266f16e43f8SFrank Wang 267f16e43f8SFrank Wang /* Perform the erase */ 268f16e43f8SFrank Wang rc = ums[common->lun].erase_sector(&ums[common->lun], 269f16e43f8SFrank Wang file_offset / SECTOR_SIZE, 270f16e43f8SFrank Wang amount / SECTOR_SIZE); 271f16e43f8SFrank Wang if (!rc) { 272f16e43f8SFrank Wang curlun->sense_data = SS_MEDIUM_NOT_PRESENT; 273f16e43f8SFrank Wang rc = -EIO; 274f16e43f8SFrank Wang } 275f16e43f8SFrank Wang 276f16e43f8SFrank Wang out: 277f16e43f8SFrank Wang common->data_dir = DATA_DIR_NONE; 278f16e43f8SFrank Wang bh->state = BUF_STATE_EMPTY; 279f16e43f8SFrank Wang 280f16e43f8SFrank Wang return rc; 281f16e43f8SFrank Wang } 282f16e43f8SFrank Wang 2830d0c3248SFrank Wang #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 2840d0c3248SFrank Wang static int rkusb_do_vs_write(struct fsg_common *common) 2850d0c3248SFrank Wang { 2860d0c3248SFrank Wang struct fsg_lun *curlun = &common->luns[common->lun]; 2870d0c3248SFrank Wang u16 type = get_unaligned_be16(&common->cmnd[4]); 2880d0c3248SFrank Wang struct vendor_item *vhead; 2890d0c3248SFrank Wang struct fsg_buffhd *bh; 2900d0c3248SFrank Wang void *data; 2910d0c3248SFrank Wang int rc; 2920d0c3248SFrank Wang 2930d0c3248SFrank Wang if (common->data_size >= (u32)65536) { 2940d0c3248SFrank Wang /* _MUST_ small than 64K */ 2950d0c3248SFrank Wang curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 2960d0c3248SFrank Wang return -EINVAL; 2970d0c3248SFrank Wang } 2980d0c3248SFrank Wang 2990d0c3248SFrank Wang common->residue = common->data_size; 3000d0c3248SFrank Wang common->usb_amount_left = common->data_size; 3010d0c3248SFrank Wang 3020d0c3248SFrank Wang /* Carry out the file writes */ 3030d0c3248SFrank Wang if (unlikely(common->data_size == 0)) 3040d0c3248SFrank Wang return -EIO; /* No data to write */ 3050d0c3248SFrank Wang 3060d0c3248SFrank Wang for (;;) { 3070d0c3248SFrank Wang if (common->usb_amount_left > 0) { 3080d0c3248SFrank Wang /* Wait for the next buffer to become available */ 3090d0c3248SFrank Wang bh = common->next_buffhd_to_fill; 3100d0c3248SFrank Wang if (bh->state != BUF_STATE_EMPTY) 3110d0c3248SFrank Wang goto wait; 3120d0c3248SFrank Wang 3130d0c3248SFrank Wang /* Request the next buffer */ 3140d0c3248SFrank Wang common->usb_amount_left -= common->data_size; 3150d0c3248SFrank Wang bh->outreq->length = common->data_size; 3160d0c3248SFrank Wang bh->bulk_out_intended_length = common->data_size; 3170d0c3248SFrank Wang bh->outreq->short_not_ok = 1; 3180d0c3248SFrank Wang 3190d0c3248SFrank Wang START_TRANSFER_OR(common, bulk_out, bh->outreq, 3200d0c3248SFrank Wang &bh->outreq_busy, &bh->state) 3210d0c3248SFrank Wang /* 3220d0c3248SFrank Wang * Don't know what to do if 3230d0c3248SFrank Wang * common->fsg is NULL 3240d0c3248SFrank Wang */ 3250d0c3248SFrank Wang return -EIO; 3260d0c3248SFrank Wang common->next_buffhd_to_fill = bh->next; 3270d0c3248SFrank Wang } else { 3280d0c3248SFrank Wang /* Then, wait for the data to become available */ 3290d0c3248SFrank Wang bh = common->next_buffhd_to_drain; 3300d0c3248SFrank Wang if (bh->state != BUF_STATE_FULL) 3310d0c3248SFrank Wang goto wait; 3320d0c3248SFrank Wang 3330d0c3248SFrank Wang common->next_buffhd_to_drain = bh->next; 3340d0c3248SFrank Wang bh->state = BUF_STATE_EMPTY; 3350d0c3248SFrank Wang 3360d0c3248SFrank Wang /* Did something go wrong with the transfer? */ 3370d0c3248SFrank Wang if (bh->outreq->status != 0) { 3380d0c3248SFrank Wang curlun->sense_data = SS_COMMUNICATION_FAILURE; 3390d0c3248SFrank Wang curlun->info_valid = 1; 3400d0c3248SFrank Wang break; 3410d0c3248SFrank Wang } 3420d0c3248SFrank Wang 3430d0c3248SFrank Wang /* Perform the write */ 3440d0c3248SFrank Wang vhead = (struct vendor_item *)bh->buf; 3450d0c3248SFrank Wang data = bh->buf + sizeof(struct vendor_item); 3460d0c3248SFrank Wang 3470d0c3248SFrank Wang if (!type) { 3480d0c3248SFrank Wang /* Vendor storage */ 3490d0c3248SFrank Wang rc = vendor_storage_write(vhead->id, 3500d0c3248SFrank Wang (char __user *)data, 3510d0c3248SFrank Wang vhead->size); 3520d0c3248SFrank Wang if (rc < 0) 3530d0c3248SFrank Wang return -EIO; 3540d0c3248SFrank Wang } else { 3550d0c3248SFrank Wang /* RPMB */ 3566f0347c8Stony.xu #ifdef CONFIG_OPTEE_V1 3576f0347c8Stony.xu rc = 3586f0347c8Stony.xu write_keybox_to_secure_storage((u8 *)data, 3596f0347c8Stony.xu vhead->size); 360*f18b06fbSTony Xu if (rc < 0) 3616f0347c8Stony.xu return -EIO; 3626f0347c8Stony.xu #endif 3630d0c3248SFrank Wang } 3640d0c3248SFrank Wang 3650d0c3248SFrank Wang common->residue -= common->data_size; 3660d0c3248SFrank Wang 3670d0c3248SFrank Wang /* Did the host decide to stop early? */ 3680d0c3248SFrank Wang if (bh->outreq->actual != bh->outreq->length) 3690d0c3248SFrank Wang common->short_packet_received = 1; 3700d0c3248SFrank Wang break; /* Command done */ 3710d0c3248SFrank Wang } 3720d0c3248SFrank Wang wait: 3730d0c3248SFrank Wang /* Wait for something to happen */ 3740d0c3248SFrank Wang rc = sleep_thread(common); 3750d0c3248SFrank Wang if (rc) 3760d0c3248SFrank Wang return rc; 3770d0c3248SFrank Wang } 3780d0c3248SFrank Wang 3790d0c3248SFrank Wang return -EIO; /* No default reply */ 3800d0c3248SFrank Wang } 3810d0c3248SFrank Wang 3820d0c3248SFrank Wang static int rkusb_do_vs_read(struct fsg_common *common) 3830d0c3248SFrank Wang { 3840d0c3248SFrank Wang struct fsg_lun *curlun = &common->luns[common->lun]; 3850d0c3248SFrank Wang u16 type = get_unaligned_be16(&common->cmnd[4]); 3860d0c3248SFrank Wang struct vendor_item *vhead; 3870d0c3248SFrank Wang struct fsg_buffhd *bh; 3880d0c3248SFrank Wang void *data; 3890d0c3248SFrank Wang int rc; 3900d0c3248SFrank Wang 3910d0c3248SFrank Wang if (common->data_size >= (u32)65536) { 3920d0c3248SFrank Wang /* _MUST_ small than 64K */ 3930d0c3248SFrank Wang curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 3940d0c3248SFrank Wang return -EINVAL; 3950d0c3248SFrank Wang } 3960d0c3248SFrank Wang 3970d0c3248SFrank Wang common->residue = common->data_size; 3980d0c3248SFrank Wang common->usb_amount_left = common->data_size; 3990d0c3248SFrank Wang 4000d0c3248SFrank Wang /* Carry out the file reads */ 4010d0c3248SFrank Wang if (unlikely(common->data_size == 0)) 4020d0c3248SFrank Wang return -EIO; /* No default reply */ 4030d0c3248SFrank Wang 4040d0c3248SFrank Wang for (;;) { 4050d0c3248SFrank Wang /* Wait for the next buffer to become available */ 4060d0c3248SFrank Wang bh = common->next_buffhd_to_fill; 4070d0c3248SFrank Wang while (bh->state != BUF_STATE_EMPTY) { 4080d0c3248SFrank Wang rc = sleep_thread(common); 4090d0c3248SFrank Wang if (rc) 4100d0c3248SFrank Wang return rc; 4110d0c3248SFrank Wang } 4120d0c3248SFrank Wang 4130d0c3248SFrank Wang memset(bh->buf, 0, FSG_BUFLEN); 4140d0c3248SFrank Wang vhead = (struct vendor_item *)bh->buf; 4150d0c3248SFrank Wang data = bh->buf + sizeof(struct vendor_item); 4160d0c3248SFrank Wang vhead->id = get_unaligned_be16(&common->cmnd[2]); 4170d0c3248SFrank Wang 4180d0c3248SFrank Wang if (!type) { 4190d0c3248SFrank Wang /* Vendor storage */ 4200d0c3248SFrank Wang rc = vendor_storage_read(vhead->id, 4210d0c3248SFrank Wang (char __user *)data, 4220d0c3248SFrank Wang common->data_size); 4230d0c3248SFrank Wang if (!rc) 4240d0c3248SFrank Wang return -EIO; 4250d0c3248SFrank Wang vhead->size = rc; 4260d0c3248SFrank Wang } else { 4270d0c3248SFrank Wang /* RPMB */ 4280d0c3248SFrank Wang } 4290d0c3248SFrank Wang 4300d0c3248SFrank Wang common->residue -= common->data_size; 4310d0c3248SFrank Wang bh->inreq->length = common->data_size; 4320d0c3248SFrank Wang bh->state = BUF_STATE_FULL; 4330d0c3248SFrank Wang 4340d0c3248SFrank Wang break; /* No more left to read */ 4350d0c3248SFrank Wang } 4360d0c3248SFrank Wang 4370d0c3248SFrank Wang return -EIO; /* No default reply */ 4380d0c3248SFrank Wang } 4390d0c3248SFrank Wang #endif 4400d0c3248SFrank Wang 441f16e43f8SFrank Wang static int rkusb_do_read_capacity(struct fsg_common *common, 442f16e43f8SFrank Wang struct fsg_buffhd *bh) 443f16e43f8SFrank Wang { 444f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 445f16e43f8SFrank Wang u32 len = common->data_size; 446d015bf41SFrank Wang enum if_type type = ums[common->lun].block_dev.if_type; 447f16e43f8SFrank Wang 448f16e43f8SFrank Wang /* 449f16e43f8SFrank Wang * bit[0]: Direct LBA, 0: Disabled; 4500d0c3248SFrank Wang * bit[1]: Vendor Storage API, 0: Disabed (default); 451d015bf41SFrank Wang * bit[2]: First 4M Access, 0: Disabled; 4520d0c3248SFrank Wang * bit[3]: Read LBA On, 0: Disabed (default); 4530d0c3248SFrank Wang * bit[4]: New Vendor Storage API, 0: Disabed; 4540d0c3248SFrank Wang * bit[5:63}: Reserved. 455f16e43f8SFrank Wang */ 456f16e43f8SFrank Wang memset((void *)&buf[0], 0, len); 4570d0c3248SFrank Wang if (type == IF_TYPE_MMC) 4580d0c3248SFrank Wang buf[0] = BIT(0) | BIT(2) | BIT(4); 4590d0c3248SFrank Wang else 4600d0c3248SFrank Wang buf[0] = BIT(0) | BIT(4); 461f16e43f8SFrank Wang 462f16e43f8SFrank Wang /* Set data xfer size */ 463f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 464f16e43f8SFrank Wang 465f16e43f8SFrank Wang return len; 466f16e43f8SFrank Wang } 467f16e43f8SFrank Wang 468d23ec8c4SKever Yang static void rkusb_fixup_cbwcb(struct fsg_common *common, 469d23ec8c4SKever Yang struct fsg_buffhd *bh) 470d23ec8c4SKever Yang { 471d23ec8c4SKever Yang struct usb_request *req = bh->outreq; 472d23ec8c4SKever Yang struct fsg_bulk_cb_wrap *cbw = req->buf; 473d23ec8c4SKever Yang 474d23ec8c4SKever Yang /* FIXME cbw.DataTransferLength was not set by Upgrade Tool */ 475d23ec8c4SKever Yang common->data_size = le32_to_cpu(cbw->DataTransferLength); 476d23ec8c4SKever Yang if (common->data_size == 0) { 477d23ec8c4SKever Yang common->data_size = 478d23ec8c4SKever Yang get_unaligned_be16(&common->cmnd[7]) << 9; 479d23ec8c4SKever Yang printf("Trasfer Length NOT set, please use new version tool\n"); 480d23ec8c4SKever Yang debug("%s %d, cmnd1 %x\n", __func__, 481d23ec8c4SKever Yang get_unaligned_be16(&common->cmnd[7]), 482d23ec8c4SKever Yang get_unaligned_be16(&common->cmnd[1])); 483d23ec8c4SKever Yang } 484d23ec8c4SKever Yang if (cbw->Flags & USB_BULK_IN_FLAG) 485d23ec8c4SKever Yang common->data_dir = DATA_DIR_TO_HOST; 486d23ec8c4SKever Yang else 487d23ec8c4SKever Yang common->data_dir = DATA_DIR_FROM_HOST; 488d23ec8c4SKever Yang 489d23ec8c4SKever Yang /* Not support */ 490d23ec8c4SKever Yang common->cmnd[1] = 0; 491d23ec8c4SKever Yang } 492d23ec8c4SKever Yang 493f16e43f8SFrank Wang static int rkusb_cmd_process(struct fsg_common *common, 494f16e43f8SFrank Wang struct fsg_buffhd *bh, int *reply) 495f16e43f8SFrank Wang { 496f16e43f8SFrank Wang struct usb_request *req = bh->outreq; 497f16e43f8SFrank Wang struct fsg_bulk_cb_wrap *cbw = req->buf; 498f16e43f8SFrank Wang int rc; 499f16e43f8SFrank Wang 500f16e43f8SFrank Wang dump_cbw(cbw); 501f16e43f8SFrank Wang 502f16e43f8SFrank Wang if (rkusb_check_lun(common)) { 503f16e43f8SFrank Wang *reply = -EINVAL; 504f16e43f8SFrank Wang return RKUSB_RC_ERROR; 505f16e43f8SFrank Wang } 506f16e43f8SFrank Wang 507f16e43f8SFrank Wang switch (common->cmnd[0]) { 508f16e43f8SFrank Wang case RKUSB_TEST_UNIT_READY: 509f16e43f8SFrank Wang *reply = rkusb_do_test_unit_ready(common, bh); 510f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 511f16e43f8SFrank Wang break; 512f16e43f8SFrank Wang 513f16e43f8SFrank Wang case RKUSB_READ_FLASH_ID: 514f16e43f8SFrank Wang *reply = rkusb_do_read_flash_id(common, bh); 515f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 516f16e43f8SFrank Wang break; 517f16e43f8SFrank Wang 518f16e43f8SFrank Wang case RKUSB_TEST_BAD_BLOCK: 519f16e43f8SFrank Wang *reply = rkusb_do_test_bad_block(common, bh); 520f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 521f16e43f8SFrank Wang break; 522f16e43f8SFrank Wang 523f16e43f8SFrank Wang case RKUSB_LBA_READ_10: 5245fb597c2SKever Yang rkusb_fixup_cbwcb(common, bh); 525f16e43f8SFrank Wang common->cmnd[0] = SC_READ_10; 526f16e43f8SFrank Wang common->cmnd[1] = 0; /* Not support */ 527f16e43f8SFrank Wang rc = RKUSB_RC_CONTINUE; 528f16e43f8SFrank Wang break; 529f16e43f8SFrank Wang 530f16e43f8SFrank Wang case RKUSB_LBA_WRITE_10: 5315fb597c2SKever Yang rkusb_fixup_cbwcb(common, bh); 532f16e43f8SFrank Wang common->cmnd[0] = SC_WRITE_10; 533f16e43f8SFrank Wang common->cmnd[1] = 0; /* Not support */ 534f16e43f8SFrank Wang rc = RKUSB_RC_CONTINUE; 535f16e43f8SFrank Wang break; 536f16e43f8SFrank Wang 537f16e43f8SFrank Wang case RKUSB_READ_FLASH_INFO: 538f16e43f8SFrank Wang *reply = rkusb_do_read_flash_info(common, bh); 539f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 540f16e43f8SFrank Wang break; 541f16e43f8SFrank Wang 542829f2b85SFrank Wang case RKUSB_GET_CHIP_VER: 543829f2b85SFrank Wang *reply = rkusb_do_get_chip_info(common, bh); 544829f2b85SFrank Wang rc = RKUSB_RC_FINISHED; 545829f2b85SFrank Wang break; 546829f2b85SFrank Wang 547f16e43f8SFrank Wang case RKUSB_LBA_ERASE: 548f16e43f8SFrank Wang *reply = rkusb_do_lba_erase(common, bh); 549f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 550f16e43f8SFrank Wang break; 551f16e43f8SFrank Wang 5520d0c3248SFrank Wang #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 5530d0c3248SFrank Wang case RKUSB_VS_WRITE: 5540d0c3248SFrank Wang *reply = rkusb_do_vs_write(common); 5550d0c3248SFrank Wang rc = RKUSB_RC_FINISHED; 5560d0c3248SFrank Wang break; 5570d0c3248SFrank Wang 5580d0c3248SFrank Wang case RKUSB_VS_READ: 5590d0c3248SFrank Wang *reply = rkusb_do_vs_read(common); 5600d0c3248SFrank Wang rc = RKUSB_RC_FINISHED; 5610d0c3248SFrank Wang break; 5620d0c3248SFrank Wang #endif 5630d0c3248SFrank Wang 564f16e43f8SFrank Wang case RKUSB_READ_CAPACITY: 565f16e43f8SFrank Wang *reply = rkusb_do_read_capacity(common, bh); 566f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 567f16e43f8SFrank Wang break; 568f16e43f8SFrank Wang 569f16e43f8SFrank Wang case RKUSB_RESET: 570f16e43f8SFrank Wang *reply = rkusb_do_reset(common, bh); 571f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 572f16e43f8SFrank Wang break; 573f16e43f8SFrank Wang 574f16e43f8SFrank Wang case RKUSB_READ_10: 575f16e43f8SFrank Wang case RKUSB_WRITE_10: 576e0023032SKever Yang printf("CMD Not support, pls use new version Tool\n"); 577e0023032SKever Yang case RKUSB_SET_DEVICE_ID: 578f16e43f8SFrank Wang case RKUSB_ERASE_10: 579f16e43f8SFrank Wang case RKUSB_WRITE_SPARE: 580f16e43f8SFrank Wang case RKUSB_READ_SPARE: 581f16e43f8SFrank Wang case RKUSB_ERASE_10_FORCE: 582f16e43f8SFrank Wang case RKUSB_GET_VERSION: 583f16e43f8SFrank Wang case RKUSB_ERASE_SYS_DISK: 584f16e43f8SFrank Wang case RKUSB_SDRAM_READ_10: 585f16e43f8SFrank Wang case RKUSB_SDRAM_WRITE_10: 586f16e43f8SFrank Wang case RKUSB_SDRAM_EXECUTE: 587f16e43f8SFrank Wang case RKUSB_LOW_FORMAT: 588f16e43f8SFrank Wang case RKUSB_SET_RESET_FLAG: 589f16e43f8SFrank Wang case RKUSB_SPI_READ_10: 590f16e43f8SFrank Wang case RKUSB_SPI_WRITE_10: 591f16e43f8SFrank Wang case RKUSB_SESSION: 592f16e43f8SFrank Wang /* Fall through */ 593f16e43f8SFrank Wang default: 594f16e43f8SFrank Wang rc = RKUSB_RC_UNKNOWN_CMND; 595f16e43f8SFrank Wang break; 596f16e43f8SFrank Wang } 597f16e43f8SFrank Wang 598f16e43f8SFrank Wang return rc; 599f16e43f8SFrank Wang } 600f16e43f8SFrank Wang 601f16e43f8SFrank Wang DECLARE_GADGET_BIND_CALLBACK(rkusb_ums_dnl, fsg_add); 602