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 8f16e43f8SFrank Wang #include <rockusb.h> 9f16e43f8SFrank Wang 10f16e43f8SFrank Wang #define ROCKUSB_INTERFACE_CLASS 0xff 11f16e43f8SFrank Wang #define ROCKUSB_INTERFACE_SUB_CLASS 0x06 12f16e43f8SFrank Wang #define ROCKUSB_INTERFACE_PROTOCOL 0x05 13f16e43f8SFrank Wang 14f16e43f8SFrank Wang static struct usb_interface_descriptor rkusb_intf_desc = { 15f16e43f8SFrank Wang .bLength = USB_DT_INTERFACE_SIZE, 16f16e43f8SFrank Wang .bDescriptorType = USB_DT_INTERFACE, 17f16e43f8SFrank Wang .bInterfaceNumber = 0x00, 18f16e43f8SFrank Wang .bAlternateSetting = 0x00, 19f16e43f8SFrank Wang .bNumEndpoints = 0x02, 20f16e43f8SFrank Wang .bInterfaceClass = ROCKUSB_INTERFACE_CLASS, 21f16e43f8SFrank Wang .bInterfaceSubClass = ROCKUSB_INTERFACE_SUB_CLASS, 22f16e43f8SFrank Wang .bInterfaceProtocol = ROCKUSB_INTERFACE_PROTOCOL, 23f16e43f8SFrank Wang }; 24f16e43f8SFrank Wang 25f16e43f8SFrank Wang static struct usb_descriptor_header *rkusb_fs_function[] = { 26f16e43f8SFrank Wang (struct usb_descriptor_header *)&rkusb_intf_desc, 27f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_fs_bulk_in_desc, 28f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_fs_bulk_out_desc, 29f16e43f8SFrank Wang NULL, 30f16e43f8SFrank Wang }; 31f16e43f8SFrank Wang 32f16e43f8SFrank Wang static struct usb_descriptor_header *rkusb_hs_function[] = { 33f16e43f8SFrank Wang (struct usb_descriptor_header *)&rkusb_intf_desc, 34f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_hs_bulk_in_desc, 35f16e43f8SFrank Wang (struct usb_descriptor_header *)&fsg_hs_bulk_out_desc, 36f16e43f8SFrank Wang NULL, 37f16e43f8SFrank Wang }; 38f16e43f8SFrank Wang 39f16e43f8SFrank Wang struct rk_flash_info { 40f16e43f8SFrank Wang u32 flash_size; 41f16e43f8SFrank Wang u16 block_size; 42f16e43f8SFrank Wang u8 page_size; 43f16e43f8SFrank Wang u8 ecc_bits; 44f16e43f8SFrank Wang u8 access_time; 45f16e43f8SFrank Wang u8 manufacturer; 46f16e43f8SFrank Wang u8 flash_mask; 47f16e43f8SFrank Wang } __packed; 48f16e43f8SFrank Wang 49f16e43f8SFrank Wang int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) 50f16e43f8SFrank Wang { 51*ba437c8cSFrank Wang if (IS_RKUSB_UMS_DNL(name)) { 52*ba437c8cSFrank Wang /* Fix to Rockchip VID and PID */ 53*ba437c8cSFrank Wang dev->idVendor = __constant_cpu_to_le16(0x2207); 54*ba437c8cSFrank Wang dev->idProduct = __constant_cpu_to_le16(CONFIG_ROCKUSB_G_DNL_PID); 55*ba437c8cSFrank Wang 56f16e43f8SFrank Wang /* Enumerate as a loader device */ 57f16e43f8SFrank Wang dev->bcdUSB = cpu_to_le16(0x0201); 58*ba437c8cSFrank Wang } 59f16e43f8SFrank Wang 60f16e43f8SFrank Wang return 0; 61f16e43f8SFrank Wang } 62f16e43f8SFrank Wang 63f16e43f8SFrank Wang __maybe_unused 64f16e43f8SFrank Wang static inline void dump_cbw(struct fsg_bulk_cb_wrap *cbw) 65f16e43f8SFrank Wang { 66f16e43f8SFrank Wang assert(!cbw); 67f16e43f8SFrank Wang 68f16e43f8SFrank Wang debug("%s:\n", __func__); 69f16e43f8SFrank Wang debug("Signature %x\n", cbw->Signature); 70f16e43f8SFrank Wang debug("Tag %x\n", cbw->Tag); 71f16e43f8SFrank Wang debug("DataTransferLength %x\n", cbw->DataTransferLength); 72f16e43f8SFrank Wang debug("Flags %x\n", cbw->Flags); 73f16e43f8SFrank Wang debug("LUN %x\n", cbw->Lun); 74f16e43f8SFrank Wang debug("Length %x\n", cbw->Length); 75f16e43f8SFrank Wang debug("OptionCode %x\n", cbw->CDB[0]); 76f16e43f8SFrank Wang debug("SubCode %x\n", cbw->CDB[1]); 77f16e43f8SFrank Wang debug("SectorAddr %x\n", get_unaligned_be32(&cbw->CDB[2])); 78f16e43f8SFrank Wang debug("BlkSectors %x\n\n", get_unaligned_be16(&cbw->CDB[7])); 79f16e43f8SFrank Wang } 80f16e43f8SFrank Wang 81f16e43f8SFrank Wang static int rkusb_check_lun(struct fsg_common *common) 82f16e43f8SFrank Wang { 83f16e43f8SFrank Wang struct fsg_lun *curlun; 84f16e43f8SFrank Wang 85f16e43f8SFrank Wang /* Check the LUN */ 86f16e43f8SFrank Wang if (common->lun >= 0 && common->lun < common->nluns) { 87f16e43f8SFrank Wang curlun = &common->luns[common->lun]; 88f16e43f8SFrank Wang if (common->cmnd[0] != SC_REQUEST_SENSE) { 89f16e43f8SFrank Wang curlun->sense_data = SS_NO_SENSE; 90f16e43f8SFrank Wang curlun->info_valid = 0; 91f16e43f8SFrank Wang } 92f16e43f8SFrank Wang } else { 93f16e43f8SFrank Wang curlun = NULL; 94f16e43f8SFrank Wang common->bad_lun_okay = 0; 95f16e43f8SFrank Wang 96f16e43f8SFrank Wang /* 97f16e43f8SFrank Wang * INQUIRY and REQUEST SENSE commands are explicitly allowed 98f16e43f8SFrank Wang * to use unsupported LUNs; all others may not. 99f16e43f8SFrank Wang */ 100f16e43f8SFrank Wang if (common->cmnd[0] != SC_INQUIRY && 101f16e43f8SFrank Wang common->cmnd[0] != SC_REQUEST_SENSE) { 102f16e43f8SFrank Wang debug("unsupported LUN %d\n", common->lun); 103f16e43f8SFrank Wang return -EINVAL; 104f16e43f8SFrank Wang } 105f16e43f8SFrank Wang } 106f16e43f8SFrank Wang 107f16e43f8SFrank Wang return 0; 108f16e43f8SFrank Wang } 109f16e43f8SFrank Wang 110f16e43f8SFrank Wang static void __do_reset(struct usb_ep *ep, struct usb_request *req) 111f16e43f8SFrank Wang { 112f16e43f8SFrank Wang do_reset(NULL, 0, 0, NULL); 113f16e43f8SFrank Wang } 114f16e43f8SFrank Wang 115f16e43f8SFrank Wang static int rkusb_do_reset(struct fsg_common *common, 116f16e43f8SFrank Wang struct fsg_buffhd *bh) 117f16e43f8SFrank Wang { 118f16e43f8SFrank Wang common->data_size_from_cmnd = common->cmnd[4]; 119f16e43f8SFrank Wang common->residue = 0; 120f16e43f8SFrank Wang bh->inreq->complete = __do_reset; 121f16e43f8SFrank Wang bh->state = BUF_STATE_EMPTY; 122f16e43f8SFrank Wang 123f16e43f8SFrank Wang return 0; 124f16e43f8SFrank Wang } 125f16e43f8SFrank Wang 126f16e43f8SFrank Wang static int rkusb_do_test_unit_ready(struct fsg_common *common, 127f16e43f8SFrank Wang struct fsg_buffhd *bh) 128f16e43f8SFrank Wang { 129f16e43f8SFrank Wang common->residue = 0x06 << 24; /* Max block xfer support from host */ 130f16e43f8SFrank Wang common->data_dir = DATA_DIR_NONE; 131f16e43f8SFrank Wang bh->state = BUF_STATE_EMPTY; 132f16e43f8SFrank Wang 133f16e43f8SFrank Wang return 0; 134f16e43f8SFrank Wang } 135f16e43f8SFrank Wang 136f16e43f8SFrank Wang static int rkusb_do_read_flash_id(struct fsg_common *common, 137f16e43f8SFrank Wang struct fsg_buffhd *bh) 138f16e43f8SFrank Wang { 139f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 140f16e43f8SFrank Wang u32 len = common->data_size; 141f16e43f8SFrank Wang 142f16e43f8SFrank Wang memcpy((void *)&buf[0], "EMMC ", 5); 143f16e43f8SFrank Wang 144f16e43f8SFrank Wang /* Set data xfer size */ 145f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 146f16e43f8SFrank Wang 147f16e43f8SFrank Wang return len; 148f16e43f8SFrank Wang } 149f16e43f8SFrank Wang 150f16e43f8SFrank Wang static int rkusb_do_test_bad_block(struct fsg_common *common, 151f16e43f8SFrank Wang struct fsg_buffhd *bh) 152f16e43f8SFrank Wang { 153f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 154f16e43f8SFrank Wang u32 len = common->data_size; 155f16e43f8SFrank Wang 156f16e43f8SFrank Wang memset((void *)&buf[0], 0, len); 157f16e43f8SFrank Wang 158f16e43f8SFrank Wang /* Set data xfer size */ 159f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 160f16e43f8SFrank Wang 161f16e43f8SFrank Wang return len; 162f16e43f8SFrank Wang } 163f16e43f8SFrank Wang 164f16e43f8SFrank Wang static int rkusb_do_read_flash_info(struct fsg_common *common, 165f16e43f8SFrank Wang struct fsg_buffhd *bh) 166f16e43f8SFrank Wang { 167f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 168f16e43f8SFrank Wang u32 len = common->data_size; 169f16e43f8SFrank Wang struct rk_flash_info finfo = { 170f16e43f8SFrank Wang .block_size = 1024, 171f16e43f8SFrank Wang .ecc_bits = 0, 172f16e43f8SFrank Wang .page_size = 4, 173f16e43f8SFrank Wang .access_time = 40, 174f16e43f8SFrank Wang .manufacturer = 0, 175f16e43f8SFrank Wang .flash_mask = 0 176f16e43f8SFrank Wang }; 177f16e43f8SFrank Wang 178f16e43f8SFrank Wang finfo.flash_size = (u32)ums[common->lun].block_dev.lba; 179f16e43f8SFrank Wang if (finfo.flash_size) 180f16e43f8SFrank Wang finfo.flash_mask = 1; 181f16e43f8SFrank Wang 182f16e43f8SFrank Wang memset((void *)&buf[0], 0, len); 183f16e43f8SFrank Wang memcpy((void *)&buf[0], (void *)&finfo, len); 184f16e43f8SFrank Wang 185f16e43f8SFrank Wang /* Set data xfer size */ 186f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 187f16e43f8SFrank Wang 188f16e43f8SFrank Wang return len; 189f16e43f8SFrank Wang } 190f16e43f8SFrank Wang 191f16e43f8SFrank Wang static int rkusb_do_lba_erase(struct fsg_common *common, 192f16e43f8SFrank Wang struct fsg_buffhd *bh) 193f16e43f8SFrank Wang { 194f16e43f8SFrank Wang struct fsg_lun *curlun = &common->luns[common->lun]; 195f16e43f8SFrank Wang u32 lba, amount; 196f16e43f8SFrank Wang loff_t file_offset; 197f16e43f8SFrank Wang int rc; 198f16e43f8SFrank Wang 199f16e43f8SFrank Wang lba = get_unaligned_be32(&common->cmnd[2]); 200f16e43f8SFrank Wang if (lba >= curlun->num_sectors) { 201f16e43f8SFrank Wang curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; 202f16e43f8SFrank Wang rc = -EINVAL; 203f16e43f8SFrank Wang goto out; 204f16e43f8SFrank Wang } 205f16e43f8SFrank Wang 206f16e43f8SFrank Wang file_offset = ((loff_t) lba) << 9; 207f16e43f8SFrank Wang amount = get_unaligned_be16(&common->cmnd[7]) << 9; 208f16e43f8SFrank Wang if (unlikely(amount == 0)) { 209f16e43f8SFrank Wang curlun->sense_data = SS_INVALID_FIELD_IN_CDB; 210f16e43f8SFrank Wang rc = -EIO; 211f16e43f8SFrank Wang goto out; 212f16e43f8SFrank Wang } 213f16e43f8SFrank Wang 214f16e43f8SFrank Wang /* Perform the erase */ 215f16e43f8SFrank Wang rc = ums[common->lun].erase_sector(&ums[common->lun], 216f16e43f8SFrank Wang file_offset / SECTOR_SIZE, 217f16e43f8SFrank Wang amount / SECTOR_SIZE); 218f16e43f8SFrank Wang if (!rc) { 219f16e43f8SFrank Wang curlun->sense_data = SS_MEDIUM_NOT_PRESENT; 220f16e43f8SFrank Wang rc = -EIO; 221f16e43f8SFrank Wang } 222f16e43f8SFrank Wang 223f16e43f8SFrank Wang out: 224f16e43f8SFrank Wang common->data_dir = DATA_DIR_NONE; 225f16e43f8SFrank Wang bh->state = BUF_STATE_EMPTY; 226f16e43f8SFrank Wang 227f16e43f8SFrank Wang return rc; 228f16e43f8SFrank Wang } 229f16e43f8SFrank Wang 230f16e43f8SFrank Wang static int rkusb_do_read_capacity(struct fsg_common *common, 231f16e43f8SFrank Wang struct fsg_buffhd *bh) 232f16e43f8SFrank Wang { 233f16e43f8SFrank Wang u8 *buf = (u8 *)bh->buf; 234f16e43f8SFrank Wang u32 len = common->data_size; 235f16e43f8SFrank Wang 236f16e43f8SFrank Wang /* 237f16e43f8SFrank Wang * bit[0]: Direct LBA, 0: Disabled; 238f16e43f8SFrank Wang * bit[1:63}: Reserved. 239f16e43f8SFrank Wang */ 240f16e43f8SFrank Wang memset((void *)&buf[0], 0, len); 241f16e43f8SFrank Wang 242f16e43f8SFrank Wang /* Set data xfer size */ 243f16e43f8SFrank Wang common->residue = common->data_size_from_cmnd = len; 244f16e43f8SFrank Wang 245f16e43f8SFrank Wang return len; 246f16e43f8SFrank Wang } 247f16e43f8SFrank Wang 248f16e43f8SFrank Wang static int rkusb_cmd_process(struct fsg_common *common, 249f16e43f8SFrank Wang struct fsg_buffhd *bh, int *reply) 250f16e43f8SFrank Wang { 251f16e43f8SFrank Wang struct usb_request *req = bh->outreq; 252f16e43f8SFrank Wang struct fsg_bulk_cb_wrap *cbw = req->buf; 253f16e43f8SFrank Wang int rc; 254f16e43f8SFrank Wang 255f16e43f8SFrank Wang dump_cbw(cbw); 256f16e43f8SFrank Wang 257f16e43f8SFrank Wang if (rkusb_check_lun(common)) { 258f16e43f8SFrank Wang *reply = -EINVAL; 259f16e43f8SFrank Wang return RKUSB_RC_ERROR; 260f16e43f8SFrank Wang } 261f16e43f8SFrank Wang 262f16e43f8SFrank Wang switch (common->cmnd[0]) { 263f16e43f8SFrank Wang case RKUSB_TEST_UNIT_READY: 264f16e43f8SFrank Wang *reply = rkusb_do_test_unit_ready(common, bh); 265f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 266f16e43f8SFrank Wang break; 267f16e43f8SFrank Wang 268f16e43f8SFrank Wang case RKUSB_READ_FLASH_ID: 269f16e43f8SFrank Wang *reply = rkusb_do_read_flash_id(common, bh); 270f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 271f16e43f8SFrank Wang break; 272f16e43f8SFrank Wang 273f16e43f8SFrank Wang case RKUSB_TEST_BAD_BLOCK: 274f16e43f8SFrank Wang *reply = rkusb_do_test_bad_block(common, bh); 275f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 276f16e43f8SFrank Wang break; 277f16e43f8SFrank Wang 278f16e43f8SFrank Wang case RKUSB_LBA_READ_10: 279f16e43f8SFrank Wang common->cmnd[0] = SC_READ_10; 280f16e43f8SFrank Wang common->cmnd[1] = 0; /* Not support */ 281f16e43f8SFrank Wang rc = RKUSB_RC_CONTINUE; 282f16e43f8SFrank Wang break; 283f16e43f8SFrank Wang 284f16e43f8SFrank Wang case RKUSB_LBA_WRITE_10: 285f16e43f8SFrank Wang common->cmnd[0] = SC_WRITE_10; 286f16e43f8SFrank Wang common->cmnd[1] = 0; /* Not support */ 287f16e43f8SFrank Wang rc = RKUSB_RC_CONTINUE; 288f16e43f8SFrank Wang break; 289f16e43f8SFrank Wang 290f16e43f8SFrank Wang case RKUSB_READ_FLASH_INFO: 291f16e43f8SFrank Wang *reply = rkusb_do_read_flash_info(common, bh); 292f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 293f16e43f8SFrank Wang break; 294f16e43f8SFrank Wang 295f16e43f8SFrank Wang case RKUSB_LBA_ERASE: 296f16e43f8SFrank Wang *reply = rkusb_do_lba_erase(common, bh); 297f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 298f16e43f8SFrank Wang break; 299f16e43f8SFrank Wang 300f16e43f8SFrank Wang case RKUSB_READ_CAPACITY: 301f16e43f8SFrank Wang *reply = rkusb_do_read_capacity(common, bh); 302f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 303f16e43f8SFrank Wang break; 304f16e43f8SFrank Wang 305f16e43f8SFrank Wang case RKUSB_RESET: 306f16e43f8SFrank Wang *reply = rkusb_do_reset(common, bh); 307f16e43f8SFrank Wang rc = RKUSB_RC_FINISHED; 308f16e43f8SFrank Wang break; 309f16e43f8SFrank Wang 310f16e43f8SFrank Wang case RKUSB_SET_DEVICE_ID: 311f16e43f8SFrank Wang case RKUSB_READ_10: 312f16e43f8SFrank Wang case RKUSB_WRITE_10: 313f16e43f8SFrank Wang case RKUSB_ERASE_10: 314f16e43f8SFrank Wang case RKUSB_WRITE_SPARE: 315f16e43f8SFrank Wang case RKUSB_READ_SPARE: 316f16e43f8SFrank Wang case RKUSB_ERASE_10_FORCE: 317f16e43f8SFrank Wang case RKUSB_GET_VERSION: 318f16e43f8SFrank Wang case RKUSB_ERASE_SYS_DISK: 319f16e43f8SFrank Wang case RKUSB_SDRAM_READ_10: 320f16e43f8SFrank Wang case RKUSB_SDRAM_WRITE_10: 321f16e43f8SFrank Wang case RKUSB_SDRAM_EXECUTE: 322f16e43f8SFrank Wang case RKUSB_GET_CHIP_VER: 323f16e43f8SFrank Wang case RKUSB_LOW_FORMAT: 324f16e43f8SFrank Wang case RKUSB_SET_RESET_FLAG: 325f16e43f8SFrank Wang case RKUSB_SPI_READ_10: 326f16e43f8SFrank Wang case RKUSB_SPI_WRITE_10: 327f16e43f8SFrank Wang case RKUSB_SESSION: 328f16e43f8SFrank Wang /* Fall through */ 329f16e43f8SFrank Wang default: 330f16e43f8SFrank Wang rc = RKUSB_RC_UNKNOWN_CMND; 331f16e43f8SFrank Wang break; 332f16e43f8SFrank Wang } 333f16e43f8SFrank Wang 334f16e43f8SFrank Wang return rc; 335f16e43f8SFrank Wang } 336f16e43f8SFrank Wang 337f16e43f8SFrank Wang DECLARE_GADGET_BIND_CALLBACK(rkusb_ums_dnl, fsg_add); 338