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