1*65f6f07bSMike Frysinger /* 2*65f6f07bSMike Frysinger * atmel_df_pow2.c - convert Atmel Dataflashes to Power of 2 mode 3*65f6f07bSMike Frysinger * 4*65f6f07bSMike Frysinger * Copyright 2009 Analog Devices Inc. 5*65f6f07bSMike Frysinger * 6*65f6f07bSMike Frysinger * Licensed under the 2-clause BSD. 7*65f6f07bSMike Frysinger */ 8*65f6f07bSMike Frysinger 9*65f6f07bSMike Frysinger #include <common.h> 10*65f6f07bSMike Frysinger #include <exports.h> 11*65f6f07bSMike Frysinger 12*65f6f07bSMike Frysinger #define CMD_ID 0x9f 13*65f6f07bSMike Frysinger #define CMD_STAT 0xd7 14*65f6f07bSMike Frysinger #define CMD_CFG 0x3d 15*65f6f07bSMike Frysinger 16*65f6f07bSMike Frysinger static int flash_cmd(struct spi_slave *slave, uchar cmd, uchar *buf, int len) 17*65f6f07bSMike Frysinger { 18*65f6f07bSMike Frysinger buf[0] = cmd; 19*65f6f07bSMike Frysinger return spi_xfer(slave, 8 * len, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END); 20*65f6f07bSMike Frysinger } 21*65f6f07bSMike Frysinger 22*65f6f07bSMike Frysinger static int flash_status(struct spi_slave *slave) 23*65f6f07bSMike Frysinger { 24*65f6f07bSMike Frysinger uchar buf[2]; 25*65f6f07bSMike Frysinger if (flash_cmd(slave, CMD_STAT, buf, sizeof(buf))) 26*65f6f07bSMike Frysinger return -1; 27*65f6f07bSMike Frysinger return buf[1]; 28*65f6f07bSMike Frysinger } 29*65f6f07bSMike Frysinger 30*65f6f07bSMike Frysinger static int flash_set_pow2(struct spi_slave *slave) 31*65f6f07bSMike Frysinger { 32*65f6f07bSMike Frysinger int ret; 33*65f6f07bSMike Frysinger uchar buf[4]; 34*65f6f07bSMike Frysinger 35*65f6f07bSMike Frysinger buf[1] = 0x2a; 36*65f6f07bSMike Frysinger buf[2] = 0x80; 37*65f6f07bSMike Frysinger buf[3] = 0xa6; 38*65f6f07bSMike Frysinger 39*65f6f07bSMike Frysinger ret = flash_cmd(slave, CMD_CFG, buf, sizeof(buf)); 40*65f6f07bSMike Frysinger if (ret) 41*65f6f07bSMike Frysinger return ret; 42*65f6f07bSMike Frysinger 43*65f6f07bSMike Frysinger /* wait Tp, or 6 msec */ 44*65f6f07bSMike Frysinger udelay(6000); 45*65f6f07bSMike Frysinger 46*65f6f07bSMike Frysinger ret = flash_status(slave); 47*65f6f07bSMike Frysinger if (ret == -1) 48*65f6f07bSMike Frysinger return 1; 49*65f6f07bSMike Frysinger 50*65f6f07bSMike Frysinger return ret & 0x1 ? 0 : 1; 51*65f6f07bSMike Frysinger } 52*65f6f07bSMike Frysinger 53*65f6f07bSMike Frysinger static int flash_check(struct spi_slave *slave) 54*65f6f07bSMike Frysinger { 55*65f6f07bSMike Frysinger int ret; 56*65f6f07bSMike Frysinger uchar buf[4]; 57*65f6f07bSMike Frysinger 58*65f6f07bSMike Frysinger ret = flash_cmd(slave, CMD_ID, buf, sizeof(buf)); 59*65f6f07bSMike Frysinger if (ret) 60*65f6f07bSMike Frysinger return ret; 61*65f6f07bSMike Frysinger 62*65f6f07bSMike Frysinger if (buf[1] != 0x1F) { 63*65f6f07bSMike Frysinger printf("atmel flash not found (id[0] = %#x)\n", buf[1]); 64*65f6f07bSMike Frysinger return 1; 65*65f6f07bSMike Frysinger } 66*65f6f07bSMike Frysinger 67*65f6f07bSMike Frysinger if ((buf[2] >> 5) != 0x1) { 68*65f6f07bSMike Frysinger printf("AT45 flash not found (id[0] = %#x)\n", buf[2]); 69*65f6f07bSMike Frysinger return 2; 70*65f6f07bSMike Frysinger } 71*65f6f07bSMike Frysinger 72*65f6f07bSMike Frysinger return 0; 73*65f6f07bSMike Frysinger } 74*65f6f07bSMike Frysinger 75*65f6f07bSMike Frysinger static char *getline(void) 76*65f6f07bSMike Frysinger { 77*65f6f07bSMike Frysinger static char buffer[100]; 78*65f6f07bSMike Frysinger char c; 79*65f6f07bSMike Frysinger size_t i; 80*65f6f07bSMike Frysinger 81*65f6f07bSMike Frysinger i = 0; 82*65f6f07bSMike Frysinger while (1) { 83*65f6f07bSMike Frysinger buffer[i] = '\0'; 84*65f6f07bSMike Frysinger 85*65f6f07bSMike Frysinger c = getc(); 86*65f6f07bSMike Frysinger 87*65f6f07bSMike Frysinger switch (c) { 88*65f6f07bSMike Frysinger case '\r': /* Enter/Return key */ 89*65f6f07bSMike Frysinger case '\n': 90*65f6f07bSMike Frysinger puts("\n"); 91*65f6f07bSMike Frysinger return buffer; 92*65f6f07bSMike Frysinger 93*65f6f07bSMike Frysinger case 0x03: /* ^C - break */ 94*65f6f07bSMike Frysinger return NULL; 95*65f6f07bSMike Frysinger 96*65f6f07bSMike Frysinger case 0x5F: 97*65f6f07bSMike Frysinger case 0x08: /* ^H - backspace */ 98*65f6f07bSMike Frysinger case 0x7F: /* DEL - backspace */ 99*65f6f07bSMike Frysinger if (i) { 100*65f6f07bSMike Frysinger puts("\b \b"); 101*65f6f07bSMike Frysinger i--; 102*65f6f07bSMike Frysinger } 103*65f6f07bSMike Frysinger break; 104*65f6f07bSMike Frysinger 105*65f6f07bSMike Frysinger default: 106*65f6f07bSMike Frysinger /* Ignore control characters */ 107*65f6f07bSMike Frysinger if (c < 0x20) 108*65f6f07bSMike Frysinger break; 109*65f6f07bSMike Frysinger /* Queue up all other characters */ 110*65f6f07bSMike Frysinger buffer[i++] = c; 111*65f6f07bSMike Frysinger printf("%c", c); 112*65f6f07bSMike Frysinger break; 113*65f6f07bSMike Frysinger } 114*65f6f07bSMike Frysinger } 115*65f6f07bSMike Frysinger } 116*65f6f07bSMike Frysinger 117*65f6f07bSMike Frysinger int atmel_df_pow2(int argc, char *argv[]) 118*65f6f07bSMike Frysinger { 119*65f6f07bSMike Frysinger /* Print the ABI version */ 120*65f6f07bSMike Frysinger app_startup(argv); 121*65f6f07bSMike Frysinger if (XF_VERSION != get_version()) { 122*65f6f07bSMike Frysinger printf("Expects ABI version %d\n", XF_VERSION); 123*65f6f07bSMike Frysinger printf("Actual U-Boot ABI version %lu\n", get_version()); 124*65f6f07bSMike Frysinger printf("Can't run\n\n"); 125*65f6f07bSMike Frysinger return 1; 126*65f6f07bSMike Frysinger } 127*65f6f07bSMike Frysinger 128*65f6f07bSMike Frysinger spi_init(); 129*65f6f07bSMike Frysinger 130*65f6f07bSMike Frysinger while (1) { 131*65f6f07bSMike Frysinger struct spi_slave *slave; 132*65f6f07bSMike Frysinger char *line, *p; 133*65f6f07bSMike Frysinger int bus, cs, status; 134*65f6f07bSMike Frysinger 135*65f6f07bSMike Frysinger puts("\nenter the [BUS:]CS of the SPI flash: "); 136*65f6f07bSMike Frysinger line = getline(); 137*65f6f07bSMike Frysinger 138*65f6f07bSMike Frysinger /* CTRL+C */ 139*65f6f07bSMike Frysinger if (!line) 140*65f6f07bSMike Frysinger return 0; 141*65f6f07bSMike Frysinger if (line[0] == '\0') 142*65f6f07bSMike Frysinger continue; 143*65f6f07bSMike Frysinger 144*65f6f07bSMike Frysinger bus = cs = simple_strtoul(line, &p, 10); 145*65f6f07bSMike Frysinger if (*p) { 146*65f6f07bSMike Frysinger if (*p == ':') { 147*65f6f07bSMike Frysinger ++p; 148*65f6f07bSMike Frysinger cs = simple_strtoul(p, &p, 10); 149*65f6f07bSMike Frysinger } 150*65f6f07bSMike Frysinger if (*p) { 151*65f6f07bSMike Frysinger puts("invalid format, please try again\n"); 152*65f6f07bSMike Frysinger continue; 153*65f6f07bSMike Frysinger } 154*65f6f07bSMike Frysinger } else 155*65f6f07bSMike Frysinger bus = 0; 156*65f6f07bSMike Frysinger 157*65f6f07bSMike Frysinger printf("\ngoing to work with dataflash at %i:%i\n", bus, cs); 158*65f6f07bSMike Frysinger 159*65f6f07bSMike Frysinger /* use a low speed -- it'll work with all devices, and 160*65f6f07bSMike Frysinger * speed here doesn't really matter. 161*65f6f07bSMike Frysinger */ 162*65f6f07bSMike Frysinger slave = spi_setup_slave(bus, cs, 1000, SPI_MODE_3); 163*65f6f07bSMike Frysinger if (!slave) { 164*65f6f07bSMike Frysinger puts("unable to setup slave\n"); 165*65f6f07bSMike Frysinger continue; 166*65f6f07bSMike Frysinger } 167*65f6f07bSMike Frysinger 168*65f6f07bSMike Frysinger if (spi_claim_bus(slave)) { 169*65f6f07bSMike Frysinger spi_free_slave(slave); 170*65f6f07bSMike Frysinger continue; 171*65f6f07bSMike Frysinger } 172*65f6f07bSMike Frysinger 173*65f6f07bSMike Frysinger if (flash_check(slave)) { 174*65f6f07bSMike Frysinger puts("no flash found\n"); 175*65f6f07bSMike Frysinger goto done; 176*65f6f07bSMike Frysinger } 177*65f6f07bSMike Frysinger 178*65f6f07bSMike Frysinger status = flash_status(slave); 179*65f6f07bSMike Frysinger if (status == -1) { 180*65f6f07bSMike Frysinger puts("unable to read status register\n"); 181*65f6f07bSMike Frysinger goto done; 182*65f6f07bSMike Frysinger } 183*65f6f07bSMike Frysinger if (status & 0x1) { 184*65f6f07bSMike Frysinger puts("flash is already in power-of-2 mode!\n"); 185*65f6f07bSMike Frysinger goto done; 186*65f6f07bSMike Frysinger } 187*65f6f07bSMike Frysinger 188*65f6f07bSMike Frysinger puts("are you sure you wish to set power-of-2 mode?\n"); 189*65f6f07bSMike Frysinger puts("this operation is permanent and irreversible\n"); 190*65f6f07bSMike Frysinger printf("enter YES to continue: "); 191*65f6f07bSMike Frysinger line = getline(); 192*65f6f07bSMike Frysinger if (!line || strcmp(line, "YES")) 193*65f6f07bSMike Frysinger goto done; 194*65f6f07bSMike Frysinger 195*65f6f07bSMike Frysinger if (flash_set_pow2(slave)) { 196*65f6f07bSMike Frysinger puts("setting pow2 mode failed\n"); 197*65f6f07bSMike Frysinger goto done; 198*65f6f07bSMike Frysinger } 199*65f6f07bSMike Frysinger 200*65f6f07bSMike Frysinger puts( 201*65f6f07bSMike Frysinger "Configuration should be updated now. You will have to\n" 202*65f6f07bSMike Frysinger "power cycle the part in order to finish the conversion.\n" 203*65f6f07bSMike Frysinger ); 204*65f6f07bSMike Frysinger 205*65f6f07bSMike Frysinger done: 206*65f6f07bSMike Frysinger spi_release_bus(slave); 207*65f6f07bSMike Frysinger spi_free_slave(slave); 208*65f6f07bSMike Frysinger } 209*65f6f07bSMike Frysinger } 210