1e90e674fSJoseph Chen /*
28c6654f1SJon Lin * (C) Copyright 2020-2023 Rockchip Electronics Co., Ltd.
3e90e674fSJoseph Chen *
4e90e674fSJoseph Chen * SPDX-License-Identifier: GPL-2.0+
5e90e674fSJoseph Chen */
6e90e674fSJoseph Chen
7e90e674fSJoseph Chen #include <common.h>
8e90e674fSJoseph Chen #include <debug_uart.h>
9e90e674fSJoseph Chen #include <malloc.h>
10e90e674fSJoseph Chen #include <mmc.h>
11e90e674fSJoseph Chen #include <stdlib.h>
1269ef04c1SYifeng Zhao #include <scsi.h>
13e90e674fSJoseph Chen
14e90e674fSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
15e90e674fSJoseph Chen
168c6654f1SJon Lin struct bootdev_list {
178c6654f1SJon Lin u32 if_type;
188c6654f1SJon Lin u8 devnum;
198c6654f1SJon Lin u8 iomux_routing;
208c6654f1SJon Lin };
218c6654f1SJon Lin
228c6654f1SJon Lin #if CONFIG_IS_ENABLED(ROCKCHIP_RK3588)
238c6654f1SJon Lin static const struct bootdev_list dev_list[] = {
248c6654f1SJon Lin {IF_TYPE_MMC, 0, 0},
258c6654f1SJon Lin {IF_TYPE_MTD, 0, 0}, /* BLK_MTD_NAND */
268c6654f1SJon Lin {IF_TYPE_MTD, 1, 0}, /* BLK_MTD_SPI_NAND FSPI M0 */
278c6654f1SJon Lin {IF_TYPE_MTD, 1, 1}, /* BLK_MTD_SPI_NAND FSPI M1 */
288c6654f1SJon Lin {IF_TYPE_MTD, 1, 2}, /* BLK_MTD_SPI_NAND FSPI M2 */
298c6654f1SJon Lin {IF_TYPE_MTD, 2, 0}, /* BLK_MTD_SPI_NOR FSPI M0 */
308c6654f1SJon Lin {IF_TYPE_MTD, 2, 1}, /* BLK_MTD_SPI_NOR FSPI M1 */
318c6654f1SJon Lin {IF_TYPE_MTD, 2, 2}, /* BLK_MTD_SPI_NOR FSPI M2 */
32b93bed43SYifeng Zhao };
33b93bed43SYifeng Zhao #elif CONFIG_IS_ENABLED(ROCKCHIP_RK3576)
34b93bed43SYifeng Zhao static const struct bootdev_list dev_list[] = {
3569ef04c1SYifeng Zhao {IF_TYPE_SCSI, 0, 0},
36b93bed43SYifeng Zhao {IF_TYPE_MMC, 0, 0},
37b93bed43SYifeng Zhao {IF_TYPE_MTD, 1, 0}, /* BLK_MTD_SPI_NAND FSPI0 M0 */
38b93bed43SYifeng Zhao {IF_TYPE_MTD, 1, 1}, /* BLK_MTD_SPI_NAND FSPI1 M0 */
39b93bed43SYifeng Zhao {IF_TYPE_MTD, 1, 2}, /* BLK_MTD_SPI_NAND FSPI1 M1 */
40b93bed43SYifeng Zhao {IF_TYPE_MTD, 2, 0}, /* BLK_MTD_SPI_NOR FSPI0 M0 */
41b93bed43SYifeng Zhao {IF_TYPE_MTD, 2, 1}, /* BLK_MTD_SPI_NOR FSPI1 M0 */
42b93bed43SYifeng Zhao {IF_TYPE_MTD, 2, 2}, /* BLK_MTD_SPI_NOR FSPI1 M0 */
438c6654f1SJon Lin };
448c6654f1SJon Lin #else
458c6654f1SJon Lin static const struct bootdev_list dev_list[] = {
468c6654f1SJon Lin {IF_TYPE_MMC, 0, 0},
478c6654f1SJon Lin {IF_TYPE_MTD, 0, 0}, /* BLK_MTD_NAND */
488c6654f1SJon Lin {IF_TYPE_MTD, 1, 0}, /* BLK_MTD_SPI_NAND */
498c6654f1SJon Lin {IF_TYPE_MTD, 2, 0}, /* BLK_MTD_SPI_NOR */
508c6654f1SJon Lin {IF_TYPE_RKNAND, 0, 0},
518c6654f1SJon Lin };
528c6654f1SJon Lin #endif
538c6654f1SJon Lin
5470990948SYifeng Zhao static struct blk_desc *boot_blk_desc;
rockchip_get_bootdev(void)5570990948SYifeng Zhao struct blk_desc *rockchip_get_bootdev(void)
5670990948SYifeng Zhao {
5770990948SYifeng Zhao return boot_blk_desc;
5870990948SYifeng Zhao }
5970990948SYifeng Zhao
board_set_iomux(enum if_type if_type,int devnum,int routing)608c6654f1SJon Lin __weak void board_set_iomux(enum if_type if_type, int devnum, int routing)
6170990948SYifeng Zhao {
628c6654f1SJon Lin }
638c6654f1SJon Lin
board_unset_iomux(enum if_type if_type,int devnum,int routing)64*fea881d8SJon Lin __weak void board_unset_iomux(enum if_type if_type, int devnum, int routing)
65*fea881d8SJon Lin {
66*fea881d8SJon Lin }
67*fea881d8SJon Lin
usbplug_blk_get_devnum_by_type(enum if_type if_type,int devnum)688c6654f1SJon Lin struct blk_desc *usbplug_blk_get_devnum_by_type(enum if_type if_type, int devnum)
698c6654f1SJon Lin {
708c6654f1SJon Lin struct blk_desc *blk_desc = NULL;
718c6654f1SJon Lin u8 iomux_routing;
728c6654f1SJon Lin int i = 0;
738c6654f1SJon Lin
748c6654f1SJon Lin for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
758c6654f1SJon Lin if (if_type != dev_list[i].if_type || devnum != dev_list[i].devnum)
768c6654f1SJon Lin continue;
778c6654f1SJon Lin iomux_routing = dev_list[i].iomux_routing;
788c6654f1SJon Lin switch (if_type) {
798c6654f1SJon Lin #ifdef CONFIG_MMC
808c6654f1SJon Lin case IF_TYPE_MMC:
818c6654f1SJon Lin board_set_iomux(if_type, devnum, iomux_routing);
828c6654f1SJon Lin mmc_initialize(gd->bd);
838c6654f1SJon Lin break;
848c6654f1SJon Lin #endif
858c6654f1SJon Lin case IF_TYPE_MTD:
868c6654f1SJon Lin board_set_iomux(if_type, devnum, iomux_routing);
878c6654f1SJon Lin break;
8869ef04c1SYifeng Zhao #if defined(CONFIG_SCSI) && defined(CONFIG_CMD_SCSI) && (defined(CONFIG_AHCI) || defined(CONFIG_UFS))
8969ef04c1SYifeng Zhao case IF_TYPE_SCSI:
9069ef04c1SYifeng Zhao scsi_scan(true);
9169ef04c1SYifeng Zhao break;
9269ef04c1SYifeng Zhao #endif
938c6654f1SJon Lin default:
948c6654f1SJon Lin printf("Bootdev 0x%x is not support\n", if_type);
958c6654f1SJon Lin return NULL;
968c6654f1SJon Lin }
978c6654f1SJon Lin
988c6654f1SJon Lin printf("scandev: %s %d m%d\n", blk_get_if_type_name(if_type), devnum, iomux_routing);
998c6654f1SJon Lin blk_desc = blk_get_devnum_by_type(if_type, devnum);
1008c6654f1SJon Lin if (blk_desc)
1018c6654f1SJon Lin break;
102*fea881d8SJon Lin
103*fea881d8SJon Lin board_unset_iomux(if_type, devnum, iomux_routing);
1048c6654f1SJon Lin }
1058c6654f1SJon Lin
10670990948SYifeng Zhao boot_blk_desc = blk_desc;
10770990948SYifeng Zhao
1088c6654f1SJon Lin return blk_desc;
10970990948SYifeng Zhao }
11070990948SYifeng Zhao
bootdev_rockusb_cmd(void)111e90e674fSJoseph Chen static char *bootdev_rockusb_cmd(void)
112e90e674fSJoseph Chen {
1138c6654f1SJon Lin struct blk_desc *blk_desc = NULL;
1148c6654f1SJon Lin u32 if_type = IF_TYPE_UNKNOWN;
1158c6654f1SJon Lin u8 devnum, iomux_routing;
116e90e674fSJoseph Chen char *cmd;
117e90e674fSJoseph Chen int i = 0;
118e90e674fSJoseph Chen
1198c6654f1SJon Lin for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
1208c6654f1SJon Lin if_type = dev_list[i].if_type;
1218c6654f1SJon Lin devnum = dev_list[i].devnum;
1228c6654f1SJon Lin iomux_routing = dev_list[i].iomux_routing;
1238c6654f1SJon Lin switch (if_type) {
1248c6654f1SJon Lin #ifdef CONFIG_MMC
1258c6654f1SJon Lin case IF_TYPE_MMC:
1268c6654f1SJon Lin board_set_iomux(if_type, devnum, iomux_routing);
127e90e674fSJoseph Chen mmc_initialize(gd->bd);
1288c6654f1SJon Lin break;
1298c6654f1SJon Lin #endif
1308c6654f1SJon Lin case IF_TYPE_MTD:
1318c6654f1SJon Lin board_set_iomux(if_type, devnum, iomux_routing);
1328c6654f1SJon Lin break;
13369ef04c1SYifeng Zhao #if defined(CONFIG_SCSI) && defined(CONFIG_CMD_SCSI) && (defined(CONFIG_AHCI) || defined(CONFIG_UFS))
13469ef04c1SYifeng Zhao case IF_TYPE_SCSI:
13569ef04c1SYifeng Zhao scsi_scan(true);
13669ef04c1SYifeng Zhao break;
13769ef04c1SYifeng Zhao #endif
1388c6654f1SJon Lin default:
1398c6654f1SJon Lin printf("Bootdev 0x%x is not support\n", if_type);
1408c6654f1SJon Lin return NULL;
14170990948SYifeng Zhao }
142e90e674fSJoseph Chen
1438c6654f1SJon Lin printf("Scandev: %s %d m%d\n", blk_get_if_type_name(if_type), devnum, iomux_routing);
1448c6654f1SJon Lin blk_desc = blk_get_devnum_by_type(if_type, devnum);
14570990948SYifeng Zhao if (blk_desc)
146e90e674fSJoseph Chen break;
147*fea881d8SJon Lin
148*fea881d8SJon Lin board_unset_iomux(if_type, devnum, iomux_routing);
149e90e674fSJoseph Chen }
150e90e674fSJoseph Chen
1518c6654f1SJon Lin boot_blk_desc = blk_desc;
15270990948SYifeng Zhao
1538c6654f1SJon Lin if (!if_type) {
154e90e674fSJoseph Chen printf("No boot device\n");
155e90e674fSJoseph Chen return NULL;
156e90e674fSJoseph Chen }
157e90e674fSJoseph Chen
1588c6654f1SJon Lin printf("Bootdev: %s %d\n", blk_get_if_type_name(if_type), devnum);
159e90e674fSJoseph Chen
160e90e674fSJoseph Chen cmd = malloc(32);
161e90e674fSJoseph Chen if (!cmd)
162e90e674fSJoseph Chen return NULL;
163e90e674fSJoseph Chen
1648c6654f1SJon Lin snprintf(cmd, 32, "rockusb 0 %s %d", blk_get_if_type_name(if_type), devnum);
165e90e674fSJoseph Chen
166e90e674fSJoseph Chen return cmd;
167e90e674fSJoseph Chen }
168e90e674fSJoseph Chen
board_init(void)169e90e674fSJoseph Chen int board_init(void)
170e90e674fSJoseph Chen {
171e90e674fSJoseph Chen return run_command(bootdev_rockusb_cmd(), 0);
172e90e674fSJoseph Chen }
173e90e674fSJoseph Chen
174