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