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#include <linux/delay.h>
  13
  14#define CMD_ID    0x9f
  15#define CMD_STAT  0xd7
  16#define CMD_CFG   0x3d
  17
  18static int flash_cmd(struct spi_slave *slave, uchar cmd, uchar *buf, int len)
  19{
  20        buf[0] = cmd;
  21        return spi_xfer(slave, 8 * len, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END);
  22}
  23
  24static int flash_status(struct spi_slave *slave)
  25{
  26        uchar buf[2];
  27        if (flash_cmd(slave, CMD_STAT, buf, sizeof(buf)))
  28                return -1;
  29        return buf[1];
  30}
  31
  32static int flash_set_pow2(struct spi_slave *slave)
  33{
  34        int ret;
  35        uchar buf[4];
  36
  37        buf[1] = 0x2a;
  38        buf[2] = 0x80;
  39        buf[3] = 0xa6;
  40
  41        ret = flash_cmd(slave, CMD_CFG, buf, sizeof(buf));
  42        if (ret)
  43                return ret;
  44
  45        /* wait Tp, or 6 msec */
  46        udelay(6000);
  47
  48        ret = flash_status(slave);
  49        if (ret == -1)
  50                return 1;
  51
  52        return ret & 0x1 ? 0 : 1;
  53}
  54
  55static int flash_check(struct spi_slave *slave)
  56{
  57        int ret;
  58        uchar buf[4];
  59
  60        ret = flash_cmd(slave, CMD_ID, buf, sizeof(buf));
  61        if (ret)
  62                return ret;
  63
  64        if (buf[1] != 0x1F) {
  65                printf("atmel flash not found (id[0] = %#x)\n", buf[1]);
  66                return 1;
  67        }
  68
  69        if ((buf[2] >> 5) != 0x1) {
  70                printf("AT45 flash not found (id[0] = %#x)\n", buf[2]);
  71                return 2;
  72        }
  73
  74        return 0;
  75}
  76
  77static char *getline(void)
  78{
  79        static char buffer[100];
  80        char c;
  81        size_t i;
  82
  83        i = 0;
  84        while (1) {
  85                buffer[i] = '\0';
  86
  87                c = getc();
  88
  89                switch (c) {
  90                case '\r':      /* Enter/Return key */
  91                case '\n':
  92                        puts("\n");
  93                        return buffer;
  94
  95                case 0x03:      /* ^C - break */
  96                        return NULL;
  97
  98                case 0x5F:
  99                case 0x08:      /* ^H  - backspace */
 100                case 0x7F:      /* DEL - backspace */
 101                        if (i) {
 102                                puts("\b \b");
 103                                i--;
 104                        }
 105                        break;
 106
 107                default:
 108                        /* Ignore control characters */
 109                        if (c < 0x20)
 110                                break;
 111                        /* Queue up all other characters */
 112                        buffer[i++] = c;
 113                        printf("%c", c);
 114                        break;
 115                }
 116        }
 117}
 118
 119int atmel_df_pow2(int argc, char *const argv[])
 120{
 121        /* Print the ABI version */
 122        app_startup(argv);
 123        if (XF_VERSION != get_version()) {
 124                printf("Expects ABI version %d\n", XF_VERSION);
 125                printf("Actual U-Boot ABI version %lu\n", get_version());
 126                printf("Can't run\n\n");
 127                return 1;
 128        }
 129
 130        while (1) {
 131                struct spi_slave *slave;
 132                char *line, *p;
 133                int bus, cs, status;
 134
 135                puts("\nenter the [BUS:]CS of the SPI flash: ");
 136                line = getline();
 137
 138                /* CTRL+C */
 139                if (!line)
 140                        return 0;
 141                if (line[0] == '\0')
 142                        continue;
 143
 144                bus = dectoul(line, &p);
 145                cs = bus;
 146                if (*p) {
 147                        if (*p == ':') {
 148                                ++p;
 149                                cs = dectoul(p, &p);
 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