1 /* 2 * Copyright 2017 Rockchip Electronics Co., Ltd 3 * Frank Wang <frank.wang@rock-chips.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <errno.h> 9 #include <common.h> 10 #include <command.h> 11 #include <console.h> 12 #include <dm/device.h> 13 #include <g_dnl.h> 14 #include <part.h> 15 #include <usb.h> 16 #include <usb_mass_storage.h> 17 #include <rockusb.h> 18 19 static struct rockusb rkusb; 20 static struct rockusb *g_rkusb; 21 22 static int rkusb_read_sector(struct ums *ums_dev, 23 ulong start, lbaint_t blkcnt, void *buf) 24 { 25 struct blk_desc *block_dev = &ums_dev->block_dev; 26 lbaint_t blkstart = start + ums_dev->start_sector; 27 int ret; 28 29 if ((blkstart + blkcnt) > RKUSB_READ_LIMIT_ADDR) { 30 memset(buf, 0xcc, blkcnt * SECTOR_SIZE); 31 return blkcnt; 32 } else { 33 ret = blk_dread(block_dev, blkstart, blkcnt, buf); 34 if (!ret) 35 ret = -EIO; 36 return ret; 37 } 38 } 39 40 static int rkusb_write_sector(struct ums *ums_dev, 41 ulong start, lbaint_t blkcnt, const void *buf) 42 { 43 struct blk_desc *block_dev = &ums_dev->block_dev; 44 lbaint_t blkstart = start + ums_dev->start_sector; 45 struct blk_desc *mtd_blk = NULL; 46 int ret; 47 48 if (block_dev->if_type == IF_TYPE_MTD) { 49 mtd_blk = dev_get_uclass_platdata(block_dev->bdev); 50 mtd_blk->op_flag |= BLK_MTD_CONT_WRITE; 51 } 52 53 ret = blk_dwrite(block_dev, blkstart, blkcnt, buf); 54 if (!ret) 55 ret = -EIO; 56 #if defined(CONFIG_SCSI) && defined(CONFIG_CMD_SCSI) && (defined(CONFIG_UFS)) 57 if (block_dev->if_type == IF_TYPE_SCSI && block_dev->rawblksz == 4096) { 58 /* write loader to UFS BootA */ 59 if (blkstart < 8192 && blkstart >= 64) 60 blk_write_devnum(IF_TYPE_SCSI, 1, blkstart, blkcnt, (ulong *)buf); 61 } 62 #endif 63 if (block_dev->if_type == IF_TYPE_MTD) { 64 mtd_blk->op_flag &= ~(BLK_MTD_CONT_WRITE); 65 } 66 return ret; 67 } 68 69 static int rkusb_erase_sector(struct ums *ums_dev, 70 ulong start, lbaint_t blkcnt) 71 { 72 struct blk_desc *block_dev = &ums_dev->block_dev; 73 lbaint_t blkstart = start + ums_dev->start_sector; 74 75 return blk_derase(block_dev, blkstart, blkcnt); 76 } 77 78 static void rkusb_fini(void) 79 { 80 int i; 81 82 for (i = 0; i < g_rkusb->ums_cnt; i++) 83 free((void *)g_rkusb->ums[i].name); 84 free(g_rkusb->ums); 85 g_rkusb->ums = NULL; 86 g_rkusb->ums_cnt = 0; 87 g_rkusb = NULL; 88 } 89 90 #define RKUSB_NAME_LEN 16 91 92 static int rkusb_init(const char *devtype, const char *devnums_part_str) 93 { 94 char *s, *t, *devnum_part_str, *name; 95 struct blk_desc *block_dev; 96 disk_partition_t info; 97 int partnum, cnt; 98 int ret = -1; 99 struct ums *ums_new; 100 101 s = strdup(devnums_part_str); 102 if (!s) 103 return -1; 104 105 t = s; 106 g_rkusb->ums_cnt = 0; 107 108 for (;;) { 109 devnum_part_str = strsep(&t, ","); 110 if (!devnum_part_str) 111 break; 112 #if defined(CONFIG_SCSI) && defined(CONFIG_CMD_SCSI) && (defined(CONFIG_UFS)) 113 if (!strcmp(devtype, "scsi")) { 114 block_dev= blk_get_devnum_by_typename(devtype, 0); 115 if (block_dev == NULL) 116 return -ENXIO; 117 } else 118 #endif 119 { 120 partnum = blk_get_device_part_str(devtype, devnum_part_str, 121 &block_dev, &info, 1); 122 if (partnum < 0) 123 goto cleanup; 124 } 125 126 /* f_mass_storage.c assumes SECTOR_SIZE sectors */ 127 if (block_dev->blksz != SECTOR_SIZE) 128 goto cleanup; 129 130 ums_new = realloc(g_rkusb->ums, (g_rkusb->ums_cnt + 1) * 131 sizeof(*g_rkusb->ums)); 132 if (!ums_new) 133 goto cleanup; 134 g_rkusb->ums = ums_new; 135 cnt = g_rkusb->ums_cnt; 136 137 /* Expose all partitions for rockusb command */ 138 g_rkusb->ums[cnt].start_sector = 0; 139 g_rkusb->ums[cnt].num_sectors = block_dev->lba; 140 141 g_rkusb->ums[cnt].read_sector = rkusb_read_sector; 142 g_rkusb->ums[cnt].write_sector = rkusb_write_sector; 143 g_rkusb->ums[cnt].erase_sector = rkusb_erase_sector; 144 145 name = malloc(RKUSB_NAME_LEN); 146 if (!name) 147 goto cleanup; 148 snprintf(name, RKUSB_NAME_LEN, "rkusb disk %d", cnt); 149 g_rkusb->ums[cnt].name = name; 150 g_rkusb->ums[cnt].block_dev = *block_dev; 151 152 printf("RKUSB: LUN %d, dev %d, hwpart %d, sector %#x, count %#x\n", 153 g_rkusb->ums_cnt, 154 g_rkusb->ums[cnt].block_dev.devnum, 155 g_rkusb->ums[cnt].block_dev.hwpart, 156 g_rkusb->ums[cnt].start_sector, 157 g_rkusb->ums[cnt].num_sectors); 158 159 g_rkusb->ums_cnt++; 160 } 161 162 if (g_rkusb->ums_cnt) 163 ret = 0; 164 165 cleanup: 166 free(s); 167 if (ret < 0) 168 rkusb_fini(); 169 170 return ret; 171 } 172 173 void rkusb_force_to_usb2(bool enable) 174 { 175 if (g_rkusb) 176 g_rkusb->force_usb2 = enable; 177 } 178 179 bool rkusb_force_usb2_enabled(void) 180 { 181 if (!g_rkusb) 182 return true; 183 184 return g_rkusb->force_usb2; 185 } 186 187 void rkusb_switch_to_usb3_enable(bool enable) 188 { 189 if (g_rkusb) 190 g_rkusb->switch_usb3 = enable; 191 } 192 193 bool rkusb_switch_usb3_enabled(void) 194 { 195 if (!g_rkusb) 196 return false; 197 198 return g_rkusb->switch_usb3; 199 } 200 201 static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 202 { 203 const char *usb_controller; 204 const char *devtype; 205 const char *devnum; 206 unsigned int controller_index; 207 int rc; 208 int cable_ready_timeout __maybe_unused; 209 const char *s; 210 211 if (argc != 4) 212 return CMD_RET_USAGE; 213 214 re_enumerate: 215 usb_controller = argv[1]; 216 devtype = argv[2]; 217 devnum = argv[3]; 218 219 if (!strcmp(devtype, "mmc") && !strcmp(devnum, "1")) { 220 pr_err("Forbid to flash mmc 1(sdcard)\n"); 221 return CMD_RET_FAILURE; 222 } else if ((!strcmp(devtype, "nvme") || !strcmp(devtype, "scsi")) && !strcmp(devnum, "0")) { 223 /* 224 * Add partnum ":0" to active 'allow_whole_dev' partition 225 * search mechanism on multi storage, where there maybe not 226 * valid partition table. 227 */ 228 devnum = "0:0"; 229 } 230 231 g_rkusb = &rkusb; 232 rc = rkusb_init(devtype, devnum); 233 if (rc < 0) 234 return CMD_RET_FAILURE; 235 236 if (g_rkusb->ums[0].block_dev.if_type == IF_TYPE_MTD && 237 g_rkusb->ums[0].block_dev.devnum == BLK_MTD_NAND) { 238 #ifdef CONFIG_CMD_GO 239 pr_err("Enter bootrom rockusb...\n"); 240 flushc(); 241 run_command("rbrom", 0); 242 #else 243 pr_err("rockusb: count not support loader upgrade!\n"); 244 #endif 245 } 246 247 controller_index = (unsigned int)(simple_strtoul( 248 usb_controller, NULL, 0)); 249 rc = usb_gadget_initialize(controller_index); 250 if (rc) { 251 pr_err("Couldn't init USB controller."); 252 rc = CMD_RET_FAILURE; 253 goto cleanup_rkusb; 254 } 255 256 rc = fsg_init(g_rkusb->ums, g_rkusb->ums_cnt); 257 if (rc) { 258 pr_err("fsg_init failed"); 259 rc = CMD_RET_FAILURE; 260 goto cleanup_board; 261 } 262 263 if (rkusb_switch_usb3_enabled()) { 264 /* Maskrom usb3 serialnumber get from upgrade tool */ 265 rkusb_switch_to_usb3_enable(false); 266 } else { 267 s = env_get("serial#"); 268 if (s) { 269 char *sn = (char *)calloc(strlen(s) + 1, sizeof(char)); 270 char *sn_p = sn; 271 272 if (!sn) 273 goto cleanup_board; 274 275 memcpy(sn, s, strlen(s)); 276 while (*sn_p) { 277 if (*sn_p == '\\' || *sn_p == '/') 278 *sn_p = '_'; 279 sn_p++; 280 } 281 282 g_dnl_set_serialnumber(sn); 283 free(sn); 284 #if defined(CONFIG_SUPPORT_USBPLUG) 285 } else { 286 char sn[9] = "Rockchip"; 287 288 g_dnl_set_serialnumber(sn); 289 #endif 290 } 291 } 292 293 rc = g_dnl_register("rkusb_ums_dnl"); 294 if (rc) { 295 pr_err("g_dnl_register failed"); 296 rc = CMD_RET_FAILURE; 297 goto cleanup_board; 298 } 299 300 /* Timeout unit: seconds */ 301 cable_ready_timeout = UMS_CABLE_READY_TIMEOUT; 302 303 if (!g_dnl_board_usb_cable_connected()) { 304 puts("Please connect USB cable.\n"); 305 306 while (!g_dnl_board_usb_cable_connected()) { 307 if (ctrlc()) { 308 puts("\rCTRL+C - Operation aborted.\n"); 309 rc = CMD_RET_SUCCESS; 310 goto cleanup_register; 311 } 312 if (!cable_ready_timeout) { 313 puts("\rUSB cable not detected.\nCommand exit.\n"); 314 rc = CMD_RET_SUCCESS; 315 goto cleanup_register; 316 } 317 318 printf("\rAuto exit in: %.2d s.", cable_ready_timeout); 319 mdelay(1000); 320 cable_ready_timeout--; 321 } 322 puts("\r\n"); 323 } 324 325 while (1) { 326 usb_gadget_handle_interrupts(controller_index); 327 328 rc = fsg_main_thread(NULL); 329 if (rc) { 330 if (rc == -ENODEV && rkusb_usb3_capable() && 331 !rkusb_force_usb2_enabled()) { 332 printf("wait for usb3 connect timeout\n"); 333 rkusb_force_to_usb2(true); 334 g_dnl_unregister(); 335 usb_gadget_release(controller_index); 336 rkusb_fini(); 337 goto re_enumerate; 338 } 339 340 /* Check I/O error */ 341 if (rc == -EIO) 342 printf("\rCheck USB cable connection\n"); 343 344 /* Check CTRL+C */ 345 if (rc == -EPIPE) 346 printf("\rCTRL+C - Operation aborted\n"); 347 348 rc = CMD_RET_SUCCESS; 349 goto cleanup_register; 350 } 351 352 if (rkusb_switch_usb3_enabled()) { 353 printf("rockusb switch to usb3\n"); 354 g_dnl_unregister(); 355 usb_gadget_release(controller_index); 356 rkusb_fini(); 357 goto re_enumerate; 358 } 359 } 360 361 cleanup_register: 362 g_dnl_unregister(); 363 cleanup_board: 364 usb_gadget_release(controller_index); 365 cleanup_rkusb: 366 rkusb_fini(); 367 368 return rc; 369 } 370 371 U_BOOT_CMD_ALWAYS(rockusb, 4, 1, do_rkusb, 372 "Use the rockusb Protocol", 373 "<USB_controller> <devtype> <dev[:part]> e.g. rockusb 0 mmc 0\n" 374 ); 375