183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22e192b24SSimon Glass /*
32e192b24SSimon Glass * Copyright (C) 2000-2005, DENX Software Engineering
42e192b24SSimon Glass * Wolfgang Denk <wd@denx.de>
52e192b24SSimon Glass * Copyright (C) Procsys. All rights reserved.
62e192b24SSimon Glass * Mushtaq Khan <mushtaq_k@procsys.com>
72e192b24SSimon Glass * <mushtaqk_921@yahoo.co.in>
82e192b24SSimon Glass * Copyright (C) 2008 Freescale Semiconductor, Inc.
92e192b24SSimon Glass * Dave Liu <daveliu@freescale.com>
102e192b24SSimon Glass */
112e192b24SSimon Glass
122e192b24SSimon Glass #include <common.h>
13f19f1ecbSSimon Glass #include <ahci.h>
14f19f1ecbSSimon Glass #include <dm.h>
152e192b24SSimon Glass #include <command.h>
162e192b24SSimon Glass #include <part.h>
172e192b24SSimon Glass #include <sata.h>
18f19f1ecbSSimon Glass #include <dm/device-internal.h>
19f19f1ecbSSimon Glass #include <dm/uclass-internal.h>
202e192b24SSimon Glass
212e192b24SSimon Glass static int sata_curr_device = -1;
222e192b24SSimon Glass
sata_remove(int devnum)23f19f1ecbSSimon Glass int sata_remove(int devnum)
24f19f1ecbSSimon Glass {
25f19f1ecbSSimon Glass #ifdef CONFIG_AHCI
26f19f1ecbSSimon Glass struct udevice *dev;
27f19f1ecbSSimon Glass int rc;
28f19f1ecbSSimon Glass
29f19f1ecbSSimon Glass rc = uclass_find_device(UCLASS_AHCI, devnum, &dev);
30f19f1ecbSSimon Glass if (!rc && !dev)
31f19f1ecbSSimon Glass rc = uclass_find_first_device(UCLASS_AHCI, &dev);
32f19f1ecbSSimon Glass if (rc || !dev) {
33f19f1ecbSSimon Glass printf("Cannot find SATA device %d (err=%d)\n", devnum, rc);
34f19f1ecbSSimon Glass return CMD_RET_FAILURE;
35f19f1ecbSSimon Glass }
36f19f1ecbSSimon Glass
37f19f1ecbSSimon Glass rc = device_remove(dev, DM_REMOVE_NORMAL);
38f19f1ecbSSimon Glass if (rc) {
39f19f1ecbSSimon Glass printf("Cannot remove SATA device '%s' (err=%d)\n", dev->name,
40f19f1ecbSSimon Glass rc);
41f19f1ecbSSimon Glass return CMD_RET_FAILURE;
42f19f1ecbSSimon Glass }
43f19f1ecbSSimon Glass
44f19f1ecbSSimon Glass return 0;
45f19f1ecbSSimon Glass #else
46f19f1ecbSSimon Glass return sata_stop();
47f19f1ecbSSimon Glass #endif
48f19f1ecbSSimon Glass }
49f19f1ecbSSimon Glass
sata_probe(int devnum)50f19f1ecbSSimon Glass int sata_probe(int devnum)
51f19f1ecbSSimon Glass {
52f19f1ecbSSimon Glass #ifdef CONFIG_AHCI
53f19f1ecbSSimon Glass struct udevice *dev;
54f19f1ecbSSimon Glass int rc;
55f19f1ecbSSimon Glass
56f19f1ecbSSimon Glass rc = uclass_get_device(UCLASS_AHCI, devnum, &dev);
57f19f1ecbSSimon Glass if (rc)
58f19f1ecbSSimon Glass rc = uclass_find_first_device(UCLASS_AHCI, &dev);
59f19f1ecbSSimon Glass if (rc) {
60f19f1ecbSSimon Glass printf("Cannot probe SATA device %d (err=%d)\n", devnum, rc);
61f19f1ecbSSimon Glass return CMD_RET_FAILURE;
62f19f1ecbSSimon Glass }
63*b3860bfeSMarcel Ziswiler if (!dev) {
64*b3860bfeSMarcel Ziswiler printf("No SATA device found!\n");
65*b3860bfeSMarcel Ziswiler return CMD_RET_FAILURE;
66*b3860bfeSMarcel Ziswiler }
67f19f1ecbSSimon Glass rc = sata_scan(dev);
68f19f1ecbSSimon Glass if (rc) {
69f19f1ecbSSimon Glass printf("Cannot scan SATA device %d (err=%d)\n", devnum, rc);
70f19f1ecbSSimon Glass return CMD_RET_FAILURE;
71f19f1ecbSSimon Glass }
72f19f1ecbSSimon Glass
73f19f1ecbSSimon Glass return 0;
74f19f1ecbSSimon Glass #else
75f19f1ecbSSimon Glass return sata_initialize() < 0 ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
76f19f1ecbSSimon Glass #endif
77f19f1ecbSSimon Glass }
78f19f1ecbSSimon Glass
do_sata(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])792e192b24SSimon Glass static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
802e192b24SSimon Glass {
812e192b24SSimon Glass int rc = 0;
822e192b24SSimon Glass
83f19f1ecbSSimon Glass if (argc >= 2) {
84f19f1ecbSSimon Glass int devnum = 0;
852e192b24SSimon Glass
86f19f1ecbSSimon Glass if (argc == 3)
87f19f1ecbSSimon Glass devnum = (int)simple_strtoul(argv[2], NULL, 10);
88f19f1ecbSSimon Glass if (!strcmp(argv[1], "stop"))
89f19f1ecbSSimon Glass return sata_remove(devnum);
902e192b24SSimon Glass
91f19f1ecbSSimon Glass if (!strcmp(argv[1], "init")) {
92f19f1ecbSSimon Glass if (sata_curr_device != -1) {
93f19f1ecbSSimon Glass rc = sata_remove(devnum);
94f19f1ecbSSimon Glass if (rc)
95f19f1ecbSSimon Glass return rc;
96f19f1ecbSSimon Glass }
97f19f1ecbSSimon Glass
98f19f1ecbSSimon Glass return sata_probe(devnum);
99f19f1ecbSSimon Glass }
1002e192b24SSimon Glass }
1012e192b24SSimon Glass
1022e192b24SSimon Glass /* If the user has not yet run `sata init`, do it now */
103aa6ab905STang Yuantian if (sata_curr_device == -1) {
104f19f1ecbSSimon Glass rc = sata_probe(0);
1057e83f1d5STroy Kisky if (rc)
1067e83f1d5STroy Kisky return rc;
107f19f1ecbSSimon Glass sata_curr_device = 0;
108aa6ab905STang Yuantian }
1092e192b24SSimon Glass
110e29e71e9SSimon Glass return blk_common_cmd(argc, argv, IF_TYPE_SATA, &sata_curr_device);
1112e192b24SSimon Glass }
1122e192b24SSimon Glass
1132e192b24SSimon Glass U_BOOT_CMD(
1142e192b24SSimon Glass sata, 5, 1, do_sata,
1152e192b24SSimon Glass "SATA sub system",
1162e192b24SSimon Glass "init - init SATA sub system\n"
117f19f1ecbSSimon Glass "sata stop [dev] - disable SATA sub system or device\n"
1182e192b24SSimon Glass "sata info - show available SATA devices\n"
1192e192b24SSimon Glass "sata device [dev] - show or set current device\n"
1202e192b24SSimon Glass "sata part [dev] - print partition table\n"
1212e192b24SSimon Glass "sata read addr blk# cnt\n"
1222e192b24SSimon Glass "sata write addr blk# cnt"
1232e192b24SSimon Glass );
124