xref: /rk3399_rockchip-uboot/cmd/sata.c (revision c649e3c91cdc96a86ca2665fcfafaca5c4b384b1)
1 /*
2  * Copyright (C) 2000-2005, DENX Software Engineering
3  *		Wolfgang Denk <wd@denx.de>
4  * Copyright (C) Procsys. All rights reserved.
5  *		Mushtaq Khan <mushtaq_k@procsys.com>
6  *			<mushtaqk_921@yahoo.co.in>
7  * Copyright (C) 2008 Freescale Semiconductor, Inc.
8  *		Dave Liu <daveliu@freescale.com>
9  *
10  * SPDX-License-Identifier:	GPL-2.0+
11  */
12 
13 #include <common.h>
14 #include <command.h>
15 #include <part.h>
16 #include <sata.h>
17 
18 static int sata_curr_device = -1;
19 struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
20 
21 static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start,
22 				lbaint_t blkcnt, void *dst)
23 {
24 	return sata_read(block_dev->devnum, start, blkcnt, dst);
25 }
26 
27 static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
28 				 lbaint_t blkcnt, const void *buffer)
29 {
30 	return sata_write(block_dev->devnum, start, blkcnt, buffer);
31 }
32 
33 int __sata_initialize(void)
34 {
35 	int rc;
36 	int i;
37 
38 	for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {
39 		memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc));
40 		sata_dev_desc[i].if_type = IF_TYPE_SATA;
41 		sata_dev_desc[i].devnum = i;
42 		sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
43 		sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
44 		sata_dev_desc[i].lba = 0;
45 		sata_dev_desc[i].blksz = 512;
46 		sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
47 		sata_dev_desc[i].block_read = sata_bread;
48 		sata_dev_desc[i].block_write = sata_bwrite;
49 
50 		rc = init_sata(i);
51 		if (!rc) {
52 			rc = scan_sata(i);
53 			if (!rc && (sata_dev_desc[i].lba > 0) &&
54 				(sata_dev_desc[i].blksz > 0))
55 				part_init(&sata_dev_desc[i]);
56 		}
57 	}
58 	sata_curr_device = 0;
59 	return rc;
60 }
61 int sata_initialize(void) __attribute__((weak,alias("__sata_initialize")));
62 
63 __weak int __sata_stop(void)
64 {
65 	int i, err = 0;
66 
67 	for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
68 		err |= reset_sata(i);
69 
70 	if (err)
71 		printf("Could not reset some SATA devices\n");
72 
73 	return err;
74 }
75 int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
76 
77 #ifdef CONFIG_PARTITIONS
78 struct blk_desc *sata_get_dev(int dev)
79 {
80 	return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
81 }
82 #endif
83 
84 static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
85 {
86 	int rc = 0;
87 
88 	if (argc == 2 && strcmp(argv[1], "stop") == 0)
89 		return sata_stop();
90 
91 	if (argc == 2 && strcmp(argv[1], "init") == 0) {
92 		if (sata_curr_device != -1)
93 			sata_stop();
94 
95 		return sata_initialize();
96 	}
97 
98 	/* If the user has not yet run `sata init`, do it now */
99 	if (sata_curr_device == -1)
100 		if (sata_initialize())
101 			return 1;
102 
103 	switch (argc) {
104 	case 0:
105 	case 1:
106 		return CMD_RET_USAGE;
107 	case 2:
108 		if (strncmp(argv[1], "inf", 3) == 0) {
109 			int i;
110 
111 			putc('\n');
112 			for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) {
113 				if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN)
114 					continue;
115 				printf("SATA device %d: ", i);
116 				dev_print(&sata_dev_desc[i]);
117 			}
118 			return 0;
119 		} else if (strncmp(argv[1], "dev", 3) == 0) {
120 			if (sata_curr_device < 0 ||
121 			    sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) {
122 				puts("\nno SATA devices available\n");
123 				return 1;
124 			}
125 			printf("\nSATA device %d: ", sata_curr_device);
126 			dev_print(&sata_dev_desc[sata_curr_device]);
127 			return 0;
128 		} else if (strncmp(argv[1], "part", 4) == 0) {
129 			int dev, ok;
130 
131 			for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) {
132 				if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
133 					++ok;
134 					if (dev)
135 						putc ('\n');
136 					part_print(&sata_dev_desc[dev]);
137 				}
138 			}
139 			if (!ok) {
140 				puts("\nno SATA devices available\n");
141 				rc ++;
142 			}
143 			return rc;
144 		}
145 		return CMD_RET_USAGE;
146 	case 3:
147 		if (strncmp(argv[1], "dev", 3) == 0) {
148 			int dev = (int)simple_strtoul(argv[2], NULL, 10);
149 
150 			printf("\nSATA device %d: ", dev);
151 			if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
152 				puts ("unknown device\n");
153 				return 1;
154 			}
155 			dev_print(&sata_dev_desc[dev]);
156 
157 			if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN)
158 				return 1;
159 
160 			sata_curr_device = dev;
161 
162 			puts("... is now current device\n");
163 
164 			return 0;
165 		} else if (strncmp(argv[1], "part", 4) == 0) {
166 			int dev = (int)simple_strtoul(argv[2], NULL, 10);
167 
168 			if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) {
169 				part_print(&sata_dev_desc[dev]);
170 			} else {
171 				printf("\nSATA device %d not available\n", dev);
172 				rc = 1;
173 			}
174 			return rc;
175 		}
176 		return CMD_RET_USAGE;
177 
178 	default: /* at least 4 args */
179 		if (strcmp(argv[1], "read") == 0) {
180 			ulong addr = simple_strtoul(argv[2], NULL, 16);
181 			ulong cnt = simple_strtoul(argv[4], NULL, 16);
182 			ulong n;
183 			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
184 
185 			printf("\nSATA read: device %d block # %ld, count %ld ... ",
186 				sata_curr_device, blk, cnt);
187 
188 			n = blk_dread(&sata_dev_desc[sata_curr_device],
189 				      blk, cnt, (u32 *)addr);
190 
191 			/* flush cache after read */
192 			flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz);
193 
194 			printf("%ld blocks read: %s\n",
195 				n, (n==cnt) ? "OK" : "ERROR");
196 			return (n == cnt) ? 0 : 1;
197 		} else if (strcmp(argv[1], "write") == 0) {
198 			ulong addr = simple_strtoul(argv[2], NULL, 16);
199 			ulong cnt = simple_strtoul(argv[4], NULL, 16);
200 			ulong n;
201 
202 			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
203 
204 			printf("\nSATA write: device %d block # %ld, count %ld ... ",
205 				sata_curr_device, blk, cnt);
206 
207 			n = blk_dwrite(&sata_dev_desc[sata_curr_device],
208 				       blk, cnt, (u32 *)addr);
209 
210 			printf("%ld blocks written: %s\n",
211 				n, (n == cnt) ? "OK" : "ERROR");
212 			return (n == cnt) ? 0 : 1;
213 		} else {
214 			return CMD_RET_USAGE;
215 		}
216 
217 		return rc;
218 	}
219 }
220 
221 U_BOOT_CMD(
222 	sata, 5, 1, do_sata,
223 	"SATA sub system",
224 	"init - init SATA sub system\n"
225 	"sata stop - disable SATA sub system\n"
226 	"sata info - show available SATA devices\n"
227 	"sata device [dev] - show or set current device\n"
228 	"sata part [dev] - print partition table\n"
229 	"sata read addr blk# cnt\n"
230 	"sata write addr blk# cnt"
231 );
232