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        spi_init();
 130
 131        while (1) {
 132                struct spi_slave *slave;
 133                char *line, *p;
 134                int bus, cs, status;
 135
 136                puts("\nenter the [BUS:]CS of the SPI flash: ");
 137                line = getline();
 138
 139                /* CTRL+C */
 140                if (!line)
 141                        return 0;
 142                if (line[0] == '\0')
 143                        continue;
 144
 145                bus = cs = simple_strtoul(line, &p, 10);
 146                if (*p) {
 147                        if (*p == ':') {
 148                                ++p;
 149                                cs = simple_strtoul(p, &p, 10);
 150                        }
 151                        if (*p) {
 152                                puts("invalid format, please try again\n");
 153                                continue;
 154                        }
 155                } else
 156                        bus = 0;
 157
 158                printf("\ngoing to work with dataflash at %i:%i\n", bus, cs);
 159
 160                /* use a low speed -- it'll work with all devices, and
 161                 * speed here doesn't really matter.
 162                 */
 163                slave = spi_setup_slave(bus, cs, 1000, SPI_MODE_3);
 164                if (!slave) {
 165                        puts("unable to setup slave\n");
 166                        continue;
 167                }
 168
 169                if (spi_claim_bus(slave)) {
 170                        spi_free_slave(slave);
 171                        continue;
 172                }
 173
 174                if (flash_check(slave)) {
 175                        puts("no flash found\n");
 176                        goto done;
 177                }
 178
 179                status = flash_status(slave);
 180                if (status == -1) {
 181                        puts("unable to read status register\n");
 182                        goto done;
 183                }
 184                if (status & 0x1) {
 185                        puts("flash is already in power-of-2 mode!\n");
 186                        goto done;
 187                }
 188
 189                puts("are you sure you wish to set power-of-2 mode?\n");
 190                puts("this operation is permanent and irreversible\n");
 191                printf("enter YES to continue: ");
 192                line = getline();
 193                if (!line || strcmp(line, "YES"))
 194                        goto done;
 195
 196                if (flash_set_pow2(slave)) {
 197                        puts("setting pow2 mode failed\n");
 198                        goto done;
 199                }
 200
 201                puts(
 202                        "Configuration should be updated now.  You will have to\n"
 203                        "power cycle the part in order to finish the conversion.\n"
 204                );
 205
 206 done:
 207                spi_release_bus(slave);
 208                spi_free_slave(slave);
 209        }
 210}
 211