xref: /rk3399_rockchip-uboot/drivers/usb/gadget/f_rockusb.c (revision ba437c8c987895da95fa841aaeea893b747ab0e5)
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