1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2017 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun * Frank Wang <frank.wang@rock-chips.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <asm/io.h>
9*4882a593Smuzhiyun #include <android_avb/avb_ops_user.h>
10*4882a593Smuzhiyun #include <android_avb/rk_avb_ops_user.h>
11*4882a593Smuzhiyun #include <asm/arch/boot_mode.h>
12*4882a593Smuzhiyun #include <asm/arch/chip_info.h>
13*4882a593Smuzhiyun #include <asm/arch/rk_atags.h>
14*4882a593Smuzhiyun #include <write_keybox.h>
15*4882a593Smuzhiyun #include <linux/mtd/mtd.h>
16*4882a593Smuzhiyun #include <optee_include/OpteeClientInterface.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
19*4882a593Smuzhiyun #include <asm/arch/vendor.h>
20*4882a593Smuzhiyun #endif
21*4882a593Smuzhiyun #include <rockusb.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define ROCKUSB_INTERFACE_CLASS 0xff
24*4882a593Smuzhiyun #define ROCKUSB_INTERFACE_SUB_CLASS 0x06
25*4882a593Smuzhiyun #define ROCKUSB_INTERFACE_PROTOCOL 0x05
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define ROCKCHIP_FLASH_BLOCK_SIZE 1024
28*4882a593Smuzhiyun #define ROCKCHIP_FLASH_PAGE_SIZE 4
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static struct usb_interface_descriptor rkusb_intf_desc = {
31*4882a593Smuzhiyun .bLength = USB_DT_INTERFACE_SIZE,
32*4882a593Smuzhiyun .bDescriptorType = USB_DT_INTERFACE,
33*4882a593Smuzhiyun .bInterfaceNumber = 0x00,
34*4882a593Smuzhiyun .bAlternateSetting = 0x00,
35*4882a593Smuzhiyun .bNumEndpoints = 0x02,
36*4882a593Smuzhiyun .bInterfaceClass = ROCKUSB_INTERFACE_CLASS,
37*4882a593Smuzhiyun .bInterfaceSubClass = ROCKUSB_INTERFACE_SUB_CLASS,
38*4882a593Smuzhiyun .bInterfaceProtocol = ROCKUSB_INTERFACE_PROTOCOL,
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static struct usb_descriptor_header *rkusb_fs_function[] = {
42*4882a593Smuzhiyun (struct usb_descriptor_header *)&rkusb_intf_desc,
43*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_fs_bulk_in_desc,
44*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_fs_bulk_out_desc,
45*4882a593Smuzhiyun NULL,
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static struct usb_descriptor_header *rkusb_hs_function[] = {
49*4882a593Smuzhiyun (struct usb_descriptor_header *)&rkusb_intf_desc,
50*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_hs_bulk_in_desc,
51*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_hs_bulk_out_desc,
52*4882a593Smuzhiyun NULL,
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun static struct usb_descriptor_header *rkusb_ss_function[] = {
56*4882a593Smuzhiyun (struct usb_descriptor_header *)&rkusb_intf_desc,
57*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_ss_bulk_in_desc,
58*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_ss_bulk_in_comp_desc,
59*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_ss_bulk_out_desc,
60*4882a593Smuzhiyun (struct usb_descriptor_header *)&fsg_ss_bulk_out_comp_desc,
61*4882a593Smuzhiyun NULL,
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun struct rk_flash_info {
65*4882a593Smuzhiyun u32 flash_size;
66*4882a593Smuzhiyun u16 block_size;
67*4882a593Smuzhiyun u8 page_size;
68*4882a593Smuzhiyun u8 ecc_bits;
69*4882a593Smuzhiyun u8 access_time;
70*4882a593Smuzhiyun u8 manufacturer;
71*4882a593Smuzhiyun u8 flash_mask;
72*4882a593Smuzhiyun } __packed;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun static int rkusb_rst_code; /* The subcode in reset command (0xFF) */
75*4882a593Smuzhiyun
g_dnl_bind_fixup(struct usb_device_descriptor * dev,const char * name)76*4882a593Smuzhiyun int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun if (IS_RKUSB_UMS_DNL(name)) {
79*4882a593Smuzhiyun /* Fix to Rockchip's VID and PID */
80*4882a593Smuzhiyun dev->idVendor = __constant_cpu_to_le16(0x2207);
81*4882a593Smuzhiyun dev->idProduct = __constant_cpu_to_le16(CONFIG_ROCKUSB_G_DNL_PID);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Enumerate as a loader device */
84*4882a593Smuzhiyun #if defined(CONFIG_SUPPORT_USBPLUG)
85*4882a593Smuzhiyun dev->bcdUSB = cpu_to_le16(0x0200);
86*4882a593Smuzhiyun #else
87*4882a593Smuzhiyun dev->bcdUSB = cpu_to_le16(0x0201);
88*4882a593Smuzhiyun #endif
89*4882a593Smuzhiyun } else if (!strncmp(name, "usb_dnl_fastboot", 16)) {
90*4882a593Smuzhiyun /* Fix to Google's VID and PID */
91*4882a593Smuzhiyun dev->idVendor = __constant_cpu_to_le16(0x18d1);
92*4882a593Smuzhiyun dev->idProduct = __constant_cpu_to_le16(0xd00d);
93*4882a593Smuzhiyun } else if (!strncmp(name, "usb_dnl_dfu", 11)) {
94*4882a593Smuzhiyun /* Fix to Rockchip's VID and PID for DFU */
95*4882a593Smuzhiyun dev->idVendor = cpu_to_le16(0x2207);
96*4882a593Smuzhiyun dev->idProduct = cpu_to_le16(0x0107);
97*4882a593Smuzhiyun } else if (!strncmp(name, "usb_dnl_ums", 11)) {
98*4882a593Smuzhiyun dev->idVendor = cpu_to_le16(0x2207);
99*4882a593Smuzhiyun dev->idProduct = cpu_to_le16(0x0010);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun return 0;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun __maybe_unused
dump_cbw(struct fsg_bulk_cb_wrap * cbw)106*4882a593Smuzhiyun static inline void dump_cbw(struct fsg_bulk_cb_wrap *cbw)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun assert(!cbw);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun debug("%s:\n", __func__);
111*4882a593Smuzhiyun debug("Signature %x\n", cbw->Signature);
112*4882a593Smuzhiyun debug("Tag %x\n", cbw->Tag);
113*4882a593Smuzhiyun debug("DataTransferLength %x\n", cbw->DataTransferLength);
114*4882a593Smuzhiyun debug("Flags %x\n", cbw->Flags);
115*4882a593Smuzhiyun debug("LUN %x\n", cbw->Lun);
116*4882a593Smuzhiyun debug("Length %x\n", cbw->Length);
117*4882a593Smuzhiyun debug("OptionCode %x\n", cbw->CDB[0]);
118*4882a593Smuzhiyun debug("SubCode %x\n", cbw->CDB[1]);
119*4882a593Smuzhiyun debug("SectorAddr %x\n", get_unaligned_be32(&cbw->CDB[2]));
120*4882a593Smuzhiyun debug("BlkSectors %x\n\n", get_unaligned_be16(&cbw->CDB[7]));
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
rkusb_check_lun(struct fsg_common * common)123*4882a593Smuzhiyun static int rkusb_check_lun(struct fsg_common *common)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun struct fsg_lun *curlun;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* Check the LUN */
128*4882a593Smuzhiyun if (common->lun >= 0 && common->lun < common->nluns) {
129*4882a593Smuzhiyun curlun = &common->luns[common->lun];
130*4882a593Smuzhiyun if (common->cmnd[0] != SC_REQUEST_SENSE) {
131*4882a593Smuzhiyun curlun->sense_data = SS_NO_SENSE;
132*4882a593Smuzhiyun curlun->info_valid = 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun } else {
135*4882a593Smuzhiyun curlun = NULL;
136*4882a593Smuzhiyun common->bad_lun_okay = 0;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /*
139*4882a593Smuzhiyun * INQUIRY and REQUEST SENSE commands are explicitly allowed
140*4882a593Smuzhiyun * to use unsupported LUNs; all others may not.
141*4882a593Smuzhiyun */
142*4882a593Smuzhiyun if (common->cmnd[0] != SC_INQUIRY &&
143*4882a593Smuzhiyun common->cmnd[0] != SC_REQUEST_SENSE) {
144*4882a593Smuzhiyun debug("unsupported LUN %d\n", common->lun);
145*4882a593Smuzhiyun return -EINVAL;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
__do_reset(struct usb_ep * ep,struct usb_request * req)152*4882a593Smuzhiyun static void __do_reset(struct usb_ep *ep, struct usb_request *req)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun u32 boot_flag = BOOT_NORMAL;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (rkusb_rst_code == 0x03)
157*4882a593Smuzhiyun boot_flag = BOOT_BROM_DOWNLOAD;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun rkusb_rst_code = 0; /* restore to default */
160*4882a593Smuzhiyun writel(boot_flag, (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun do_reset(NULL, 0, 0, NULL);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
rkusb_do_reset(struct fsg_common * common,struct fsg_buffhd * bh)165*4882a593Smuzhiyun static int rkusb_do_reset(struct fsg_common *common,
166*4882a593Smuzhiyun struct fsg_buffhd *bh)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun common->data_size_from_cmnd = common->cmnd[4];
169*4882a593Smuzhiyun common->residue = 0;
170*4882a593Smuzhiyun bh->inreq->complete = __do_reset;
171*4882a593Smuzhiyun bh->state = BUF_STATE_EMPTY;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun rkusb_rst_code = !common->cmnd[1] ? 0xff : common->cmnd[1];
174*4882a593Smuzhiyun return 0;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
rkusb_do_test_unit_ready(struct fsg_common * common,struct fsg_buffhd * bh)177*4882a593Smuzhiyun static int rkusb_do_test_unit_ready(struct fsg_common *common,
178*4882a593Smuzhiyun struct fsg_buffhd *bh)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun struct blk_desc *desc = &ums[common->lun].block_dev;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if ((desc->if_type == IF_TYPE_MTD && desc->devnum == BLK_MTD_SPI_NOR) ||
183*4882a593Smuzhiyun desc->if_type == IF_TYPE_SPINOR)
184*4882a593Smuzhiyun common->residue = 0x03 << 24; /* 128KB Max block xfer for SPI Nor */
185*4882a593Smuzhiyun else
186*4882a593Smuzhiyun common->residue = 0x06 << 24; /* Max block xfer support from host */
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun common->data_dir = DATA_DIR_NONE;
189*4882a593Smuzhiyun bh->state = BUF_STATE_EMPTY;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
rkusb_do_read_flash_id(struct fsg_common * common,struct fsg_buffhd * bh)194*4882a593Smuzhiyun static int rkusb_do_read_flash_id(struct fsg_common *common,
195*4882a593Smuzhiyun struct fsg_buffhd *bh)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun u8 *buf = (u8 *)bh->buf;
198*4882a593Smuzhiyun u32 len = 5;
199*4882a593Smuzhiyun enum if_type type = ums[common->lun].block_dev.if_type;
200*4882a593Smuzhiyun u32 devnum = ums[common->lun].block_dev.devnum;
201*4882a593Smuzhiyun const char *str;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun switch (type) {
204*4882a593Smuzhiyun case IF_TYPE_MMC:
205*4882a593Smuzhiyun str = "EMMC ";
206*4882a593Smuzhiyun break;
207*4882a593Smuzhiyun case IF_TYPE_RKNAND:
208*4882a593Smuzhiyun str = "NAND ";
209*4882a593Smuzhiyun break;
210*4882a593Smuzhiyun case IF_TYPE_MTD:
211*4882a593Smuzhiyun if (devnum == BLK_MTD_SPI_NAND)
212*4882a593Smuzhiyun str ="SNAND";
213*4882a593Smuzhiyun else if (devnum == BLK_MTD_NAND)
214*4882a593Smuzhiyun str = "NAND ";
215*4882a593Smuzhiyun else
216*4882a593Smuzhiyun str = "NOR ";
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun default:
219*4882a593Smuzhiyun str = "UNKN "; /* unknown */
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun memcpy((void *)&buf[0], str, len);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* Set data xfer size */
226*4882a593Smuzhiyun common->residue = common->data_size_from_cmnd = len;
227*4882a593Smuzhiyun common->data_size = len;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return len;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
rkusb_do_test_bad_block(struct fsg_common * common,struct fsg_buffhd * bh)232*4882a593Smuzhiyun static int rkusb_do_test_bad_block(struct fsg_common *common,
233*4882a593Smuzhiyun struct fsg_buffhd *bh)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun u8 *buf = (u8 *)bh->buf;
236*4882a593Smuzhiyun u32 len = 64;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun memset((void *)&buf[0], 0, len);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /* Set data xfer size */
241*4882a593Smuzhiyun common->residue = common->data_size_from_cmnd = len;
242*4882a593Smuzhiyun common->data_size = len;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return len;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
rkusb_do_read_flash_info(struct fsg_common * common,struct fsg_buffhd * bh)247*4882a593Smuzhiyun static int rkusb_do_read_flash_info(struct fsg_common *common,
248*4882a593Smuzhiyun struct fsg_buffhd *bh)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun struct blk_desc *desc = &ums[common->lun].block_dev;
251*4882a593Smuzhiyun u8 *buf = (u8 *)bh->buf;
252*4882a593Smuzhiyun u32 len = sizeof(struct rk_flash_info);
253*4882a593Smuzhiyun struct rk_flash_info finfo = {
254*4882a593Smuzhiyun .block_size = ROCKCHIP_FLASH_BLOCK_SIZE,
255*4882a593Smuzhiyun .ecc_bits = 0,
256*4882a593Smuzhiyun .page_size = ROCKCHIP_FLASH_PAGE_SIZE,
257*4882a593Smuzhiyun .access_time = 40,
258*4882a593Smuzhiyun .manufacturer = 0,
259*4882a593Smuzhiyun .flash_mask = 0
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun finfo.flash_size = (u32)desc->lba;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (desc->if_type == IF_TYPE_MTD &&
265*4882a593Smuzhiyun (desc->devnum == BLK_MTD_NAND ||
266*4882a593Smuzhiyun desc->devnum == BLK_MTD_SPI_NAND)) {
267*4882a593Smuzhiyun struct mtd_info *mtd = (struct mtd_info *)desc->bdev->priv;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (mtd) {
270*4882a593Smuzhiyun finfo.block_size = mtd->erasesize >> 9;
271*4882a593Smuzhiyun finfo.page_size = mtd->writesize >> 9;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (desc->if_type == IF_TYPE_MTD && desc->devnum == BLK_MTD_SPI_NOR) {
276*4882a593Smuzhiyun /* RV1126/RK3308 mtd spinor keep the former upgrade mode */
277*4882a593Smuzhiyun #if !defined(CONFIG_ROCKCHIP_RV1126) && !defined(CONFIG_ROCKCHIP_RK3308)
278*4882a593Smuzhiyun finfo.block_size = 0x80; /* Aligned to 64KB */
279*4882a593Smuzhiyun #else
280*4882a593Smuzhiyun finfo.block_size = ROCKCHIP_FLASH_BLOCK_SIZE;
281*4882a593Smuzhiyun #endif
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun debug("Flash info: block_size= %x page_size= %x\n", finfo.block_size,
285*4882a593Smuzhiyun finfo.page_size);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun if (finfo.flash_size)
288*4882a593Smuzhiyun finfo.flash_mask = 1;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun memset((void *)&buf[0], 0, len);
291*4882a593Smuzhiyun memcpy((void *)&buf[0], (void *)&finfo, len);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun /* Set data xfer size */
294*4882a593Smuzhiyun common->residue = common->data_size_from_cmnd = len;
295*4882a593Smuzhiyun /* legacy upgrade_tool does not set correct transfer size */
296*4882a593Smuzhiyun common->data_size = len;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun return len;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
rkusb_do_get_chip_info(struct fsg_common * common,struct fsg_buffhd * bh)301*4882a593Smuzhiyun static int rkusb_do_get_chip_info(struct fsg_common *common,
302*4882a593Smuzhiyun struct fsg_buffhd *bh)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun u8 *buf = (u8 *)bh->buf;
305*4882a593Smuzhiyun u32 len = common->data_size;
306*4882a593Smuzhiyun u32 chip_info[4];
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun memset((void *)chip_info, 0, sizeof(chip_info));
309*4882a593Smuzhiyun rockchip_rockusb_get_chip_info(chip_info);
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun memset((void *)&buf[0], 0, len);
312*4882a593Smuzhiyun memcpy((void *)&buf[0], (void *)chip_info, len);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* Set data xfer size */
315*4882a593Smuzhiyun common->residue = common->data_size_from_cmnd = len;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun return len;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
rkusb_do_lba_erase(struct fsg_common * common,struct fsg_buffhd * bh)320*4882a593Smuzhiyun static int rkusb_do_lba_erase(struct fsg_common *common,
321*4882a593Smuzhiyun struct fsg_buffhd *bh)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun struct fsg_lun *curlun = &common->luns[common->lun];
324*4882a593Smuzhiyun u32 lba, amount;
325*4882a593Smuzhiyun loff_t file_offset;
326*4882a593Smuzhiyun int rc;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun lba = get_unaligned_be32(&common->cmnd[2]);
329*4882a593Smuzhiyun if (lba >= curlun->num_sectors) {
330*4882a593Smuzhiyun curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
331*4882a593Smuzhiyun rc = -EINVAL;
332*4882a593Smuzhiyun goto out;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun file_offset = ((loff_t) lba) << 9;
336*4882a593Smuzhiyun amount = get_unaligned_be16(&common->cmnd[7]) << 9;
337*4882a593Smuzhiyun if (unlikely(amount == 0)) {
338*4882a593Smuzhiyun curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
339*4882a593Smuzhiyun rc = -EIO;
340*4882a593Smuzhiyun goto out;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /* Perform the erase */
344*4882a593Smuzhiyun rc = ums[common->lun].erase_sector(&ums[common->lun],
345*4882a593Smuzhiyun file_offset / SECTOR_SIZE,
346*4882a593Smuzhiyun amount / SECTOR_SIZE);
347*4882a593Smuzhiyun if (!rc) {
348*4882a593Smuzhiyun curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
349*4882a593Smuzhiyun rc = -EIO;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun out:
353*4882a593Smuzhiyun common->data_dir = DATA_DIR_NONE;
354*4882a593Smuzhiyun bh->state = BUF_STATE_EMPTY;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return rc;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
rkusb_do_erase_force(struct fsg_common * common,struct fsg_buffhd * bh)359*4882a593Smuzhiyun static int rkusb_do_erase_force(struct fsg_common *common,
360*4882a593Smuzhiyun struct fsg_buffhd *bh)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun struct blk_desc *desc = &ums[common->lun].block_dev;
363*4882a593Smuzhiyun struct fsg_lun *curlun = &common->luns[common->lun];
364*4882a593Smuzhiyun u16 block_size = ROCKCHIP_FLASH_BLOCK_SIZE;
365*4882a593Smuzhiyun u32 lba, amount;
366*4882a593Smuzhiyun loff_t file_offset;
367*4882a593Smuzhiyun int rc;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun lba = get_unaligned_be32(&common->cmnd[2]);
370*4882a593Smuzhiyun if (lba >= curlun->num_sectors) {
371*4882a593Smuzhiyun curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
372*4882a593Smuzhiyun rc = -EINVAL;
373*4882a593Smuzhiyun goto out;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (desc->if_type == IF_TYPE_MTD &&
377*4882a593Smuzhiyun (desc->devnum == BLK_MTD_NAND ||
378*4882a593Smuzhiyun desc->devnum == BLK_MTD_SPI_NAND)) {
379*4882a593Smuzhiyun struct mtd_info *mtd = (struct mtd_info *)desc->bdev->priv;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (mtd)
382*4882a593Smuzhiyun block_size = mtd->erasesize >> 9;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun file_offset = ((loff_t)lba) * block_size;
386*4882a593Smuzhiyun amount = get_unaligned_be16(&common->cmnd[7]) * block_size;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun debug("%s lba= %x, nsec= %x\n", __func__, lba,
389*4882a593Smuzhiyun (u32)get_unaligned_be16(&common->cmnd[7]));
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun if (unlikely(amount == 0)) {
392*4882a593Smuzhiyun curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
393*4882a593Smuzhiyun rc = -EIO;
394*4882a593Smuzhiyun goto out;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /* Perform the erase */
398*4882a593Smuzhiyun rc = ums[common->lun].erase_sector(&ums[common->lun],
399*4882a593Smuzhiyun file_offset,
400*4882a593Smuzhiyun amount);
401*4882a593Smuzhiyun if (!rc) {
402*4882a593Smuzhiyun curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
403*4882a593Smuzhiyun rc = -EIO;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun out:
407*4882a593Smuzhiyun common->data_dir = DATA_DIR_NONE;
408*4882a593Smuzhiyun bh->state = BUF_STATE_EMPTY;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun return rc;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
rkusb_do_vs_write(struct fsg_common * common)414*4882a593Smuzhiyun static int rkusb_do_vs_write(struct fsg_common *common)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun struct fsg_lun *curlun = &common->luns[common->lun];
417*4882a593Smuzhiyun u16 type = get_unaligned_be16(&common->cmnd[4]);
418*4882a593Smuzhiyun struct vendor_item *vhead;
419*4882a593Smuzhiyun struct fsg_buffhd *bh;
420*4882a593Smuzhiyun void *data;
421*4882a593Smuzhiyun int rc;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun if (common->data_size >= (u32)65536) {
424*4882a593Smuzhiyun /* _MUST_ small than 64K */
425*4882a593Smuzhiyun curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
426*4882a593Smuzhiyun return -EINVAL;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun common->residue = common->data_size;
430*4882a593Smuzhiyun common->usb_amount_left = common->data_size;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun /* Carry out the file writes */
433*4882a593Smuzhiyun if (unlikely(common->data_size == 0))
434*4882a593Smuzhiyun return -EIO; /* No data to write */
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun for (;;) {
437*4882a593Smuzhiyun if (common->usb_amount_left > 0) {
438*4882a593Smuzhiyun /* Wait for the next buffer to become available */
439*4882a593Smuzhiyun bh = common->next_buffhd_to_fill;
440*4882a593Smuzhiyun if (bh->state != BUF_STATE_EMPTY)
441*4882a593Smuzhiyun goto wait;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun /* Request the next buffer */
444*4882a593Smuzhiyun common->usb_amount_left -= common->data_size;
445*4882a593Smuzhiyun bh->outreq->length = common->data_size;
446*4882a593Smuzhiyun bh->bulk_out_intended_length = common->data_size;
447*4882a593Smuzhiyun bh->outreq->short_not_ok = 1;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun START_TRANSFER_OR(common, bulk_out, bh->outreq,
450*4882a593Smuzhiyun &bh->outreq_busy, &bh->state)
451*4882a593Smuzhiyun /*
452*4882a593Smuzhiyun * Don't know what to do if
453*4882a593Smuzhiyun * common->fsg is NULL
454*4882a593Smuzhiyun */
455*4882a593Smuzhiyun return -EIO;
456*4882a593Smuzhiyun common->next_buffhd_to_fill = bh->next;
457*4882a593Smuzhiyun } else {
458*4882a593Smuzhiyun /* Then, wait for the data to become available */
459*4882a593Smuzhiyun bh = common->next_buffhd_to_drain;
460*4882a593Smuzhiyun if (bh->state != BUF_STATE_FULL)
461*4882a593Smuzhiyun goto wait;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun common->next_buffhd_to_drain = bh->next;
464*4882a593Smuzhiyun bh->state = BUF_STATE_EMPTY;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /* Did something go wrong with the transfer? */
467*4882a593Smuzhiyun if (bh->outreq->status != 0) {
468*4882a593Smuzhiyun curlun->sense_data = SS_COMMUNICATION_FAILURE;
469*4882a593Smuzhiyun curlun->info_valid = 1;
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /* Perform the write */
474*4882a593Smuzhiyun vhead = (struct vendor_item *)bh->buf;
475*4882a593Smuzhiyun data = bh->buf + sizeof(struct vendor_item);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun if (!type) {
478*4882a593Smuzhiyun if (vhead->id == HDCP_14_HDMI_ID ||
479*4882a593Smuzhiyun vhead->id == HDCP_14_HDMIRX_ID ||
480*4882a593Smuzhiyun vhead->id == HDCP_14_DP_ID) {
481*4882a593Smuzhiyun rc = vendor_handle_hdcp(vhead);
482*4882a593Smuzhiyun if (rc < 0) {
483*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
484*4882a593Smuzhiyun return -EIO;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun /* Vendor storage */
489*4882a593Smuzhiyun rc = vendor_storage_write(vhead->id,
490*4882a593Smuzhiyun (char __user *)data,
491*4882a593Smuzhiyun vhead->size);
492*4882a593Smuzhiyun if (rc < 0) {
493*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
494*4882a593Smuzhiyun return -EIO;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun } else if (type == 1) {
497*4882a593Smuzhiyun /* RPMB */
498*4882a593Smuzhiyun rc =
499*4882a593Smuzhiyun write_keybox_to_secure_storage((u8 *)data,
500*4882a593Smuzhiyun vhead->size);
501*4882a593Smuzhiyun if (rc < 0) {
502*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
503*4882a593Smuzhiyun return -EIO;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun } else if (type == 2) {
506*4882a593Smuzhiyun /* security storage */
507*4882a593Smuzhiyun #ifdef CONFIG_RK_AVB_LIBAVB_USER
508*4882a593Smuzhiyun debug("%s call rk_avb_write_perm_attr %d, %d\n",
509*4882a593Smuzhiyun __func__, vhead->id, vhead->size);
510*4882a593Smuzhiyun rc = rk_avb_write_perm_attr(vhead->id,
511*4882a593Smuzhiyun (char __user *)data,
512*4882a593Smuzhiyun vhead->size);
513*4882a593Smuzhiyun if (rc < 0) {
514*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
515*4882a593Smuzhiyun return -EIO;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun #else
518*4882a593Smuzhiyun printf("Please enable CONFIG_RK_AVB_LIBAVB_USER\n");
519*4882a593Smuzhiyun #endif
520*4882a593Smuzhiyun } else if (type == 3) {
521*4882a593Smuzhiyun /* efuse or otp*/
522*4882a593Smuzhiyun #ifdef CONFIG_OPTEE_CLIENT
523*4882a593Smuzhiyun if (memcmp(data, "TAEK", 4) == 0) {
524*4882a593Smuzhiyun if (vhead->size - 8 != 32) {
525*4882a593Smuzhiyun printf("check ta encryption key size fail!\n");
526*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
527*4882a593Smuzhiyun return -EIO;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun if (trusty_write_ta_encryption_key((uint32_t *)(data + 8), 8) != 0) {
530*4882a593Smuzhiyun printf("trusty_write_ta_encryption_key error!");
531*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
532*4882a593Smuzhiyun return -EIO;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun } else if (memcmp(data, "EHUK", 4) == 0) {
535*4882a593Smuzhiyun if (vhead->size - 8 != 32) {
536*4882a593Smuzhiyun printf("check oem huk size fail!\n");
537*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
538*4882a593Smuzhiyun return -EIO;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun if (trusty_write_oem_huk((uint32_t *)(data + 8), 8) != 0) {
541*4882a593Smuzhiyun printf("trusty_write_oem_huk error!");
542*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
543*4882a593Smuzhiyun return -EIO;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun } else {
546*4882a593Smuzhiyun printf("Unknown tag\n");
547*4882a593Smuzhiyun curlun->sense_data = SS_WRITE_ERROR;
548*4882a593Smuzhiyun return -EIO;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun #else
551*4882a593Smuzhiyun printf("Please enable CONFIG_OPTEE_CLIENT\n");
552*4882a593Smuzhiyun #endif
553*4882a593Smuzhiyun } else {
554*4882a593Smuzhiyun return -EINVAL;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun common->residue -= common->data_size;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun /* Did the host decide to stop early? */
560*4882a593Smuzhiyun if (bh->outreq->actual != bh->outreq->length)
561*4882a593Smuzhiyun common->short_packet_received = 1;
562*4882a593Smuzhiyun break; /* Command done */
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun wait:
565*4882a593Smuzhiyun /* Wait for something to happen */
566*4882a593Smuzhiyun rc = sleep_thread(common);
567*4882a593Smuzhiyun if (rc)
568*4882a593Smuzhiyun return rc;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun return -EIO; /* No default reply */
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
rkusb_do_vs_read(struct fsg_common * common)574*4882a593Smuzhiyun static int rkusb_do_vs_read(struct fsg_common *common)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun struct fsg_lun *curlun = &common->luns[common->lun];
577*4882a593Smuzhiyun u16 type = get_unaligned_be16(&common->cmnd[4]);
578*4882a593Smuzhiyun struct vendor_item *vhead;
579*4882a593Smuzhiyun struct fsg_buffhd *bh;
580*4882a593Smuzhiyun void *data;
581*4882a593Smuzhiyun int rc;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun if (common->data_size >= (u32)65536) {
584*4882a593Smuzhiyun /* _MUST_ small than 64K */
585*4882a593Smuzhiyun curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
586*4882a593Smuzhiyun return -EINVAL;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun common->residue = common->data_size;
590*4882a593Smuzhiyun common->usb_amount_left = common->data_size;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun /* Carry out the file reads */
593*4882a593Smuzhiyun if (unlikely(common->data_size == 0))
594*4882a593Smuzhiyun return -EIO; /* No default reply */
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun for (;;) {
597*4882a593Smuzhiyun /* Wait for the next buffer to become available */
598*4882a593Smuzhiyun bh = common->next_buffhd_to_fill;
599*4882a593Smuzhiyun while (bh->state != BUF_STATE_EMPTY) {
600*4882a593Smuzhiyun rc = sleep_thread(common);
601*4882a593Smuzhiyun if (rc)
602*4882a593Smuzhiyun return rc;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun memset(bh->buf, 0, FSG_BUFLEN);
606*4882a593Smuzhiyun vhead = (struct vendor_item *)bh->buf;
607*4882a593Smuzhiyun data = bh->buf + sizeof(struct vendor_item);
608*4882a593Smuzhiyun vhead->id = get_unaligned_be16(&common->cmnd[2]);
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun if (!type) {
611*4882a593Smuzhiyun /* Vendor storage */
612*4882a593Smuzhiyun rc = vendor_storage_read(vhead->id,
613*4882a593Smuzhiyun (char __user *)data,
614*4882a593Smuzhiyun common->data_size);
615*4882a593Smuzhiyun if (!rc) {
616*4882a593Smuzhiyun curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
617*4882a593Smuzhiyun return -EIO;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun vhead->size = rc;
620*4882a593Smuzhiyun } else if (type == 1) {
621*4882a593Smuzhiyun /* RPMB */
622*4882a593Smuzhiyun rc =
623*4882a593Smuzhiyun read_raw_data_from_secure_storage((u8 *)data,
624*4882a593Smuzhiyun common->data_size);
625*4882a593Smuzhiyun if (!rc) {
626*4882a593Smuzhiyun curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
627*4882a593Smuzhiyun return -EIO;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun vhead->size = rc;
630*4882a593Smuzhiyun } else if (type == 2) {
631*4882a593Smuzhiyun /* security storage */
632*4882a593Smuzhiyun #ifdef CONFIG_RK_AVB_LIBAVB_USER
633*4882a593Smuzhiyun rc = rk_avb_read_perm_attr(vhead->id,
634*4882a593Smuzhiyun (char __user *)data,
635*4882a593Smuzhiyun vhead->size);
636*4882a593Smuzhiyun if (rc < 0)
637*4882a593Smuzhiyun return -EIO;
638*4882a593Smuzhiyun vhead->size = rc;
639*4882a593Smuzhiyun #else
640*4882a593Smuzhiyun printf("Please enable CONFIG_RK_AVB_LIBAVB_USER!\n");
641*4882a593Smuzhiyun #endif
642*4882a593Smuzhiyun } else {
643*4882a593Smuzhiyun return -EINVAL;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun common->residue -= common->data_size;
647*4882a593Smuzhiyun bh->inreq->length = common->data_size;
648*4882a593Smuzhiyun bh->state = BUF_STATE_FULL;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun break; /* No more left to read */
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun return -EIO; /* No default reply */
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun #endif
656*4882a593Smuzhiyun
rkusb_do_get_storage_info(struct fsg_common * common,struct fsg_buffhd * bh)657*4882a593Smuzhiyun static int rkusb_do_get_storage_info(struct fsg_common *common,
658*4882a593Smuzhiyun struct fsg_buffhd *bh)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun enum if_type type = ums[common->lun].block_dev.if_type;
661*4882a593Smuzhiyun int devnum = ums[common->lun].block_dev.devnum;
662*4882a593Smuzhiyun u32 media = BOOT_TYPE_UNKNOWN;
663*4882a593Smuzhiyun u32 len = common->data_size;
664*4882a593Smuzhiyun u8 *buf = (u8 *)bh->buf;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (len > 4)
667*4882a593Smuzhiyun len = 4;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun switch (type) {
670*4882a593Smuzhiyun case IF_TYPE_MMC:
671*4882a593Smuzhiyun media = BOOT_TYPE_EMMC;
672*4882a593Smuzhiyun break;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun case IF_TYPE_SD:
675*4882a593Smuzhiyun media = BOOT_TYPE_SD0;
676*4882a593Smuzhiyun break;
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun case IF_TYPE_MTD:
679*4882a593Smuzhiyun if (devnum == BLK_MTD_SPI_NAND)
680*4882a593Smuzhiyun media = BOOT_TYPE_MTD_BLK_SPI_NAND;
681*4882a593Smuzhiyun else if (devnum == BLK_MTD_NAND)
682*4882a593Smuzhiyun media = BOOT_TYPE_NAND;
683*4882a593Smuzhiyun else
684*4882a593Smuzhiyun media = BOOT_TYPE_MTD_BLK_SPI_NOR;
685*4882a593Smuzhiyun break;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun case IF_TYPE_SCSI:
688*4882a593Smuzhiyun media = BOOT_TYPE_SATA;
689*4882a593Smuzhiyun break;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun case IF_TYPE_RKNAND:
692*4882a593Smuzhiyun media = BOOT_TYPE_NAND;
693*4882a593Smuzhiyun break;
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun case IF_TYPE_NVME:
696*4882a593Smuzhiyun media = BOOT_TYPE_PCIE;
697*4882a593Smuzhiyun break;
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun default:
700*4882a593Smuzhiyun break;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun memcpy((void *)&buf[0], (void *)&media, len);
704*4882a593Smuzhiyun common->residue = len;
705*4882a593Smuzhiyun common->data_size_from_cmnd = len;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun return len;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
rkusb_do_read_capacity(struct fsg_common * common,struct fsg_buffhd * bh)710*4882a593Smuzhiyun static int rkusb_do_read_capacity(struct fsg_common *common,
711*4882a593Smuzhiyun struct fsg_buffhd *bh)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun u8 *buf = (u8 *)bh->buf;
714*4882a593Smuzhiyun u32 len = common->data_size;
715*4882a593Smuzhiyun enum if_type type = ums[common->lun].block_dev.if_type;
716*4882a593Smuzhiyun int devnum = ums[common->lun].block_dev.devnum;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun /*
719*4882a593Smuzhiyun * bit[0]: Direct LBA, 0: Disabled;
720*4882a593Smuzhiyun * bit[1]: Vendor Storage API, 0: Disabed (default);
721*4882a593Smuzhiyun * bit[2]: First 4M Access, 0: Disabled;
722*4882a593Smuzhiyun * bit[3]: Read LBA On, 0: Disabed (default);
723*4882a593Smuzhiyun * bit[4]: New Vendor Storage API, 0: Disabed;
724*4882a593Smuzhiyun * bit[5]: Read uart data from ram
725*4882a593Smuzhiyun * bit[6]: Read IDB config
726*4882a593Smuzhiyun * bit[7]: Read SecureMode
727*4882a593Smuzhiyun * bit[8]: New IDB feature
728*4882a593Smuzhiyun * bit[9]: Get storage media info
729*4882a593Smuzhiyun * bit[10:63}: Reserved.
730*4882a593Smuzhiyun */
731*4882a593Smuzhiyun memset((void *)&buf[0], 0, len);
732*4882a593Smuzhiyun if (type == IF_TYPE_MMC || type == IF_TYPE_SD || type == IF_TYPE_NVME)
733*4882a593Smuzhiyun buf[0] = BIT(0) | BIT(2) | BIT(4);
734*4882a593Smuzhiyun else
735*4882a593Smuzhiyun buf[0] = BIT(0) | BIT(4);
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun if (type == IF_TYPE_MTD &&
738*4882a593Smuzhiyun (devnum == BLK_MTD_NAND ||
739*4882a593Smuzhiyun devnum == BLK_MTD_SPI_NAND))
740*4882a593Smuzhiyun buf[0] |= (1 << 6);
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun #if !defined(CONFIG_ROCKCHIP_RV1126) && !defined(CONFIG_ROCKCHIP_RK3308)
743*4882a593Smuzhiyun if (type == IF_TYPE_MTD && devnum == BLK_MTD_SPI_NOR)
744*4882a593Smuzhiyun buf[0] |= (1 << 6);
745*4882a593Smuzhiyun #endif
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun #if defined(CONFIG_ROCKCHIP_NEW_IDB)
748*4882a593Smuzhiyun buf[1] = BIT(0);
749*4882a593Smuzhiyun #endif
750*4882a593Smuzhiyun buf[1] |= BIT(1); /* Switch Storage */
751*4882a593Smuzhiyun buf[1] |= BIT(2); /* LBAwrite Parity */
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun /* Set data xfer size */
754*4882a593Smuzhiyun common->residue = len;
755*4882a593Smuzhiyun common->data_size_from_cmnd = len;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun return len;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
rkusb_fixup_cbwcb(struct fsg_common * common,struct fsg_buffhd * bh)760*4882a593Smuzhiyun static void rkusb_fixup_cbwcb(struct fsg_common *common,
761*4882a593Smuzhiyun struct fsg_buffhd *bh)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun struct usb_request *req = bh->outreq;
764*4882a593Smuzhiyun struct fsg_bulk_cb_wrap *cbw = req->buf;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun /* FIXME cbw.DataTransferLength was not set by Upgrade Tool */
767*4882a593Smuzhiyun common->data_size = le32_to_cpu(cbw->DataTransferLength);
768*4882a593Smuzhiyun if (common->data_size == 0) {
769*4882a593Smuzhiyun common->data_size =
770*4882a593Smuzhiyun get_unaligned_be16(&common->cmnd[7]) << 9;
771*4882a593Smuzhiyun printf("Trasfer Length NOT set, please use new version tool\n");
772*4882a593Smuzhiyun debug("%s %d, cmnd1 %x\n", __func__,
773*4882a593Smuzhiyun get_unaligned_be16(&common->cmnd[7]),
774*4882a593Smuzhiyun get_unaligned_be16(&common->cmnd[1]));
775*4882a593Smuzhiyun }
776*4882a593Smuzhiyun if (cbw->Flags & USB_BULK_IN_FLAG)
777*4882a593Smuzhiyun common->data_dir = DATA_DIR_TO_HOST;
778*4882a593Smuzhiyun else
779*4882a593Smuzhiyun common->data_dir = DATA_DIR_FROM_HOST;
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun /* Not support */
782*4882a593Smuzhiyun common->cmnd[1] = 0;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
rkusb_cmd_process(struct fsg_common * common,struct fsg_buffhd * bh,int * reply)785*4882a593Smuzhiyun static int rkusb_cmd_process(struct fsg_common *common,
786*4882a593Smuzhiyun struct fsg_buffhd *bh, int *reply)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun struct usb_request *req = bh->outreq;
789*4882a593Smuzhiyun struct fsg_bulk_cb_wrap *cbw = req->buf;
790*4882a593Smuzhiyun int rc;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun dump_cbw(cbw);
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun if (rkusb_check_lun(common)) {
795*4882a593Smuzhiyun *reply = -EINVAL;
796*4882a593Smuzhiyun return RKUSB_RC_ERROR;
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun switch (common->cmnd[0]) {
800*4882a593Smuzhiyun case RKUSB_TEST_UNIT_READY:
801*4882a593Smuzhiyun *reply = rkusb_do_test_unit_ready(common, bh);
802*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
803*4882a593Smuzhiyun break;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun case RKUSB_READ_FLASH_ID:
806*4882a593Smuzhiyun *reply = rkusb_do_read_flash_id(common, bh);
807*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
808*4882a593Smuzhiyun break;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun case RKUSB_TEST_BAD_BLOCK:
811*4882a593Smuzhiyun *reply = rkusb_do_test_bad_block(common, bh);
812*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
813*4882a593Smuzhiyun break;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun case RKUSB_ERASE_10_FORCE:
816*4882a593Smuzhiyun *reply = rkusb_do_erase_force(common, bh);
817*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
818*4882a593Smuzhiyun break;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun case RKUSB_LBA_READ_10:
821*4882a593Smuzhiyun rkusb_fixup_cbwcb(common, bh);
822*4882a593Smuzhiyun common->cmnd[0] = SC_READ_10;
823*4882a593Smuzhiyun common->cmnd[1] = 0; /* Not support */
824*4882a593Smuzhiyun rc = RKUSB_RC_CONTINUE;
825*4882a593Smuzhiyun break;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun case RKUSB_LBA_WRITE_10:
828*4882a593Smuzhiyun rkusb_fixup_cbwcb(common, bh);
829*4882a593Smuzhiyun common->cmnd[0] = SC_WRITE_10;
830*4882a593Smuzhiyun common->cmnd[1] = 0; /* Not support */
831*4882a593Smuzhiyun rc = RKUSB_RC_CONTINUE;
832*4882a593Smuzhiyun break;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun case RKUSB_READ_FLASH_INFO:
835*4882a593Smuzhiyun *reply = rkusb_do_read_flash_info(common, bh);
836*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
837*4882a593Smuzhiyun break;
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun case RKUSB_GET_CHIP_VER:
840*4882a593Smuzhiyun *reply = rkusb_do_get_chip_info(common, bh);
841*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
842*4882a593Smuzhiyun break;
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun case RKUSB_LBA_ERASE:
845*4882a593Smuzhiyun *reply = rkusb_do_lba_erase(common, bh);
846*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
847*4882a593Smuzhiyun break;
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
850*4882a593Smuzhiyun case RKUSB_VS_WRITE:
851*4882a593Smuzhiyun *reply = rkusb_do_vs_write(common);
852*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
853*4882a593Smuzhiyun break;
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun case RKUSB_VS_READ:
856*4882a593Smuzhiyun *reply = rkusb_do_vs_read(common);
857*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
858*4882a593Smuzhiyun break;
859*4882a593Smuzhiyun #endif
860*4882a593Smuzhiyun case RKUSB_GET_STORAGE_MEDIA:
861*4882a593Smuzhiyun *reply = rkusb_do_get_storage_info(common, bh);
862*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
863*4882a593Smuzhiyun break;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun case RKUSB_READ_CAPACITY:
866*4882a593Smuzhiyun *reply = rkusb_do_read_capacity(common, bh);
867*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
868*4882a593Smuzhiyun break;
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun case RKUSB_RESET:
871*4882a593Smuzhiyun *reply = rkusb_do_reset(common, bh);
872*4882a593Smuzhiyun rc = RKUSB_RC_FINISHED;
873*4882a593Smuzhiyun break;
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun case RKUSB_READ_10:
876*4882a593Smuzhiyun case RKUSB_WRITE_10:
877*4882a593Smuzhiyun printf("CMD Not support, pls use new version Tool\n");
878*4882a593Smuzhiyun case RKUSB_SET_DEVICE_ID:
879*4882a593Smuzhiyun case RKUSB_ERASE_10:
880*4882a593Smuzhiyun case RKUSB_WRITE_SPARE:
881*4882a593Smuzhiyun case RKUSB_READ_SPARE:
882*4882a593Smuzhiyun case RKUSB_GET_VERSION:
883*4882a593Smuzhiyun case RKUSB_ERASE_SYS_DISK:
884*4882a593Smuzhiyun case RKUSB_SDRAM_READ_10:
885*4882a593Smuzhiyun case RKUSB_SDRAM_WRITE_10:
886*4882a593Smuzhiyun case RKUSB_SDRAM_EXECUTE:
887*4882a593Smuzhiyun case RKUSB_LOW_FORMAT:
888*4882a593Smuzhiyun case RKUSB_SET_RESET_FLAG:
889*4882a593Smuzhiyun case RKUSB_SPI_READ_10:
890*4882a593Smuzhiyun case RKUSB_SPI_WRITE_10:
891*4882a593Smuzhiyun case RKUSB_SESSION:
892*4882a593Smuzhiyun /* Fall through */
893*4882a593Smuzhiyun default:
894*4882a593Smuzhiyun rc = RKUSB_RC_UNKNOWN_CMND;
895*4882a593Smuzhiyun break;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun return rc;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun
rkusb_do_check_parity(struct fsg_common * common)901*4882a593Smuzhiyun int rkusb_do_check_parity(struct fsg_common *common)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun int ret = 0, rc;
904*4882a593Smuzhiyun u32 parity, i, usb_parity, lba, len;
905*4882a593Smuzhiyun static u32 usb_check_buffer[1024 * 256];
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun usb_parity = common->cmnd[9] | (common->cmnd[10] << 8) |
908*4882a593Smuzhiyun (common->cmnd[11] << 16) | (common->cmnd[12] << 24);
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun if (common->cmnd[0] == SC_WRITE_10 && (usb_parity)) {
911*4882a593Smuzhiyun lba = get_unaligned_be32(&common->cmnd[2]);
912*4882a593Smuzhiyun len = common->data_size_from_cmnd >> 9;
913*4882a593Smuzhiyun rc = blk_dread(&ums[common->lun].block_dev, lba, len, usb_check_buffer);
914*4882a593Smuzhiyun parity = 0x000055aa;
915*4882a593Smuzhiyun for (i = 0; i < len * 128; i++)
916*4882a593Smuzhiyun parity += usb_check_buffer[i];
917*4882a593Smuzhiyun if (!rc || parity != usb_parity)
918*4882a593Smuzhiyun common->phase_error = 1;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun return ret;
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun DECLARE_GADGET_BIND_CALLBACK(rkusb_ums_dnl, fsg_add);
925