ARM : Add GPIO Driver and IOMUX definition for S3C2440
[oweals/u-boot.git] / drivers / block / fsl_sata.c
index d441a30ed511b184f5019905c419456623f24c1a..3026adec0d6109b67eefd05177bff14409c326ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008,2010 Freescale Semiconductor, Inc.
  *             Dave Liu <daveliu@freescale.com>
  *
  * This program is free software; you can redistribute it and/or
 #include <common.h>
 #include <command.h>
 #include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fsl_serdes.h>
 #include <malloc.h>
 #include <libata.h>
 #include <fis.h>
 #include "fsl_sata.h"
 
-extern block_dev_desc_t sata_dev_desc[CFG_SATA_MAX_DEVICE];
+extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
 
-#ifndef CFG_SATA1_FLAGS
-       #define CFG_SATA1_FLAGS FLAGS_DMA
+#ifndef CONFIG_SYS_SATA1_FLAGS
+       #define CONFIG_SYS_SATA1_FLAGS  FLAGS_DMA
 #endif
-#ifndef CFG_SATA2_FLAGS
-       #define CFG_SATA2_FLAGS FLAGS_DMA
+#ifndef CONFIG_SYS_SATA2_FLAGS
+       #define CONFIG_SYS_SATA2_FLAGS  FLAGS_DMA
 #endif
 
 static struct fsl_sata_info fsl_sata_info[] = {
 #ifdef CONFIG_SATA1
-       {CFG_SATA1, CFG_SATA1_FLAGS},
+       {CONFIG_SYS_SATA1, CONFIG_SYS_SATA1_FLAGS},
 #else
        {0, 0},
 #endif
 #ifdef CONFIG_SATA2
-       {CFG_SATA2, CFG_SATA2_FLAGS},
+       {CONFIG_SYS_SATA2, CONFIG_SYS_SATA2_FLAGS},
 #else
        {0, 0},
 #endif
 };
 
-static inline void mdelay(unsigned long msec)
-{
-       unsigned long i;
-       for (i = 0; i < msec; i++)
-               udelay(1000);
-}
-
 static inline void sdelay(unsigned long sec)
 {
        unsigned long i;
@@ -81,7 +76,7 @@ void dprint_buffer(unsigned char *buf, int len)
        printf("\n\r");
 }
 
