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