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