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 block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; 20 21 static unsigned long sata_bread(block_dev_desc_t *block_dev, lbaint_t start, 22 lbaint_t blkcnt, void *dst) 23 { 24 return sata_read(block_dev->dev, start, blkcnt, dst); 25 } 26 27 static unsigned long sata_bwrite(block_dev_desc_t *block_dev, lbaint_t start, 28 lbaint_t blkcnt, const void *buffer) 29 { 30 return sata_write(block_dev->dev, 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 block_dev_desc)); 40 sata_dev_desc[i].if_type = IF_TYPE_SATA; 41 sata_dev_desc[i].dev = 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 init_part(&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 block_dev_desc_t *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 putc('\n'); 111 for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { 112 if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) 113 continue; 114 printf ("SATA device %d: ", i); 115 dev_print(&sata_dev_desc[i]); 116 } 117 return 0; 118 } else if (strncmp(argv[1],"dev", 3) == 0) { 119 if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) { 120 puts("\nno SATA devices available\n"); 121 return 1; 122 } 123 printf("\nSATA device %d: ", sata_curr_device); 124 dev_print(&sata_dev_desc[sata_curr_device]); 125 return 0; 126 } else if (strncmp(argv[1],"part",4) == 0) { 127 int dev, ok; 128 129 for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { 130 if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { 131 ++ok; 132 if (dev) 133 putc ('\n'); 134 print_part(&sata_dev_desc[dev]); 135 } 136 } 137 if (!ok) { 138 puts("\nno SATA devices available\n"); 139 rc ++; 140 } 141 return rc; 142 } 143 return CMD_RET_USAGE; 144 case 3: 145 if (strncmp(argv[1], "dev", 3) == 0) { 146 int dev = (int)simple_strtoul(argv[2], NULL, 10); 147 148 printf("\nSATA device %d: ", dev); 149 if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) { 150 puts ("unknown device\n"); 151 return 1; 152 } 153 dev_print(&sata_dev_desc[dev]); 154 155 if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) 156 return 1; 157 158 sata_curr_device = dev; 159 160 puts("... is now current device\n"); 161 162 return 0; 163 } else if (strncmp(argv[1], "part", 4) == 0) { 164 int dev = (int)simple_strtoul(argv[2], NULL, 10); 165 166 if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { 167 print_part(&sata_dev_desc[dev]); 168 } else { 169 printf("\nSATA device %d not available\n", dev); 170 rc = 1; 171 } 172 return rc; 173 } 174 return CMD_RET_USAGE; 175 176 default: /* at least 4 args */ 177 if (strcmp(argv[1], "read") == 0) { 178 ulong addr = simple_strtoul(argv[2], NULL, 16); 179 ulong cnt = simple_strtoul(argv[4], NULL, 16); 180 ulong n; 181 lbaint_t blk = simple_strtoul(argv[3], NULL, 16); 182 183 printf("\nSATA read: device %d block # %ld, count %ld ... ", 184 sata_curr_device, blk, cnt); 185 186 n = sata_read(sata_curr_device, blk, cnt, (u32 *)addr); 187 188 /* flush cache after read */ 189 flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz); 190 191 printf("%ld blocks read: %s\n", 192 n, (n==cnt) ? "OK" : "ERROR"); 193 return (n == cnt) ? 0 : 1; 194 } else if (strcmp(argv[1], "write") == 0) { 195 ulong addr = simple_strtoul(argv[2], NULL, 16); 196 ulong cnt = simple_strtoul(argv[4], NULL, 16); 197 ulong n; 198 199 lbaint_t blk = simple_strtoul(argv[3], NULL, 16); 200 201 printf("\nSATA write: device %d block # %ld, count %ld ... ", 202 sata_curr_device, blk, cnt); 203 204 n = sata_write(sata_curr_device, blk, cnt, (u32 *)addr); 205 206 printf("%ld blocks written: %s\n", 207 n, (n == cnt) ? "OK" : "ERROR"); 208 return (n == cnt) ? 0 : 1; 209 } else { 210 return CMD_RET_USAGE; 211 } 212 213 return rc; 214 } 215 } 216 217 U_BOOT_CMD( 218 sata, 5, 1, do_sata, 219 "SATA sub system", 220 "init - init SATA sub system\n" 221 "sata stop - disable SATA sub system\n" 222 "sata info - show available SATA devices\n" 223 "sata device [dev] - show or set current device\n" 224 "sata part [dev] - print partition table\n" 225 "sata read addr blk# cnt\n" 226 "sata write addr blk# cnt" 227 ); 228