-static void fsl_sata_dump_sfis(struct sfis *s)
+static void fsl_sata_dump_sfis(struct sata_fis_d2h *s)
 {
        printf("Status FIS dump:\n\r");
        printf("fis_type:               %02x\n\r", s->fis_type);
@@ -123,11 +118,22 @@ int init_sata(int dev)
        int i;
        fsl_sata_t *sata;
 
-       if (dev < 0 || dev > (CFG_SATA_MAX_DEVICE - 1)) {
+       if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
                printf("the sata index %d is out of ranges\n\r", dev);
                return -1;
        }
 
+#ifdef CONFIG_MPC85xx
+       if ((dev == 0) && (!is_serdes_configured(SATA1))) {
+               printf("SATA%d [dev = %d] is not enabled\n", dev+1, dev);
+               return -1;
+       }
+       if ((dev == 1) && (!is_serdes_configured(SATA2))) {
+               printf("SATA%d [dev = %d] is not enabled\n", dev+1, dev);
+               return -1;
+       }
+#endif
+
        /* Allocate SATA device driver struct */
        sata = (fsl_sata_t *)malloc(sizeof(fsl_sata_t));
        if (!sata) {
@@ -347,7 +353,7 @@ static void fsl_sata_dump_regs(fsl_sata_reg_t *reg)
        printf("SYSPR:          %08x\n\r", in_be32(&reg->syspr));
 }
 
-static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct cfis *cfis,
+static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
                                int is_ncq, int tag, u8 *buffer, u32 len)
 {
        cmd_hdr_entry_t *cmd_hdr;
@@ -483,7 +489,7 @@ static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct cfis *cfis,
 
        if (val32) {
                u32 der;
-               fsl_sata_dump_sfis((struct sfis *)cmd_desc->sfis);
+               fsl_sata_dump_sfis((struct sata_fis_d2h *)cmd_desc->sfis);
                printf("CE at device\n\r");
                fsl_sata_dump_regs(reg);
                der = in_le32(&reg->der);
@@ -498,19 +504,19 @@ static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct cfis *cfis,
        return len;
 }
 
-static int fsl_ata_exec_reset_cmd(struct fsl_sata *sata, struct cfis *cfis,
+static int fsl_ata_exec_reset_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
                                 int tag, u8 *buffer, u32 len)
 {
        return 0;
 }
 
-static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct cfis *cfis,
+static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
                 enum cmd_type command_type, int tag, u8 *buffer, u32 len)
 {
        int rc;
 
        if (tag > SATA_HC_MAX_CMD || tag < 0) {
-               printf("tag is out of range, tag=\n\r", tag);
+               printf("tag is out of range, tag=%d\n\r", tag);
                return -1;
        }
 
@@ -539,11 +545,9 @@ static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct cfis *cfis,
 static void fsl_sata_identify(int dev, u16 *id)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
 
-       cfis = (struct cfis *)&h2d;
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -566,12 +570,10 @@ static void fsl_sata_xfer_mode(int dev, u16 *id)
 static void fsl_sata_set_features(int dev)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
        u8 udma_cap;
 
-       cfis = (struct cfis *)&h2d;
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -597,14 +599,12 @@ static void fsl_sata_set_features(int dev)
 static u32 fsl_sata_rw_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
        u32 block;
 
        block = start;
-       cfis = (struct cfis *)&h2d;
 
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -624,12 +624,9 @@ static u32 fsl_sata_rw_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_wr
 void fsl_sata_flush_cache(int dev)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
 
-       cfis = (struct cfis *)&h2d;
-
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -641,14 +638,12 @@ void fsl_sata_flush_cache(int dev)
 static u32 fsl_sata_rw_cmd_ext(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
        u64 block;
 
        block = (u64)start;
-       cfis = (struct cfis *)&h2d;
 
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -673,20 +668,18 @@ static u32 fsl_sata_rw_cmd_ext(int dev, u32 start, u32 blkcnt, u8 *buffer, int i
 u32 fsl_sata_rw_ncq_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
        int ncq_channel;
        u64 block;
 
-       if (sata_dev_desc[dev].lba48 != 1) {
+       if (sata->lba48 != 1) {
                printf("execute FPDMA command on non-LBA48 hard disk\n\r");
                return -1;
        }
 
        block = (u64)start;
-       cfis = (struct cfis *)&h2d;
 
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -718,12 +711,9 @@ u32 fsl_sata_rw_ncq_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write
 void fsl_sata_flush_cache_ext(int dev)
 {
        fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
-       struct sata_fis_h2d h2d;
-       struct cfis *cfis;
-
-       cfis = (struct cfis *)&h2d;
+       struct sata_fis_h2d h2d, *cfis = &h2d;
 
-       memset((void *)cfis, 0, sizeof(struct cfis));
+       memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
        cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
        cfis->pm_port_c = 0x80; /* is command */
@@ -836,8 +826,9 @@ u32 ata_low_level_rw_lba28(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_
 ulong sata_read(int dev, u32 blknr, u32 blkcnt, void *buffer)
 {
        u32 rc;
+       fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
 
-       if (sata_dev_desc[dev].lba48)
+       if (sata->lba48)
                rc = ata_low_level_rw_lba48(dev, blknr, blkcnt, buffer, READ_CMD);
        else
                rc = ata_low_level_rw_lba28(dev, blknr, blkcnt, buffer, READ_CMD);
@@ -847,8 +838,9 @@ ulong sata_read(int dev, u32 blknr, u32 blkcnt, void *buffer)
 ulong sata_write(int dev, u32 blknr, u32 blkcnt, void *buffer)
 {
        u32 rc;
+       fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
 
-       if (sata_dev_desc[dev].lba48) {
+       if (sata->lba48) {
                rc = ata_low_level_rw_lba48(dev, blknr, blkcnt, buffer, WRITE_CMD);
                if (fsl_sata_get_wcache(dev) && fsl_sata_get_flush_ext(dev))
                        fsl_sata_flush_cache_ext(dev);
@@ -898,11 +890,14 @@ int scan_sata(int dev)
        n_sectors = ata_id_n_sectors(id);
        sata_dev_desc[dev].lba = (u32)n_sectors;
 
+#ifdef CONFIG_LBA48
        /* Check if support LBA48 */
        if (ata_id_has_lba48(id)) {
-               sata_dev_desc[dev].lba48 = 1;
+               sata->lba48 = 1;
                debug("Device support LBA48\n\r");
-       }
+       } else
+               debug("Device supports LBA28\n\r");
+#endif
 
        /* Get the NCQ queue depth from device */
        sata->queue_depth = ata_id_queue_depth(id);