Commit ffc664e80dfb2e17de0df5ad39e91a02e9c361bc

Authored by Dave Liu
Committed by Wolfgang Denk
1 parent 8e9bb43429

ata: add the libata support

add simple libata support in u-boot

Signed-off-by: Dave Liu <daveliu@freescale.com>

Showing 3 changed files with 364 additions and 0 deletions Side-by-side Diff

drivers/block/Makefile
... ... @@ -27,6 +27,7 @@
27 27  
28 28 COBJS-y += ahci.o
29 29 COBJS-y += ata_piix.o
  30 +COBJS-$(CONFIG_LIBATA) += libata.o
30 31 COBJS-y += sil680.o
31 32 COBJS-y += sym53c8xx.o
32 33 COBJS-y += systemace.o
drivers/block/libata.c
  1 +/*
  2 + * Copyright (C) 2008 Freescale Semiconductor, Inc.
  3 + * Dave Liu <daveliu@freescale.com>
  4 + * port from the libata of linux kernel
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License as
  8 + * published by the Free Software Foundation; either version 2 of
  9 + * the License, or (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + *
  21 + */
  22 +
  23 +#include <libata.h>
  24 +
  25 +u64 ata_id_n_sectors(u16 *id)
  26 +{
  27 + if (ata_id_has_lba(id)) {
  28 + if (ata_id_has_lba48(id))
  29 + return ata_id_u64(id, ATA_ID_LBA48_SECTORS);
  30 + else
  31 + return ata_id_u32(id, ATA_ID_LBA_SECTORS);
  32 + } else {
  33 + return 0;
  34 + }
  35 +}
  36 +
  37 +u32 ata_dev_classify(u32 sig)
  38 +{
  39 + u8 lbam, lbah;
  40 +
  41 + lbam = (sig >> 16) & 0xff;
  42 + lbah = (sig >> 24) & 0xff;
  43 +
  44 + if (((lbam == 0) && (lbah == 0)) ||
  45 + ((lbam == 0x3c) && (lbah == 0xc3)))
  46 + return ATA_DEV_ATA;
  47 +
  48 + if ((lbam == 0x14) && (lbah == 0xeb))
  49 + return ATA_DEV_ATAPI;
  50 +
  51 + if ((lbam == 0x69) && (lbah == 0x96))
  52 + return ATA_DEV_PMP;
  53 +
  54 + return ATA_DEV_UNKNOWN;
  55 +}
  56 +
  57 +static void ata_id_string(const u16 *id, unsigned char *s,
  58 + unsigned int ofs, unsigned int len)
  59 +{
  60 + unsigned int c;
  61 +
  62 + while (len > 0) {
  63 + c = id[ofs] >> 8;
  64 + *s = c;
  65 + s++;
  66 +
  67 + c = id[ofs] & 0xff;
  68 + *s = c;
  69 + s++;
  70 +
  71 + ofs++;
  72 + len -= 2;
  73 + }
  74 +}
  75 +
  76 +void ata_id_c_string(const u16 *id, unsigned char *s,
  77 + unsigned int ofs, unsigned int len)
  78 +{
  79 + unsigned char *p;
  80 +
  81 + ata_id_string(id, s, ofs, len - 1);
  82 +
  83 + p = s + strnlen((char *)s, len - 1);
  84 + while (p > s && p[-1] == ' ')
  85 + p--;
  86 + *p = '\0';
  87 +}
  88 +
  89 +void ata_dump_id(u16 *id)
  90 +{
  91 + unsigned char serial[ATA_ID_SERNO_LEN + 1];
  92 + unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
  93 + unsigned char product[ATA_ID_PROD_LEN + 1];
  94 + u64 n_sectors;
  95 +
  96 + /* Serial number */
  97 + ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
  98 + printf("S/N: %s\n\r", serial);
  99 +
  100 + /* Firmware version */
  101 + ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
  102 + printf("Firmware version: %s\n\r", firmware);
  103 +
  104 + /* Product model */
  105 + ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
  106 + printf("Product model number: %s\n\r", product);
  107 +
  108 + /* Total sectors of device */
  109 + n_sectors = ata_id_n_sectors(id);
  110 + printf("Capablity: %d sectors\n\r", n_sectors);
  111 +
  112 + printf("id[49]: capabilities ==0x%04x\n"
  113 + "id[53]: field valid ==0x%04x\n"
  114 + "id[63]: mwdma ==0x%04x\n"
  115 + "id[64]: pio ==0x%04x\n"
  116 + "id[75]: queue depth ==0x%04x\n",
  117 + id[49],
  118 + id[53],
  119 + id[63],
  120 + id[64],
  121 + id[75]);
  122 +
  123 + printf("id[76]: sata capablity ==0x%04x\n"
  124 + "id[78]: sata features supported ==0x%04x\n"
  125 + "id[79]: sata features enable ==0x%04x\n",
  126 + id[76],
  127 + id[78],
  128 + id[79]);
  129 +
  130 + printf("id[80]: major version ==0x%04x\n"
  131 + "id[81]: minor version ==0x%04x\n"
  132 + "id[82]: command set supported 1 ==0x%04x\n"
  133 + "id[83]: command set supported 2 ==0x%04x\n"
  134 + "id[84]: command set extension ==0x%04x\n",
  135 + id[80],
  136 + id[81],
  137 + id[82],
  138 + id[83],
  139 + id[84]);
  140 + printf("id[85]: command set enable 1 ==0x%04x\n"
  141 + "id[86]: command set enable 2 ==0x%04x\n"
  142 + "id[87]: command set default ==0x%04x\n"
  143 + "id[88]: udma ==0x%04x\n"
  144 + "id[93]: hardware reset result ==0x%04x\n",
  145 + id[85],
  146 + id[86],
  147 + id[87],
  148 + id[88],
  149 + id[93]);
  150 +}
  151 +
  152 +void ata_swap_buf_le16(u16 *buf, unsigned int buf_words)
  153 +{
  154 + unsigned int i;
  155 +
  156 + for (i = 0; i < buf_words; i++)
  157 + buf[i] = le16_to_cpu(buf[i]);
  158 +}
  1 +/*
  2 + * Copyright (C) 2008 Freescale Semiconductor, Inc.
  3 + * Dave Liu <daveliu@freescale.com>
  4 + * port from libata of linux kernel
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License as
  8 + * published by the Free Software Foundation; either version 2 of
  9 + * the License, or (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + *
  21 + */
  22 +
  23 +#ifndef __LIBATA_H__
  24 +#define __LIBATA_H__
  25 +
  26 +#include <common.h>
  27 +
  28 +/* command
  29 + */
  30 +enum ata_cmd {
  31 + /* non-NCQ command */
  32 + ATA_CMD_DEV_RESET = 0x08, /* ATAPI device reset */
  33 + ATA_CMD_FLUSH_CACHE = 0xE7,
  34 + ATA_CMD_FLUSH_CACHE_EXT = 0xEA,
  35 + ATA_CMD_ID_ATA = 0xEC,
  36 + ATA_CMD_ID_ATAPI = 0xA1,
  37 + ATA_CMD_READ_DMA = 0xC8,
  38 + ATA_CMD_READ_DMA_EXT = 0x25,
  39 + ATA_CMD_WRITE_DMA = 0xCA,
  40 + ATA_CMD_WRITE_DMA_EXT = 0x35,
  41 + ATA_CMD_PIO_READ = 0x20,
  42 + ATA_CMD_PIO_READ_EXT = 0x24,
  43 + ATA_CMD_PIO_WRITE = 0x30,
  44 + ATA_CMD_PIO_WRITE_EXT = 0x34,
  45 + ATA_CMD_SET_FEATURES = 0xEF,
  46 +
  47 + /* NCQ command */
  48 + ATA_CMD_READ_FPDMA_QUEUED = 0x60,
  49 + ATA_CMD_WRITE_FPDMA_QUEUED = 0x61,
  50 +};
  51 +
  52 +/* SETFEATURES stuff
  53 + */
  54 +enum ata_set_features {
  55 + /* SETFEATURES stuff */
  56 + SETFEATURES_XFER = 0x03,
  57 + XFER_UDMA_7 = 0x47,
  58 + XFER_UDMA_6 = 0x46,
  59 + XFER_UDMA_5 = 0x45,
  60 + XFER_UDMA_4 = 0x44,
  61 + XFER_UDMA_3 = 0x43,
  62 + XFER_UDMA_2 = 0x42,
  63 + XFER_UDMA_1 = 0x41,
  64 + XFER_UDMA_0 = 0x40,
  65 + XFER_MW_DMA_4 = 0x24, /* CFA only */
  66 + XFER_MW_DMA_3 = 0x23, /* CFA only */
  67 + XFER_MW_DMA_2 = 0x22,
  68 + XFER_MW_DMA_1 = 0x21,
  69 + XFER_MW_DMA_0 = 0x20,
  70 + XFER_PIO_6 = 0x0E, /* CFA only */
  71 + XFER_PIO_5 = 0x0D, /* CFA only */
  72 + XFER_PIO_4 = 0x0C,
  73 + XFER_PIO_3 = 0x0B,
  74 + XFER_PIO_2 = 0x0A,
  75 + XFER_PIO_1 = 0x09,
  76 + XFER_PIO_0 = 0x08,
  77 + XFER_PIO_SLOW = 0x00,
  78 +
  79 + SETFEATURES_WC_ON = 0x02, /* Enable write cache */
  80 + SETFEATURES_WC_OFF = 0x82, /* Disable write cache */
  81 +
  82 + SETFEATURES_SPINUP = 0x07, /* Spin-up drive */
  83 +};
  84 +
  85 +enum ata_protocol {
  86 + ATA_PROT_UNKNOWN, /* unknown */
  87 + ATA_PROT_NODATA, /* no data */
  88 + ATA_PROT_PIO, /* PIO data xfer */
  89 + ATA_PROT_DMA, /* DMA */
  90 + ATA_PROT_NCQ, /* NCQ */
  91 + ATA_PROT_ATAPI, /* packet command, PIO data xfer */
  92 + ATA_PROT_ATAPI_NODATA, /* packet command, no data */
  93 + ATA_PROT_ATAPI_DMA, /* packet command, DMA */
  94 +};
  95 +
  96 +enum ata_dev_typed {
  97 + ATA_DEV_ATA, /* ATA device */
  98 + ATA_DEV_ATAPI, /* ATAPI device */
  99 + ATA_DEV_PMP, /* Port Multiplier Port */
  100 + ATA_DEV_UNKNOWN, /* unknown */
  101 +};
  102 +
  103 +enum {
  104 + ATA_SECT_SIZE = 512,
  105 + ATA_MAX_SECTORS_128 = 128,
  106 + ATA_MAX_SECTORS = 256,
  107 + ATA_MAX_SECTORS_LBA48 = 65535,
  108 +
  109 + /* bits in ATA command block registers */
  110 + ATA_HOB = (1 << 7), /* LBA48 selector */
  111 + ATA_NIEN = (1 << 1), /* disable-irq flag */
  112 + ATA_LBA = (1 << 6), /* LBA28 selector */
  113 + ATA_DEV1 = (1 << 4), /* Select Device 1 (slave) */
  114 + ATA_BUSY = (1 << 7), /* BSY status bit */
  115 + ATA_DRDY = (1 << 6), /* device ready */
  116 + ATA_DF = (1 << 5), /* device fault */
  117 + ATA_DRQ = (1 << 3), /* data request i/o */
  118 + ATA_ERR = (1 << 0), /* have an error */
  119 + ATA_SRST = (1 << 2), /* software reset */
  120 + ATA_ICRC = (1 << 7), /* interface CRC error */
  121 + ATA_UNC = (1 << 6), /* uncorrectable media error */
  122 + ATA_IDNF = (1 << 4), /* ID not found */
  123 + ATA_ABORTED = (1 << 2), /* command aborted */
  124 +
  125 + ATA_ID_WORDS = 256,
  126 + ATA_ID_SERNO = 10,
  127 + ATA_ID_FW_REV = 23,
  128 + ATA_ID_PROD = 27,
  129 + ATA_ID_FIELD_VALID = 53,
  130 + ATA_ID_LBA_SECTORS = 60,
  131 + ATA_ID_MWDMA_MODES = 63,
  132 + ATA_ID_PIO_MODES = 64,
  133 + ATA_ID_QUEUE_DEPTH = 75,
  134 + ATA_ID_SATA_CAP = 76,
  135 + ATA_ID_SATA_FEATURES = 78,
  136 + ATA_ID_SATA_FEATURES_EN = 79,
  137 + ATA_ID_MAJOR_VER = 80,
  138 + ATA_ID_MINOR_VER = 81,
  139 + ATA_ID_UDMA_MODES = 88,
  140 + ATA_ID_LBA48_SECTORS = 100,
  141 +
  142 + ATA_ID_SERNO_LEN = 20,
  143 + ATA_ID_FW_REV_LEN = 8,
  144 + ATA_ID_PROD_LEN = 40,
  145 +
  146 + ATA_PIO3 = (1 << 0),
  147 + ATA_PIO4 = ATA_PIO3 | (1 << 1),
  148 +
  149 + ATA_UDMA0 = (1 << 0),
  150 + ATA_UDMA1 = ATA_UDMA0 | (1 << 1),
  151 + ATA_UDMA2 = ATA_UDMA1 | (1 << 2),
  152 + ATA_UDMA3 = ATA_UDMA2 | (1 << 3),
  153 + ATA_UDMA4 = ATA_UDMA3 | (1 << 4),
  154 + ATA_UDMA5 = ATA_UDMA4 | (1 << 5),
  155 + ATA_UDMA6 = ATA_UDMA5 | (1 << 6),
  156 + ATA_UDMA7 = ATA_UDMA6 | (1 << 7),
  157 +};
  158 +
  159 +#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
  160 +#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
  161 +#define ata_id_has_fua(id) ((id)[84] & (1 << 6))
  162 +#define ata_id_has_flush(id) ((id)[83] & (1 << 12))
  163 +#define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13))
  164 +#define ata_id_has_lba48(id) ((id)[83] & (1 << 10))
  165 +#define ata_id_has_wcache(id) ((id)[82] & (1 << 5))
  166 +#define ata_id_has_lba(id) ((id)[49] & (1 << 9))
  167 +#define ata_id_has_dma(id) ((id)[49] & (1 << 8))
  168 +#define ata_id_has_ncq(id) ((id)[76] & (1 << 8))
  169 +#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
  170 +
  171 +#define ata_id_u32(id,n) \
  172 + (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
  173 +#define ata_id_u64(id,n) \
  174 + ( ((u64) (id)[(n) + 3] << 48) | \
  175 + ((u64) (id)[(n) + 2] << 32) | \
  176 + ((u64) (id)[(n) + 1] << 16) | \
  177 + ((u64) (id)[(n) + 0]) )
  178 +
  179 +
  180 +static inline unsigned int ata_id_major_version(const u16 *id)
  181 +{
  182 + unsigned int mver;
  183 +
  184 + if (id[ATA_ID_MAJOR_VER] == 0xFFFF)
  185 + return 0;
  186 +
  187 + for (mver = 14; mver >= 1; mver--)
  188 + if (id[ATA_ID_MAJOR_VER] & (1 << mver))
  189 + break;
  190 + return mver;
  191 +}
  192 +
  193 +static inline int ata_id_is_sata(const u16 *id)
  194 +{
  195 + return ata_id_major_version(id) >= 5 && id[93] == 0;
  196 +}
  197 +
  198 +u64 ata_id_n_sectors(u16 *id);
  199 +u32 ata_dev_classify(u32 sig);
  200 +void ata_id_c_string(const u16 *id, unsigned char *s,
  201 + unsigned int ofs, unsigned int len);
  202 +void ata_dump_id(u16 *id);
  203 +void ata_swap_buf_le16(u16 *buf, unsigned int buf_words);
  204 +
  205 +#endif /* __LIBATA_H__ */