* [U-Boot] [PATCH 7/9] SATA: add driver for MX5 / MX6 SOCs
2012-02-22 10:24 [U-Boot] [PATCH 1/9] Define UART4 and UART5 base addresses Stefano Babic
` (4 preceding siblings ...)
2012-02-22 10:24 ` [U-Boot] [PATCH 6/9] MX53: add function to set SATA clock to internal Stefano Babic
@ 2012-02-22 10:24 ` Stefano Babic
2012-02-22 10:24 ` [U-Boot] [PATCH 8/9] MX53: Add support to ESG ima3 board Stefano Babic
2012-02-22 10:24 ` [U-Boot] [PATCH 9/9] MX53: mx53loco: Add SATA support Stefano Babic
7 siblings, 0 replies; 15+ messages in thread
From: Stefano Babic @ 2012-02-22 10:24 UTC (permalink / raw)
To: u-boot
This driver is part of Freescale's LTIB for
MX5 / MX6.
Signed-off-by: Stefano Babic <sbabic@denx.de>
Signed-off-by: Terry Lv <r65388@freescale.com>
CC: Fabio Estevam <fabio.estevam@freescale.com>
CC: Dirk Behme <dirk.behme@de.bosch.com>
---
drivers/block/Makefile | 1 +
drivers/block/dwc_ahsata.c | 969 ++++++++++++++++++++++++++++++++++++++++++++
drivers/block/dwc_ahsata.h | 335 +++++++++++++++
include/ahci.h | 5 +-
4 files changed, 1308 insertions(+), 2 deletions(-)
create mode 100644 drivers/block/dwc_ahsata.c
create mode 100644 drivers/block/dwc_ahsata.h
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 98560ef..b9c2047 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -27,6 +27,7 @@ LIB := $(obj)libblock.o
COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
COBJS-$(CONFIG_ATA_PIIX) += ata_piix.o
+COBJS-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o
COBJS-$(CONFIG_IDE_FTIDE020) += ftide020.o
COBJS-$(CONFIG_LIBATA) += libata.o
diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c
new file mode 100644
index 0000000..2703d3d
--- /dev/null
+++ b/drivers/block/dwc_ahsata.c
@@ -0,0 +1,969 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Terry Lv <r65388@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ *
+ */
+
+#include <libata.h>
+#include <ahci.h>
+#include <fis.h>
+
+#include <common.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <asm/arch/clock.h>
+#include "dwc_ahsata.h"
+
+struct sata_port_regs {
+ u32 clb;
+ u32 clbu;
+ u32 fb;
+ u32 fbu;
+ u32 is;
+ u32 ie;
+ u32 cmd;
+ u32 res1[1];
+ u32 tfd;
+ u32 sig;
+ u32 ssts;
+ u32 sctl;
+ u32 serr;
+ u32 sact;
+ u32 ci;
+ u32 sntf;
+ u32 res2[1];
+ u32 dmacr;
+ u32 res3[1];
+ u32 phycr;
+ u32 physr;
+};
+
+struct sata_host_regs {
+ u32 cap;
+ u32 ghc;
+ u32 is;
+ u32 pi;
+ u32 vs;
+ u32 ccc_ctl;
+ u32 ccc_ports;
+ u32 res1[2];
+ u32 cap2;
+ u32 res2[30];
+ u32 bistafr;
+ u32 bistcr;
+ u32 bistfctr;
+ u32 bistsr;
+ u32 bistdecr;
+ u32 res3[2];
+ u32 oobr;
+ u32 res4[8];
+ u32 timer1ms;
+ u32 res5[1];
+ u32 gparam1r;
+ u32 gparam2r;
+ u32 pparamr;
+ u32 testr;
+ u32 versionr;
+ u32 idr;
+};
+
+#define MAX_DATA_BYTES_PER_SG (4 * 1024 * 1024)
+#define MAX_BYTES_PER_TRANS (AHCI_MAX_SG * MAX_DATA_BYTES_PER_SG)
+
+#define writel_with_flush(a, b) do { writel(a, b); readl(b); } while (0)
+
+static int is_ready;
+
+static inline u32 ahci_port_base(u32 base, u32 port)
+{
+ return base + 0x100 + (port * 0x80);
+}
+
+static int waiting_for_cmd_completed(u8 *offset,
+ int timeout_msec,
+ u32 sign)
+{
+ int i;
+ u32 status;
+
+ for (i = 0;
+ ((status = readl(offset)) & sign) && i < timeout_msec;
+ ++i)
+ mdelay(1);
+
+ return (i < timeout_msec) ? 0 : -1;
+}
+
+static int ahci_setup_oobr(struct ahci_probe_ent *probe_ent,
+ int clk)
+{
+ struct sata_host_regs *host_mmio =
+ (struct sata_host_regs *)probe_ent->mmio_base;
+
+ writel(SATA_HOST_OOBR_WE, &(host_mmio->oobr));
+ writel(0x02060b14, &(host_mmio->oobr));
+
+ return 0;
+}
+
+static int ahci_host_init(struct ahci_probe_ent *probe_ent)
+{
+ u32 tmp, cap_save, num_ports;
+ int i, j, timeout = 1000;
+ struct sata_port_regs *port_mmio = NULL;
+ struct sata_host_regs *host_mmio =
+ (struct sata_host_regs *)probe_ent->mmio_base;
+ int clk = mxc_get_clock(MXC_SATA_CLK);
+
+ cap_save = readl(&(host_mmio->cap));
+ cap_save |= SATA_HOST_CAP_SSS;
+
+ /* global controller reset */
+ tmp = readl(&(host_mmio->ghc));
+ if ((tmp & SATA_HOST_GHC_HR) == 0)
+ writel_with_flush(tmp | SATA_HOST_GHC_HR, &(host_mmio->ghc));
+
+ while ((readl(&(host_mmio->ghc)) & SATA_HOST_GHC_HR)
+ && --timeout)
+ ;
+
+ if (timeout <= 0) {
+ debug("controller reset failed (0x%x)\n", tmp);
+ return -1;
+ }
+
+ /* Set timer 1ms */
+ writel(clk / 1000, &(host_mmio->timer1ms));
+
+ ahci_setup_oobr(probe_ent, 0);
+
+ writel_with_flush(SATA_HOST_GHC_AE, &(host_mmio->ghc));
+ writel(cap_save, &(host_mmio->cap));
+ num_ports = (cap_save & SATA_HOST_CAP_NP_MASK) + 1;
+ writel_with_flush((1 << num_ports) - 1,
+ &(host_mmio->pi));
+
+ /*
+ * Determine which Ports are implemented by the DWC_ahsata,
+ * by reading the PI register. This bit map value aids the
+ * software to determine how many Ports are available and
+ * which Port registers need to be initialized.
+ */
+ probe_ent->cap = readl(&(host_mmio->cap));
+ probe_ent->port_map = readl(&(host_mmio->pi));
+
+ /* Determine how many command slots the HBA supports */
+ probe_ent->n_ports =
+ (probe_ent->cap & SATA_HOST_CAP_NP_MASK) + 1;
+
+ debug("cap 0x%x port_map 0x%x n_ports %d\n",
+ probe_ent->cap, probe_ent->port_map, probe_ent->n_ports);
+
+ for (i = 0; i < probe_ent->n_ports; i++) {
+ probe_ent->port[i].port_mmio =
+ ahci_port_base((u32)host_mmio, i);
+ port_mmio =
+ (struct sata_port_regs *)probe_ent->port[i].port_mmio;
+
+ /* Ensure that the DWC_ahsata is in idle state */
+ tmp = readl(&(port_mmio->cmd));
+
+ /*
+ * When P#CMD.ST, P#CMD.CR, P#CMD.FRE and P#CMD.FR
+ * are all cleared, the Port is in an idle state.
+ */
+ if (tmp & (SATA_PORT_CMD_CR | SATA_PORT_CMD_FR |
+ SATA_PORT_CMD_FRE | SATA_PORT_CMD_ST)) {
+
+ /*
+ * System software places a Port into the idle state by
+ * clearing P#CMD.ST and waiting for P#CMD.CR to return
+ * 0 when read.
+ */
+ tmp &= ~SATA_PORT_CMD_ST;
+ writel_with_flush(tmp, &(port_mmio->cmd));
+
+ /*
+ * spec says 500 msecs for each bit, so
+ * this is slightly incorrect.
+ */
+ mdelay(500);
+
+ timeout = 1000;
+ while ((readl(&(port_mmio->cmd)) & SATA_PORT_CMD_CR)
+ && --timeout)
+ ;
+
+ if (timeout <= 0) {
+ debug("port reset failed (0x%x)\n", tmp);
+ return -1;
+ }
+ }
+
+ /* Spin-up device */
+ tmp = readl(&(port_mmio->cmd));
+ writel((tmp | SATA_PORT_CMD_SUD), &(port_mmio->cmd));
+
+ /* Wait for spin-up to finish */
+ timeout = 1000;
+ while (!(readl(&(port_mmio->cmd)) | SATA_PORT_CMD_SUD)
+ && --timeout)
+ ;
+ if (timeout <= 0) {
+ debug("Spin-Up can't finish!\n");
+ return -1;
+ }
+
+ for (j = 0; j < 100; ++j) {
+ mdelay(10);
+ tmp = readl(&(port_mmio->ssts));
+ if (((tmp & SATA_PORT_SSTS_DET_MASK) == 0x3) ||
+ ((tmp & SATA_PORT_SSTS_DET_MASK) == 0x1))
+ break;
+ }
+
+ /* Wait for COMINIT bit 26 (DIAG_X) in SERR */
+ timeout = 1000;
+ while (!(readl(&(port_mmio->serr)) | SATA_PORT_SERR_DIAG_X)
+ && --timeout)
+ ;
+ if (timeout <= 0) {
+ debug("Can't find DIAG_X set!\n");
+ return -1;
+ }
+
+ /*
+ * For each implemented Port, clear the P#SERR
+ * register, by writing ones to each implemented\
+ * bit location.
+ */
+ tmp = readl(&(port_mmio->serr));
+ debug("P#SERR 0x%x\n",
+ tmp);
+ writel(tmp, &(port_mmio->serr));
+
+ /* Ack any pending irq events for this port */
+ tmp = readl(&(host_mmio->is));
+ debug("IS 0x%x\n", tmp);
+ if (tmp)
+ writel(tmp, &(host_mmio->is));
+
+ writel(1 << i, &(host_mmio->is));
+
+ /* set irq mask (enables interrupts) */
+ writel(DEF_PORT_IRQ, &(port_mmio->ie));
+
+ /* register linkup ports */
+ tmp = readl(&(port_mmio->ssts));
+ debug("Port %d status: 0x%x\n", i, tmp);
+ if ((tmp & SATA_PORT_SSTS_DET_MASK) == 0x03)
+ probe_ent->link_port_map |= (0x01 << i);
+ }
+
+ tmp = readl(&(host_mmio->ghc));
+ debug("GHC 0x%x\n", tmp);
+ writel(tmp | SATA_HOST_GHC_IE, &(host_mmio->ghc));
+ tmp = readl(&(host_mmio->ghc));
+ debug("GHC 0x%x\n", tmp);
+
+ return 0;
+}
+
+static void ahci_print_info(struct ahci_probe_ent *probe_ent)
+{
+ struct sata_host_regs *host_mmio =
+ (struct sata_host_regs *)probe_ent->mmio_base;
+ u32 vers, cap, impl, speed;
+ const char *speed_s;
+ const char *scc_s;
+
+ vers = readl(&(host_mmio->vs));
+ cap = probe_ent->cap;
+ impl = probe_ent->port_map;
+
+ speed = (cap & SATA_HOST_CAP_ISS_MASK)
+ >> SATA_HOST_CAP_ISS_OFFSET;
+ if (speed == 1)
+ speed_s = "1.5";
+ else if (speed == 2)
+ speed_s = "3";
+ else
+ speed_s = "?";
+
+ scc_s = "SATA";
+
+ printf("AHCI %02x%02x.%02x%02x "
+ "%u slots %u ports %s Gbps 0x%x impl %s mode\n",
+ (vers >> 24) & 0xff,
+ (vers >> 16) & 0xff,
+ (vers >> 8) & 0xff,
+ vers & 0xff,
+ ((cap >> 8) & 0x1f) + 1,
+ (cap & 0x1f) + 1,
+ speed_s,
+ impl,
+ scc_s);
+
+ printf("flags: "
+ "%s%s%s%s%s%s"
+ "%s%s%s%s%s%s%s\n",
+ cap & (1 << 31) ? "64bit " : "",
+ cap & (1 << 30) ? "ncq " : "",
+ cap & (1 << 28) ? "ilck " : "",
+ cap & (1 << 27) ? "stag " : "",
+ cap & (1 << 26) ? "pm " : "",
+ cap & (1 << 25) ? "led " : "",
+ cap & (1 << 24) ? "clo " : "",
+ cap & (1 << 19) ? "nz " : "",
+ cap & (1 << 18) ? "only " : "",
+ cap & (1 << 17) ? "pmp " : "",
+ cap & (1 << 15) ? "pio " : "",
+ cap & (1 << 14) ? "slum " : "",
+ cap & (1 << 13) ? "part " : "");
+}
+
+static int ahci_init_one(int pdev)
+{
+ int rc;
+ struct ahci_probe_ent *probe_ent = NULL;
+
+ probe_ent = malloc(sizeof(struct ahci_probe_ent));
+ memset(probe_ent, 0, sizeof(struct ahci_probe_ent));
+ probe_ent->dev = pdev;
+
+ probe_ent->host_flags = ATA_FLAG_SATA
+ | ATA_FLAG_NO_LEGACY
+ | ATA_FLAG_MMIO
+ | ATA_FLAG_PIO_DMA
+ | ATA_FLAG_NO_ATAPI;
+
+ probe_ent->mmio_base = CONFIG_DWC_AHSATA_BASE_ADDR;
+
+ /* initialize adapter */
+ rc = ahci_host_init(probe_ent);
+ if (rc)
+ goto err_out;
+
+ ahci_print_info(probe_ent);
+
+ /* Save the private struct to block device struct */
+ sata_dev_desc[pdev].priv = (void *)probe_ent;
+
+ return 0;
+
+err_out:
+ return rc;
+}
+
+static int ahci_fill_sg(struct ahci_probe_ent *probe_ent,
+ u8 port, unsigned char *buf, int buf_len)
+{
+ struct ahci_ioports *pp = &(probe_ent->port[port]);
+ struct ahci_sg *ahci_sg = pp->cmd_tbl_sg;
+ u32 sg_count, max_bytes;
+ int i;
+
+ max_bytes = MAX_DATA_BYTES_PER_SG;
+ sg_count = ((buf_len - 1) / max_bytes) + 1;
+ if (sg_count > AHCI_MAX_SG) {
+ printf("Error:Too much sg!\n");
+ return -1;
+ }
+
+ for (i = 0; i < sg_count; i++) {
+ ahci_sg->addr =
+ cpu_to_le32((u32)buf + i * max_bytes);
+ ahci_sg->addr_hi = 0;
+ ahci_sg->flags_size = cpu_to_le32(0x3fffff &
+ (buf_len < max_bytes
+ ? (buf_len - 1)
+ : (max_bytes - 1)));
+ ahci_sg++;
+ buf_len -= max_bytes;
+ }
+
+ return sg_count;
+}
+
+static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 cmd_slot, u32 opts)
+{
+ struct ahci_cmd_hdr *cmd_hdr = (struct ahci_cmd_hdr *)(pp->cmd_slot +
+ AHCI_CMD_SLOT_SZ * cmd_slot);
+
+ memset(cmd_hdr, 0, AHCI_CMD_SLOT_SZ);
+ cmd_hdr->opts = cpu_to_le32(opts);
+ cmd_hdr->status = 0;
+ cmd_hdr->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff);
+ cmd_hdr->tbl_addr_hi = 0;
+}
+
+#define AHCI_GET_CMD_SLOT(c) ((c) ? ffs(c) : 0)
+
+static int ahci_exec_ata_cmd(struct ahci_probe_ent *probe_ent,
+ u8 port, struct sata_fis_h2d *cfis,
+ u8 *buf, u32 buf_len, s32 is_write)
+{
+ struct ahci_ioports *pp = &(probe_ent->port[port]);
+ struct sata_port_regs *port_mmio =
+ (struct sata_port_regs *)pp->port_mmio;
+ u32 opts;
+ int sg_count = 0, cmd_slot = 0;
+
+ cmd_slot = AHCI_GET_CMD_SLOT(readl(&(port_mmio->ci)));
+ if (32 == cmd_slot) {
+ printf("Can't find empty command slot!\n");
+ return 0;
+ }
+
+ /* Check xfer length */
+ if (buf_len > MAX_BYTES_PER_TRANS) {
+ printf("Max transfer length is %dB\n\r",
+ MAX_BYTES_PER_TRANS);
+ return 0;
+ }
+
+ memcpy((u8 *)(pp->cmd_tbl), cfis, sizeof(struct sata_fis_h2d));
+ if (buf && buf_len)
+ sg_count = ahci_fill_sg(probe_ent, port, buf, buf_len);
+ opts = (sizeof(struct sata_fis_h2d) >> 2) | (sg_count << 16);
+ if (is_write)
+ opts |= 0x40;
+ ahci_fill_cmd_slot(pp, cmd_slot, opts);
+
+ writel_with_flush(1 << cmd_slot, &(port_mmio->ci));
+
+ if (waiting_for_cmd_completed((u8 *)&(port_mmio->ci),
+ 10000, 0x1 << cmd_slot)) {
+ printf("timeout exit!\n");
+ return -1;
+ }
+ debug("ahci_exec_ata_cmd: %d byte transferred.\n",
+ pp->cmd_slot->status);
+
+ return buf_len;
+}
+
+static void ahci_set_feature(u8 dev, u8 port)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 1 << 7;
+ cfis->command = ATA_CMD_SET_FEATURES;
+ cfis->features = SETFEATURES_XFER;
+ cfis->sector_count = ffs(probe_ent->udma_mask + 1) + 0x3e;
+
+ ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, READ_CMD);
+}
+
+static int ahci_port_start(struct ahci_probe_ent *probe_ent,
+ u8 port)
+{
+ struct ahci_ioports *pp = &(probe_ent->port[port]);
+ struct sata_port_regs *port_mmio =
+ (struct sata_port_regs *)pp->port_mmio;
+ u32 port_status;
+ u32 mem;
+ int timeout = 10000000;
+
+ debug("Enter start port: %d\n", port);
+ port_status = readl(&(port_mmio->ssts));
+ debug("Port %d status: %x\n", port, port_status);
+ if ((port_status & 0xf) != 0x03) {
+ printf("No Link on this port!\n");
+ return -1;
+ }
+
+ mem = (u32)malloc(AHCI_PORT_PRIV_DMA_SZ + 1024);
+ if (!mem) {
+ free(pp);
+ printf("No mem for table!\n");
+ return -ENOMEM;
+ }
+
+ mem = (mem + 0x400) & (~0x3ff); /* Aligned to 1024-bytes */
+ memset((u8 *)mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+
+ /*
+ * First item in chunk of DMA memory: 32-slot command table,
+ * 32 bytes each in size
+ */
+ pp->cmd_slot = (struct ahci_cmd_hdr *)mem;
+ debug("cmd_slot = 0x%x\n", (unsigned int) pp->cmd_slot);
+ mem += (AHCI_CMD_SLOT_SZ * DWC_AHSATA_MAX_CMD_SLOTS);
+
+ /*
+ * Second item: Received-FIS area, 256-Byte aligned
+ */
+ pp->rx_fis = mem;
+ mem += AHCI_RX_FIS_SZ;
+
+ /*
+ * Third item: data area for storing a single command
+ * and its scatter-gather table
+ */
+ pp->cmd_tbl = mem;
+ debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl);
+
+ mem += AHCI_CMD_TBL_HDR;
+
+ writel_with_flush(0x00004444, &(port_mmio->dmacr));
+ pp->cmd_tbl_sg = (struct ahci_sg *)mem;
+ writel_with_flush((u32)pp->cmd_slot, &(port_mmio->clb));
+ writel_with_flush(pp->rx_fis, &(port_mmio->fb));
+
+ /* Enable FRE */
+ writel_with_flush((SATA_PORT_CMD_FRE | readl(&(port_mmio->cmd))),
+ &(port_mmio->cmd));
+
+ /* Wait device ready */
+ while ((readl(&(port_mmio->tfd)) & (SATA_PORT_TFD_STS_ERR |
+ SATA_PORT_TFD_STS_DRQ | SATA_PORT_TFD_STS_BSY))
+ && --timeout)
+ ;
+ if (timeout <= 0) {
+ debug("Device not ready for BSY, DRQ and"
+ "ERR in TFD!\n");
+ return -1;
+ }
+
+ writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
+ PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
+ PORT_CMD_START, &(port_mmio->cmd));
+
+ debug("Exit start port %d\n", port);
+
+ return 0;
+}
+
+int init_sata(int dev)
+{
+ int i;
+ u32 linkmap;
+ struct ahci_probe_ent *probe_ent = NULL;
+
+ if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
+ printf("The sata index %d is out of ranges\n\r", dev);
+ return -1;
+ }
+
+ ahci_init_one(dev);
+
+ probe_ent = (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ linkmap = probe_ent->link_port_map;
+
+ if (0 == linkmap) {
+ printf("No port device detected!\n");
+ return 1;
+ }
+
+ for (i = 0; i < probe_ent->n_ports; i++) {
+ if ((linkmap >> i) && ((linkmap >> i) & 0x01)) {
+ if (ahci_port_start(probe_ent, (u8)i)) {
+ printf("Can not start port %d\n", i);
+ return 1;
+ }
+ probe_ent->hard_port_no = i;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void dwc_ahsata_print_info(int dev)
+{
+ block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+
+ printf("SATA Device Info:\n\r");
+#ifdef CONFIG_SYS_64BIT_LBA
+ printf("S/N: %s\n\rProduct model number: %s\n\r"
+ "Firmware version: %s\n\rCapacity: %lld sectors\n\r",
+ pdev->product, pdev->vendor, pdev->revision, pdev->lba);
+#else
+ printf("S/N: %s\n\rProduct model number: %s\n\r"
+ "Firmware version: %s\n\rCapacity: %ld sectors\n\r",
+ pdev->product, pdev->vendor, pdev->revision, pdev->lba);
+#endif
+}
+
+static void dwc_ahsata_identify(int dev, u16 *id)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+ u8 port = probe_ent->hard_port_no;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = ATA_CMD_ID_ATA;
+
+ ahci_exec_ata_cmd(probe_ent, port, cfis,
+ (u8 *)id, ATA_ID_WORDS * 2, READ_CMD);
+ ata_swap_buf_le16(id, ATA_ID_WORDS);
+}
+
+static void dwc_ahsata_xfer_mode(int dev, u16 *id)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+
+ probe_ent->pio_mask = id[ATA_ID_PIO_MODES];
+ probe_ent->udma_mask = id[ATA_ID_UDMA_MODES];
+ debug("pio %04x, udma %04x\n\r",
+ probe_ent->pio_mask, probe_ent->udma_mask);
+}
+
+static u32 dwc_ahsata_rw_cmd(int dev, u32 start, u32 blkcnt,
+ u8 *buffer, int is_write)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+ u8 port = probe_ent->hard_port_no;
+ u32 block;
+
+ block = start;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ;
+ cfis->device = ATA_LBA;
+
+ cfis->device |= (block >> 24) & 0xf;
+ cfis->lba_high = (block >> 16) & 0xff;
+ cfis->lba_mid = (block >> 8) & 0xff;
+ cfis->lba_low = block & 0xff;
+ cfis->sector_count = (u8)(blkcnt & 0xff);
+
+ if (ahci_exec_ata_cmd(probe_ent, port, cfis,
+ buffer, ATA_SECT_SIZE * blkcnt, is_write) > 0)
+ return blkcnt;
+ else
+ return 0;
+}
+
+void dwc_ahsata_flush_cache(int dev)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+ u8 port = probe_ent->hard_port_no;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = ATA_CMD_FLUSH;
+
+ ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, 0);
+}
+
+static u32 dwc_ahsata_rw_cmd_ext(int dev, u32 start, lbaint_t blkcnt,
+ u8 *buffer, int is_write)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+ u8 port = probe_ent->hard_port_no;
+ u64 block;
+
+ block = (u64)start;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+
+ cfis->command = (is_write) ? ATA_CMD_WRITE_EXT
+ : ATA_CMD_READ_EXT;
+
+ cfis->lba_high_exp = (block >> 40) & 0xff;
+ cfis->lba_mid_exp = (block >> 32) & 0xff;
+ cfis->lba_low_exp = (block >> 24) & 0xff;
+ cfis->lba_high = (block >> 16) & 0xff;
+ cfis->lba_mid = (block >> 8) & 0xff;
+ cfis->lba_low = block & 0xff;
+ cfis->device = ATA_LBA;
+ cfis->sector_count_exp = (blkcnt >> 8) & 0xff;
+ cfis->sector_count = blkcnt & 0xff;
+
+ if (ahci_exec_ata_cmd(probe_ent, port, cfis, buffer,
+ ATA_SECT_SIZE * blkcnt, is_write) > 0)
+ return blkcnt;
+ else
+ return 0;
+}
+
+u32 dwc_ahsata_rw_ncq_cmd(int dev, u32 start, lbaint_t blkcnt,
+ u8 *buffer, int is_write)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+ u8 port = probe_ent->hard_port_no;
+ u64 block;
+
+ if (sata_dev_desc[dev].lba48 != 1) {
+ printf("execute FPDMA command on non-LBA48 hard disk\n\r");
+ return -1;
+ }
+
+ block = (u64)start;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+
+ cfis->command = (is_write) ? ATA_CMD_FPDMA_WRITE
+ : ATA_CMD_FPDMA_READ;
+
+ cfis->lba_high_exp = (block >> 40) & 0xff;
+ cfis->lba_mid_exp = (block >> 32) & 0xff;
+ cfis->lba_low_exp = (block >> 24) & 0xff;
+ cfis->lba_high = (block >> 16) & 0xff;
+ cfis->lba_mid = (block >> 8) & 0xff;
+ cfis->lba_low = block & 0xff;
+
+ cfis->device = ATA_LBA;
+ cfis->features_exp = (blkcnt >> 8) & 0xff;
+ cfis->features = blkcnt & 0xff;
+
+ /* Use the latest queue */
+ ahci_exec_ata_cmd(probe_ent, port, cfis,
+ buffer, ATA_SECT_SIZE * blkcnt, is_write);
+
+ return blkcnt;
+}
+
+void dwc_ahsata_flush_cache_ext(int dev)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ struct sata_fis_h2d h2d, *cfis = &h2d;
+ u8 port = probe_ent->hard_port_no;
+
+ memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+ cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+ cfis->pm_port_c = 0x80; /* is command */
+ cfis->command = ATA_CMD_FLUSH_EXT;
+
+ ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, 0);
+}
+
+static void dwc_ahsata_init_wcache(int dev, u16 *id)
+{
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+
+ if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id))
+ probe_ent->flags |= SATA_FLAG_WCACHE;
+ if (ata_id_has_flush(id))
+ probe_ent->flags |= SATA_FLAG_FLUSH;
+ if (ata_id_has_flush_ext(id))
+ probe_ent->flags |= SATA_FLAG_FLUSH_EXT;
+}
+
+u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
+ void *buffer, int is_write)
+{
+ u32 start, blks;
+ u8 *addr;
+ int max_blks;
+
+ start = blknr;
+ blks = blkcnt;
+ addr = (u8 *)buffer;
+
+ max_blks = ATA_MAX_SECTORS_LBA48;
+
+ do {
+ if (blks > max_blks) {
+ if (max_blks != dwc_ahsata_rw_cmd_ext(dev, start,
+ max_blks, addr, is_write))
+ return 0;
+ start += max_blks;
+ blks -= max_blks;
+ addr += ATA_SECT_SIZE * max_blks;
+ } else {
+ if (blks != dwc_ahsata_rw_cmd_ext(dev, start,
+ blks, addr, is_write))
+ return 0;
+ start += blks;
+ blks = 0;
+ addr += ATA_SECT_SIZE * blks;
+ }
+ } while (blks != 0);
+
+ return blkcnt;
+}
+
+u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt,
+ void *buffer, int is_write)
+{
+ u32 start, blks;
+ u8 *addr;
+ int max_blks;
+
+ start = blknr;
+ blks = blkcnt;
+ addr = (u8 *)buffer;
+
+ max_blks = ATA_MAX_SECTORS;
+ do {
+ if (blks > max_blks) {
+ if (max_blks != dwc_ahsata_rw_cmd(dev, start,
+ max_blks, addr, is_write))
+ return 0;
+ start += max_blks;
+ blks -= max_blks;
+ addr += ATA_SECT_SIZE * max_blks;
+ } else {
+ if (blks != dwc_ahsata_rw_cmd(dev, start,
+ blks, addr, is_write))
+ return 0;
+ start += blks;
+ blks = 0;
+ addr += ATA_SECT_SIZE * blks;
+ }
+ } while (blks != 0);
+
+ return blkcnt;
+}
+
+/*
+ * SATA interface between low level driver and command layer
+ */
+ulong sata_read(int dev, unsigned long blknr, lbaint_t blkcnt, void *buffer)
+{
+ u32 rc;
+
+ if (sata_dev_desc[dev].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);
+ return rc;
+}
+
+ulong sata_write(int dev, unsigned long blknr, lbaint_t blkcnt, void *buffer)
+{
+ u32 rc;
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ u32 flags = probe_ent->flags;
+
+ if (sata_dev_desc[dev].lba48) {
+ rc = ata_low_level_rw_lba48(dev, blknr, blkcnt,
+ buffer, WRITE_CMD);
+ if ((flags & SATA_FLAG_WCACHE) &&
+ (flags & SATA_FLAG_FLUSH_EXT))
+ dwc_ahsata_flush_cache_ext(dev);
+ } else {
+ rc = ata_low_level_rw_lba28(dev, blknr, blkcnt,
+ buffer, WRITE_CMD);
+ if ((flags & SATA_FLAG_WCACHE) &&
+ (flags & SATA_FLAG_FLUSH))
+ dwc_ahsata_flush_cache(dev);
+ }
+ return rc;
+}
+
+int scan_sata(int dev)
+{
+ u8 serial[ATA_ID_SERNO_LEN + 1] = { 0 };
+ u8 firmware[ATA_ID_FW_REV_LEN + 1] = { 0 };
+ u8 product[ATA_ID_PROD_LEN + 1] = { 0 };
+ u16 *id;
+ u64 n_sectors;
+ struct ahci_probe_ent *probe_ent =
+ (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
+ u8 port = probe_ent->hard_port_no;
+ block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+
+ id = (u16 *)malloc(ATA_ID_WORDS * 2);
+ if (!id) {
+ printf("id malloc failed\n\r");
+ return -1;
+ }
+
+ /* Identify device to get information */
+ dwc_ahsata_identify(dev, id);
+
+ /* Serial number */
+ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
+ memcpy(pdev->product, serial, sizeof(serial));
+
+ /* Firmware version */
+ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
+ memcpy(pdev->revision, firmware, sizeof(firmware));
+
+ /* Product model */
+ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
+ memcpy(pdev->vendor, product, sizeof(product));
+
+ /* Totoal sectors */
+ n_sectors = ata_id_n_sectors(id);
+ pdev->lba = (u32)n_sectors;
+
+ pdev->type = DEV_TYPE_HARDDISK;
+ pdev->blksz = ATA_SECT_SIZE;
+ pdev->lun = 0 ;
+
+ /* Check if support LBA48 */
+ if (ata_id_has_lba48(id)) {
+ pdev->lba48 = 1;
+ debug("Device support LBA48\n\r");
+ }
+
+ /* Get the NCQ queue depth from device */
+ probe_ent->flags &= (~SATA_FLAG_Q_DEP_MASK);
+ probe_ent->flags |= ata_id_queue_depth(id);
+
+ /* Get the xfer mode from device */
+ dwc_ahsata_xfer_mode(dev, id);
+
+ /* Get the write cache status from device */
+ dwc_ahsata_init_wcache(dev, id);
+
+ /* Set the xfer mode to highest speed */
+ ahci_set_feature(dev, port);
+
+ free((void *)id);
+
+ dwc_ahsata_print_info(dev);
+
+ is_ready = 1;
+
+ return 0;
+}
diff --git a/drivers/block/dwc_ahsata.h b/drivers/block/dwc_ahsata.h
new file mode 100644
index 0000000..84860ea
--- /dev/null
+++ b/drivers/block/dwc_ahsata.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Terry Lv <r65388@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_SATA_H__
+#define __FSL_SATA_H__
+
+#define DWC_AHSATA_MAX_CMD_SLOTS 32
+
+/* Max host controller numbers */
+#define SATA_HC_MAX_NUM 4
+/* Max command queue depth per host controller */
+#define DWC_AHSATA_HC_MAX_CMD 32
+/* Max port number per host controller */
+#define SATA_HC_MAX_PORT 16
+
+/* Generic Host Register */
+
+/* HBA Capabilities Register */
+#define SATA_HOST_CAP_S64A 0x80000000
+#define SATA_HOST_CAP_SNCQ 0x40000000
+#define SATA_HOST_CAP_SSNTF 0x20000000
+#define SATA_HOST_CAP_SMPS 0x10000000
+#define SATA_HOST_CAP_SSS 0x08000000
+#define SATA_HOST_CAP_SALP 0x04000000
+#define SATA_HOST_CAP_SAL 0x02000000
+#define SATA_HOST_CAP_SCLO 0x01000000
+#define SATA_HOST_CAP_ISS_MASK 0x00f00000
+#define SATA_HOST_CAP_ISS_OFFSET 20
+#define SATA_HOST_CAP_SNZO 0x00080000
+#define SATA_HOST_CAP_SAM 0x00040000
+#define SATA_HOST_CAP_SPM 0x00020000
+#define SATA_HOST_CAP_PMD 0x00008000
+#define SATA_HOST_CAP_SSC 0x00004000
+#define SATA_HOST_CAP_PSC 0x00002000
+#define SATA_HOST_CAP_NCS 0x00001f00
+#define SATA_HOST_CAP_CCCS 0x00000080
+#define SATA_HOST_CAP_EMS 0x00000040
+#define SATA_HOST_CAP_SXS 0x00000020
+#define SATA_HOST_CAP_NP_MASK 0x0000001f
+
+/* Global HBA Control Register */
+#define SATA_HOST_GHC_AE 0x80000000
+#define SATA_HOST_GHC_IE 0x00000002
+#define SATA_HOST_GHC_HR 0x00000001
+
+/* Interrupt Status Register */
+
+/* Ports Implemented Register */
+
+/* AHCI Version Register */
+#define SATA_HOST_VS_MJR_MASK 0xffff0000
+#define SATA_HOST_VS_MJR_OFFSET 16
+#define SATA_HOST_VS_MJR_MNR 0x0000ffff
+
+/* Command Completion Coalescing Control */
+#define SATA_HOST_CCC_CTL_TV_MASK 0xffff0000
+#define SATA_HOST_CCC_CTL_TV_OFFSET 16
+#define SATA_HOST_CCC_CTL_CC_MASK 0x0000ff00
+#define SATA_HOST_CCC_CTL_CC_OFFSET 8
+#define SATA_HOST_CCC_CTL_INT_MASK 0x000000f8
+#define SATA_HOST_CCC_CTL_INT_OFFSET 3
+#define SATA_HOST_CCC_CTL_EN 0x00000001
+
+/* Command Completion Coalescing Ports */
+
+/* HBA Capabilities Extended Register */
+#define SATA_HOST_CAP2_APST 0x00000004
+
+/* BIST Activate FIS Register */
+#define SATA_HOST_BISTAFR_NCP_MASK 0x0000ff00
+#define SATA_HOST_BISTAFR_NCP_OFFSET 8
+#define SATA_HOST_BISTAFR_PD_MASK 0x000000ff
+#define SATA_HOST_BISTAFR_PD_OFFSET 0
+
+/* BIST Control Register */
+#define SATA_HOST_BISTCR_FERLB 0x00100000
+#define SATA_HOST_BISTCR_TXO 0x00040000
+#define SATA_HOST_BISTCR_CNTCLR 0x00020000
+#define SATA_HOST_BISTCR_NEALB 0x00010000
+#define SATA_HOST_BISTCR_LLC_MASK 0x00000700
+#define SATA_HOST_BISTCR_LLC_OFFSET 8
+#define SATA_HOST_BISTCR_ERREN 0x00000040
+#define SATA_HOST_BISTCR_FLIP 0x00000020
+#define SATA_HOST_BISTCR_PV 0x00000010
+#define SATA_HOST_BISTCR_PATTERN_MASK 0x0000000f
+#define SATA_HOST_BISTCR_PATTERN_OFFSET 0
+
+/* BIST FIS Count Register */
+
+/* BIST Status Register */
+#define SATA_HOST_BISTSR_FRAMERR_MASK 0x0000ffff
+#define SATA_HOST_BISTSR_FRAMERR_OFFSET 0
+#define SATA_HOST_BISTSR_BRSTERR_MASK 0x00ff0000
+#define SATA_HOST_BISTSR_BRSTERR_OFFSET 16
+
+/* BIST DWORD Error Count Register */
+
+/* OOB Register*/
+#define SATA_HOST_OOBR_WE 0x80000000
+#define SATA_HOST_OOBR_cwMin_MASK 0x7f000000
+#define SATA_HOST_OOBR_cwMAX_MASK 0x00ff0000
+#define SATA_HOST_OOBR_ciMin_MASK 0x0000ff00
+#define SATA_HOST_OOBR_ciMax_MASK 0x000000ff
+
+/* Timer 1-ms Register */
+
+/* Global Parameter 1 Register */
+#define SATA_HOST_GPARAM1R_ALIGN_M 0x80000000
+#define SATA_HOST_GPARAM1R_RX_BUFFER 0x40000000
+#define SATA_HOST_GPARAM1R_PHY_DATA_MASK 0x30000000
+#define SATA_HOST_GPARAM1R_PHY_RST 0x08000000
+#define SATA_HOST_GPARAM1R_PHY_CTRL_MASK 0x07e00000
+#define SATA_HOST_GPARAM1R_PHY_STAT_MASK 0x001f8000
+#define SATA_HOST_GPARAM1R_LATCH_M 0x00004000
+#define SATA_HOST_GPARAM1R_BIST_M 0x00002000
+#define SATA_HOST_GPARAM1R_PHY_TYPE 0x00001000
+#define SATA_HOST_GPARAM1R_RETURN_ERR 0x00000400
+#define SATA_HOST_GPARAM1R_AHB_ENDIAN_MASK 0x00000300
+#define SATA_HOST_GPARAM1R_S_HADDR 0X00000080
+#define SATA_HOST_GPARAM1R_M_HADDR 0X00000040
+
+/* Global Parameter 2 Register */
+#define SATA_HOST_GPARAM2R_DEV_CP 0x00004000
+#define SATA_HOST_GPARAM2R_DEV_MP 0x00002000
+#define SATA_HOST_GPARAM2R_DEV_ENCODE_M 0x00001000
+#define SATA_HOST_GPARAM2R_RXOOB_CLK_M 0x00000800
+#define SATA_HOST_GPARAM2R_RXOOB_M 0x00000400
+#define SATA_HOST_GPARAM2R_TX_OOB_M 0x00000200
+#define SATA_HOST_GPARAM2R_RXOOB_CLK_MASK 0x000001ff
+
+/* Port Parameter Register */
+#define SATA_HOST_PPARAMR_TX_MEM_M 0x00000200
+#define SATA_HOST_PPARAMR_TX_MEM_S 0x00000100
+#define SATA_HOST_PPARAMR_RX_MEM_M 0x00000080
+#define SATA_HOST_PPARAMR_RX_MEM_S 0x00000040
+#define SATA_HOST_PPARAMR_TXFIFO_DEPTH_MASK 0x00000038
+#define SATA_HOST_PPARAMR_RXFIFO_DEPTH_MASK 0x00000007
+
+/* Test Register */
+#define SATA_HOST_TESTR_PSEL_MASK 0x00070000
+#define SATA_HOST_TESTR_TEST_IF 0x00000001
+
+/* Port Register Descriptions */
+/* Port# Command List Base Address Register */
+#define SATA_PORT_CLB_CLB_MASK 0xfffffc00
+
+/* Port# Command List Base Address Upper 32-Bits Register */
+
+/* Port# FIS Base Address Register */
+#define SATA_PORT_FB_FB_MASK 0xfffffff0
+
+/* Port# FIS Base Address Upper 32-Bits Register */
+
+/* Port# Interrupt Status Register */
+#define SATA_PORT_IS_CPDS 0x80000000
+#define SATA_PORT_IS_TFES 0x40000000
+#define SATA_PORT_IS_HBFS 0x20000000
+#define SATA_PORT_IS_HBDS 0x10000000
+#define SATA_PORT_IS_IFS 0x08000000
+#define SATA_PORT_IS_INFS 0x04000000
+#define SATA_PORT_IS_OFS 0x01000000
+#define SATA_PORT_IS_IPMS 0x00800000
+#define SATA_PORT_IS_PRCS 0x00400000
+#define SATA_PORT_IS_DMPS 0x00000080
+#define SATA_PORT_IS_PCS 0x00000040
+#define SATA_PORT_IS_DPS 0x00000020
+#define SATA_PORT_IS_UFS 0x00000010
+#define SATA_PORT_IS_SDBS 0x00000008
+#define SATA_PORT_IS_DSS 0x00000004
+#define SATA_PORT_IS_PSS 0x00000002
+#define SATA_PORT_IS_DHRS 0x00000001
+
+/* Port# Interrupt Enable Register */
+#define SATA_PORT_IE_CPDE 0x80000000
+#define SATA_PORT_IE_TFEE 0x40000000
+#define SATA_PORT_IE_HBFE 0x20000000
+#define SATA_PORT_IE_HBDE 0x10000000
+#define SATA_PORT_IE_IFE 0x08000000
+#define SATA_PORT_IE_INFE 0x04000000
+#define SATA_PORT_IE_OFE 0x01000000
+#define SATA_PORT_IE_IPME 0x00800000
+#define SATA_PORT_IE_PRCE 0x00400000
+#define SATA_PORT_IE_DMPE 0x00000080
+#define SATA_PORT_IE_PCE 0x00000040
+#define SATA_PORT_IE_DPE 0x00000020
+#define SATA_PORT_IE_UFE 0x00000010
+#define SATA_PORT_IE_SDBE 0x00000008
+#define SATA_PORT_IE_DSE 0x00000004
+#define SATA_PORT_IE_PSE 0x00000002
+#define SATA_PORT_IE_DHRE 0x00000001
+
+/* Port# Command Register */
+#define SATA_PORT_CMD_ICC_MASK 0xf0000000
+#define SATA_PORT_CMD_ASP 0x08000000
+#define SATA_PORT_CMD_ALPE 0x04000000
+#define SATA_PORT_CMD_DLAE 0x02000000
+#define SATA_PORT_CMD_ATAPI 0x01000000
+#define SATA_PORT_CMD_APSTE 0x00800000
+#define SATA_PORT_CMD_ESP 0x00200000
+#define SATA_PORT_CMD_CPD 0x00100000
+#define SATA_PORT_CMD_MPSP 0x00080000
+#define SATA_PORT_CMD_HPCP 0x00040000
+#define SATA_PORT_CMD_PMA 0x00020000
+#define SATA_PORT_CMD_CPS 0x00010000
+#define SATA_PORT_CMD_CR 0x00008000
+#define SATA_PORT_CMD_FR 0x00004000
+#define SATA_PORT_CMD_MPSS 0x00002000
+#define SATA_PORT_CMD_CCS_MASK 0x00001f00
+#define SATA_PORT_CMD_FRE 0x00000010
+#define SATA_PORT_CMD_CLO 0x00000008
+#define SATA_PORT_CMD_POD 0x00000004
+#define SATA_PORT_CMD_SUD 0x00000002
+#define SATA_PORT_CMD_ST 0x00000001
+
+/* Port# Task File Data Register */
+#define SATA_PORT_TFD_ERR_MASK 0x0000ff00
+#define SATA_PORT_TFD_STS_MASK 0x000000ff
+#define SATA_PORT_TFD_STS_ERR 0x00000001
+#define SATA_PORT_TFD_STS_DRQ 0x00000008
+#define SATA_PORT_TFD_STS_BSY 0x00000080
+
+/* Port# Signature Register */
+
+/* Port# Serial ATA Status {SStatus} Register */
+#define SATA_PORT_SSTS_IPM_MASK 0x00000f00
+#define SATA_PORT_SSTS_SPD_MASK 0x000000f0
+#define SATA_PORT_SSTS_DET_MASK 0x0000000f
+
+/* Port# Serial ATA Control {SControl} Register */
+#define SATA_PORT_SCTL_IPM_MASK 0x00000f00
+#define SATA_PORT_SCTL_SPD_MASK 0x000000f0
+#define SATA_PORT_SCTL_DET_MASK 0x0000000f
+
+/* Port# Serial ATA Error {SError} Register */
+#define SATA_PORT_SERR_DIAG_X 0x04000000
+#define SATA_PORT_SERR_DIAG_F 0x02000000
+#define SATA_PORT_SERR_DIAG_T 0x01000000
+#define SATA_PORT_SERR_DIAG_S 0x00800000
+#define SATA_PORT_SERR_DIAG_H 0x00400000
+#define SATA_PORT_SERR_DIAG_C 0x00200000
+#define SATA_PORT_SERR_DIAG_D 0x00100000
+#define SATA_PORT_SERR_DIAG_B 0x00080000
+#define SATA_PORT_SERR_DIAG_W 0x00040000
+#define SATA_PORT_SERR_DIAG_I 0x00020000
+#define SATA_PORT_SERR_DIAG_N 0x00010000
+#define SATA_PORT_SERR_ERR_E 0x00000800
+#define SATA_PORT_SERR_ERR_P 0x00000400
+#define SATA_PORT_SERR_ERR_C 0x00000200
+#define SATA_PORT_SERR_ERR_T 0x00000100
+#define SATA_PORT_SERR_ERR_M 0x00000002
+#define SATA_PORT_SERR_ERR_I 0x00000001
+
+/* Port# Serial ATA Active {SActive} Register */
+
+/* Port# Command Issue Register */
+
+/* Port# Serial ATA Notification Register */
+
+/* Port# DMA Control Register */
+#define SATA_PORT_DMACR_RXABL_MASK 0x0000f000
+#define SATA_PORT_DMACR_TXABL_MASK 0x00000f00
+#define SATA_PORT_DMACR_RXTS_MASK 0x000000f0
+#define SATA_PORT_DMACR_TXTS_MASK 0x0000000f
+
+/* Port# PHY Control Register */
+
+/* Port# PHY Status Register */
+
+#define SATA_HC_CMD_HDR_ENTRY_SIZE sizeof(struct cmd_hdr_entry)
+
+/* DW0
+*/
+#define CMD_HDR_DI_CFL_MASK 0x0000001f
+#define CMD_HDR_DI_CFL_OFFSET 0
+#define CMD_HDR_DI_A 0x00000020
+#define CMD_HDR_DI_W 0x00000040
+#define CMD_HDR_DI_P 0x00000080
+#define CMD_HDR_DI_R 0x00000100
+#define CMD_HDR_DI_B 0x00000200
+#define CMD_HDR_DI_C 0x00000400
+#define CMD_HDR_DI_PMP_MASK 0x0000f000
+#define CMD_HDR_DI_PMP_OFFSET 12
+#define CMD_HDR_DI_PRDTL 0xffff0000
+#define CMD_HDR_DI_PRDTL_OFFSET 16
+
+/* prde_fis_len
+*/
+#define CMD_HDR_PRD_ENTRY_SHIFT 16
+#define CMD_HDR_PRD_ENTRY_MASK 0x003f0000
+#define CMD_HDR_FIS_LEN_SHIFT 2
+
+/* attribute
+*/
+#define CMD_HDR_ATTR_RES 0x00000800 /* Reserved bit, should be 1 */
+#define CMD_HDR_ATTR_VBIST 0x00000400 /* Vendor BIST */
+/* Snoop enable for all descriptor */
+#define CMD_HDR_ATTR_SNOOP 0x00000200
+#define CMD_HDR_ATTR_FPDMA 0x00000100 /* FPDMA queued command */
+#define CMD_HDR_ATTR_RESET 0x00000080 /* Reset - a SRST or device reset */
+/* BIST - require the host to enter BIST mode */
+#define CMD_HDR_ATTR_BIST 0x00000040
+#define CMD_HDR_ATTR_ATAPI 0x00000020 /* ATAPI command */
+#define CMD_HDR_ATTR_TAG 0x0000001f /* TAG mask */
+
+#define FLAGS_DMA 0x00000000
+#define FLAGS_FPDMA 0x00000001
+
+#define SATA_FLAG_Q_DEP_MASK 0x0000000f
+#define SATA_FLAG_WCACHE 0x00000100
+#define SATA_FLAG_FLUSH 0x00000200
+#define SATA_FLAG_FLUSH_EXT 0x00000400
+
+#define READ_CMD 0
+#define WRITE_CMD 1
+
+extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
+
+#endif /* __FSL_SATA_H__ */
diff --git a/include/ahci.h b/include/ahci.h
index 465ea7f..c4fb9e7 100644
--- a/include/ahci.h
+++ b/include/ahci.h
@@ -30,12 +30,13 @@
#define AHCI_PCI_BAR 0x24
#define AHCI_MAX_SG 56 /* hardware max is 64K */
#define AHCI_CMD_SLOT_SZ 32
+#define AHCI_MAX_CMD_SLOT 32
#define AHCI_RX_FIS_SZ 256
#define AHCI_CMD_TBL_HDR 0x80
#define AHCI_CMD_TBL_CDB 0x40
#define AHCI_CMD_TBL_SZ AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16)
-#define AHCI_PORT_PRIV_DMA_SZ AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ \
- + AHCI_RX_FIS_SZ
+#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ * AHCI_MAX_CMD_SLOT + \
+ AHCI_CMD_TBL_SZ + AHCI_RX_FIS_SZ)
#define AHCI_CMD_ATAPI (1 << 5)
#define AHCI_CMD_WRITE (1 << 6)
#define AHCI_CMD_PREFETCH (1 << 7)
--
1.7.5.4
^ permalink raw reply related [flat|nested] 15+ messages in thread* [U-Boot] [PATCH 8/9] MX53: Add support to ESG ima3 board
2012-02-22 10:24 [U-Boot] [PATCH 1/9] Define UART4 and UART5 base addresses Stefano Babic
` (5 preceding siblings ...)
2012-02-22 10:24 ` [U-Boot] [PATCH 7/9] SATA: add driver for MX5 / MX6 SOCs Stefano Babic
@ 2012-02-22 10:24 ` Stefano Babic
2012-02-22 10:30 ` Dirk Behme
2012-02-22 10:24 ` [U-Boot] [PATCH 9/9] MX53: mx53loco: Add SATA support Stefano Babic
7 siblings, 1 reply; 15+ messages in thread
From: Stefano Babic @ 2012-02-22 10:24 UTC (permalink / raw)
To: u-boot
The ESG ima3-mx53 board is based on the Freescale
i.MX53 SOC. It boots from NOR (128 MB) and
supports Ethernet (FEC), SATA.
Signed-off-by: Stefano Babic <sbabic@denx.de>
---
board/esg/ima3-mx53/Makefile | 41 +++++
board/esg/ima3-mx53/ima3-mx53.c | 302 ++++++++++++++++++++++++++++++++++++++
board/esg/ima3-mx53/imximage.cfg | 108 ++++++++++++++
boards.cfg | 1 +
include/configs/ima3-mx53.h | 269 +++++++++++++++++++++++++++++++++
5 files changed, 721 insertions(+), 0 deletions(-)
create mode 100644 board/esg/ima3-mx53/Makefile
create mode 100644 board/esg/ima3-mx53/ima3-mx53.c
create mode 100644 board/esg/ima3-mx53/imximage.cfg
create mode 100644 include/configs/ima3-mx53.h
diff --git a/board/esg/ima3-mx53/Makefile b/board/esg/ima3-mx53/Makefile
new file mode 100644
index 0000000..f3b13bc
--- /dev/null
+++ b/board/esg/ima3-mx53/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2012, Stefano Babic <sbabic@denx.de>
+#
+# Based on ti/evm/Makefile
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).o
+
+COBJS := ima3-mx53.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/esg/ima3-mx53/ima3-mx53.c b/board/esg/ima3-mx53/ima3-mx53.c
new file mode 100644
index 0000000..9ecf31d
--- /dev/null
+++ b/board/esg/ima3-mx53/ima3-mx53.c
@@ -0,0 +1,302 @@
+/*
+ * (C) Copyright 2012, Stefano Babic <sbabic@denx.de>
+ *
+ * (C) Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/mx5x_pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/errno.h>
+#include <netdev.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <asm/gpio.h>
+
+/* NOR flash configuration */
+#define IMA3_MX53_CS0GCR1 (CSEN | DSZ(2))
+#define IMA3_MX53_CS0GCR2 0
+#define IMA3_MX53_CS0RCR1 (RCSN(2) | OEN(1) | RWSC(15))
+#define IMA3_MX53_CS0RCR2 0
+#define IMA3_MX53_CS0WCR1 (WBED1 | WCSN(2) | WEN(1) | WWSC(15))
+#define IMA3_MX53_CS0WCR2 0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void weim_nor_settings(void)
+{
+ struct weim *weim_regs = (struct weim *)WEIM_BASE_ADDR;
+
+ writel(IMA3_MX53_CS0GCR1, &weim_regs->cs0gcr1);
+ writel(IMA3_MX53_CS0GCR2, &weim_regs->cs0gcr2);
+ writel(IMA3_MX53_CS0RCR1, &weim_regs->cs0rcr1);
+ writel(IMA3_MX53_CS0RCR2, &weim_regs->cs0rcr2);
+ writel(IMA3_MX53_CS0WCR1, &weim_regs->cs0wcr1);
+ writel(IMA3_MX53_CS0WCR2, &weim_regs->cs0wcr2);
+ writel(0x0, &weim_regs->wcr);
+
+ set_chipselect_size(CS0_128);
+}
+
+int dram_init(void)
+{
+ gd->ram_size = get_ram_size((void *) CONFIG_SYS_SDRAM_BASE,
+ PHYS_SDRAM_1_SIZE);
+ return 0;
+}
+
+static void setup_iomux_uart(void)
+{
+ /* UART4 RXD */
+ mxc_request_iomux(MX53_PIN_CSI0_D13, IOMUX_CONFIG_ALT2);
+ mxc_iomux_set_pad(MX53_PIN_CSI0_D13,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_PUE_PULL | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE |
+ PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_ENABLE);
+ mxc_iomux_set_input(MX53_UART4_IPP_UART_RXD_MUX_SELECT_INPUT, 0x3);
+
+ /* UART4 TXD */
+ mxc_request_iomux(MX53_PIN_CSI0_D12, IOMUX_CONFIG_ALT2);
+ mxc_iomux_set_pad(MX53_PIN_CSI0_D12,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_PUE_PULL | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE |
+ PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_ENABLE);
+}
+
+static void setup_iomux_fec(void)
+{
+ /*FEC_MDIO*/
+ mxc_request_iomux(MX53_PIN_FEC_MDIO, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_MDIO,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_PUE_PULL | PAD_CTL_PKE_ENABLE | PAD_CTL_22K_PU |
+ PAD_CTL_ODE_OPENDRAIN_ENABLE);
+ mxc_iomux_set_input(MX53_FEC_FEC_MDI_SELECT_INPUT, 0x1);
+
+ /*FEC_MDC*/
+ mxc_request_iomux(MX53_PIN_FEC_MDC, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_MDC, PAD_CTL_DRV_HIGH);
+
+ /* FEC RXD3 */
+ mxc_request_iomux(MX53_PIN_KEY_COL0, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_KEY_COL0, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC RXD2 */
+ mxc_request_iomux(MX53_PIN_KEY_COL2, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_KEY_COL2, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC RXD1 */
+ mxc_request_iomux(MX53_PIN_FEC_RXD1, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_RXD1, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC RXD0 */
+ mxc_request_iomux(MX53_PIN_FEC_RXD0, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_RXD0, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC TXD3 */
+ mxc_request_iomux(MX53_PIN_GPIO_19, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_GPIO_19, PAD_CTL_DRV_HIGH);
+
+ /* FEC TXD2 */
+ mxc_request_iomux(MX53_PIN_KEY_ROW2, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_KEY_ROW2, PAD_CTL_DRV_HIGH);
+
+ /* FEC TXD1 */
+ mxc_request_iomux(MX53_PIN_FEC_TXD1, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_TXD1, PAD_CTL_DRV_HIGH);
+
+ /* FEC TXD0 */
+ mxc_request_iomux(MX53_PIN_FEC_TXD0, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_TXD0, PAD_CTL_DRV_HIGH);
+
+ /* FEC TX_EN */
+ mxc_request_iomux(MX53_PIN_FEC_TX_EN, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_TX_EN, PAD_CTL_DRV_HIGH);
+
+ /* FEC TX_CLK */
+ mxc_request_iomux(MX53_PIN_FEC_REF_CLK, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_REF_CLK, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC RX_ER */
+ mxc_request_iomux(MX53_PIN_FEC_RX_ER, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_RX_ER, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC RX_DV */
+ mxc_request_iomux(MX53_PIN_FEC_CRS_DV, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX53_PIN_FEC_CRS_DV, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC CRS */
+ mxc_request_iomux(MX53_PIN_KEY_COL3, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_KEY_COL3, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+
+ /* FEC COL */
+ mxc_request_iomux(MX53_PIN_KEY_ROW1, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_KEY_ROW1, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+ mxc_iomux_set_input(MX53_FEC_FEC_COL_SELECT_INPUT, 0x0);
+
+ /* FEC RX_CLK */
+ mxc_request_iomux(MX53_PIN_KEY_COL1, IOMUX_CONFIG_ALT6);
+ mxc_iomux_set_pad(MX53_PIN_KEY_COL1, PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE);
+ mxc_iomux_set_input(MX53_FEC_FEC_RX_CLK_SELECT_INPUT, 0x0);
+}
+
+#ifdef CONFIG_FSL_ESDHC
+struct fsl_esdhc_cfg esdhc_cfg = { MMC_SDHC1_BASE_ADDR, 1 };
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+ int ret;
+
+ ret = !gpio_get_value(IOMUX_TO_GPIO(MX53_PIN_GPIO_1));
+
+ return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+ mxc_request_iomux(MX53_PIN_SD1_CMD, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_SD1_CLK, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_SD1_DATA0, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_SD1_DATA1, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_SD1_DATA2, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_SD1_DATA3, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_GPIO_1, IOMUX_CONFIG_ALT1);
+ mxc_iomux_set_pad(MX53_PIN_GPIO_1,
+ PAD_CTL_DRV_HIGH | PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_100K_PU |
+ PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE);
+ gpio_direction_input(IOMUX_TO_GPIO(MX53_PIN_GPIO_1));
+
+ mxc_iomux_set_pad(MX53_PIN_SD1_CMD,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU);
+ mxc_iomux_set_pad(MX53_PIN_SD1_CLK,
+ PAD_CTL_PUE_PULL | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE |
+ PAD_CTL_47K_PU | PAD_CTL_DRV_HIGH);
+ mxc_iomux_set_pad(MX53_PIN_SD1_DATA0,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ mxc_iomux_set_pad(MX53_PIN_SD1_DATA1,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ mxc_iomux_set_pad(MX53_PIN_SD1_DATA2,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ mxc_iomux_set_pad(MX53_PIN_SD1_DATA3,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+
+ return fsl_esdhc_initialize(bis, &esdhc_cfg);
+}
+#endif
+
+static void setup_iomux_spi(void)
+{
+ /* SCLK */
+ mxc_request_iomux(MX53_PIN_CSI0_D8, IOMUX_CONFIG_ALT3);
+ mxc_iomux_set_pad(MX53_PIN_CSI0_D8,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ mxc_iomux_set_input(MX53_ECSPI2_IPP_CSPI_CLK_IN_SELECT_INPUT, 0x1);
+ /* MOSI */
+ mxc_request_iomux(MX53_PIN_CSI0_D9, IOMUX_CONFIG_ALT3);
+ mxc_iomux_set_pad(MX53_PIN_CSI0_D9,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ mxc_iomux_set_input(MX53_ECSPI2_IPP_IND_MOSI_SELECT_INPUT, 0x1);
+ /* MISO */
+ mxc_request_iomux(MX53_PIN_CSI0_D10, IOMUX_CONFIG_ALT3);
+ mxc_iomux_set_pad(MX53_PIN_CSI0_D10,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ mxc_iomux_set_input(MX53_ECSPI2_IPP_IND_MISO_SELECT_INPUT, 0x1);
+ /* SSEL 0 */
+ mxc_request_iomux(MX53_PIN_CSI0_D11, IOMUX_CONFIG_GPIO);
+ mxc_iomux_set_pad(MX53_PIN_CSI0_D11,
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU);
+ gpio_direction_output(IOMUX_TO_GPIO(MX53_PIN_CSI0_D11), 1);
+}
+
+int board_early_init_f(void)
+{
+ /* configure I/O pads */
+ setup_iomux_uart();
+ setup_iomux_fec();
+
+ weim_nor_settings();
+
+ /* configure spi */
+ setup_iomux_spi();
+
+ return 0;
+}
+
+int board_init(void)
+{
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+ mxc_set_sata_internal_clock();
+
+ return 0;
+}
+
+#if defined(CONFIG_RESET_PHY_R)
+#include <miiphy.h>
+
+void reset_phy(void)
+{
+ unsigned short reg;
+
+ /* reset the phy */
+ miiphy_reset("FEC", CONFIG_PHY_ADDR);
+
+ /* set hard link to 100Mbit, full-duplex */
+ miiphy_read("FEC", CONFIG_PHY_ADDR, MII_BMCR, ®);
+ reg &= ~BMCR_ANENABLE;
+ reg |= (BMCR_SPEED100 | BMCR_FULLDPLX);
+ miiphy_write("FEC", CONFIG_PHY_ADDR, MII_BMCR, reg);
+
+ miiphy_read("FEC", CONFIG_PHY_ADDR, 0x16, ®);
+ reg |= (1 << 5);
+ miiphy_write("FEC", CONFIG_PHY_ADDR, 0x16, reg);
+}
+#endif
+
+int checkboard(void)
+{
+ puts("Board: IMA3_MX53\n");
+
+ return 0;
+}
diff --git a/board/esg/ima3-mx53/imximage.cfg b/board/esg/ima3-mx53/imximage.cfg
new file mode 100644
index 0000000..fa6b42d
--- /dev/null
+++ b/board/esg/ima3-mx53/imximage.cfg
@@ -0,0 +1,108 @@
+#
+# (C) Copyright 2012
+# Stefano Babic DENX Software Engineering sbabic at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation Inc. 51 Franklin Street Fifth Floor Boston,
+# MA 02110-1301 USA
+#
+# Refer docs/README.imxmage for more details about how-to configure
+# and create imximage boot image
+#
+# The syntax is taken as close as possible with the kwbimage
+
+# image version
+
+IMAGE_VERSION 2
+
+# Boot Device : one of
+# spi, sd (the board has no nand neither onenand)
+
+BOOT_FROM nor
+
+# Device Configuration Data (DCD)
+#
+# Each entry must have the format:
+# Addr-type Address Value
+#
+# where:
+# Addr-type register length (1,2 or 4 bytes)
+# Address absolute address of the register
+# value value to be stored in the register
+
+# IOMUX for RAM only
+DATA 4 0x53fa8554 0x300020
+DATA 4 0x53fa8560 0x300020
+DATA 4 0x53fa8594 0x300020
+DATA 4 0x53fa8584 0x300020
+DATA 4 0x53fa8558 0x300040
+DATA 4 0x53fa8568 0x300040
+DATA 4 0x53fa8590 0x300040
+DATA 4 0x53fa857c 0x300040
+DATA 4 0x53fa8564 0x300040
+DATA 4 0x53fa8580 0x300040
+DATA 4 0x53fa8570 0x300220
+DATA 4 0x53fa8578 0x300220
+DATA 4 0x53fa872c 0x300000
+DATA 4 0x53fa8728 0x300000
+DATA 4 0x53fa871c 0x300000
+DATA 4 0x53fa8718 0x300000
+DATA 4 0x53fa8574 0x300020
+DATA 4 0x53fa8588 0x300020
+DATA 4 0x53fa855c 0x0
+DATA 4 0x53fa858c 0x0
+DATA 4 0x53fa856c 0x300040
+DATA 4 0x53fa86f0 0x300000
+DATA 4 0x53fa8720 0x300000
+DATA 4 0x53fa86fc 0x0
+DATA 4 0x53fa86f4 0x0
+DATA 4 0x53fa8714 0x0
+DATA 4 0x53fa8724 0x4000000
+#
+# DDR RAM
+DATA 4 0x63fd9088 0x40404040
+DATA 4 0x63fd9090 0x40404040
+DATA 4 0x63fd907C 0x01420143
+DATA 4 0x63fd9080 0x01450146
+DATA 4 0x63fd9018 0x00111740
+DATA 4 0x63fd9000 0x84190000
+# esdcfgX
+DATA 4 0x63fd900C 0x9f5152e3
+DATA 4 0x63fd9010 0xb68e8a63
+DATA 4 0x63fd9014 0x01ff00db
+# Read/Write command delay
+DATA 4 0x63fd902c 0x000026d2
+# Out of reset delays
+DATA 4 0x63fd9030 0x00ff0e21
+# ESDCTL ODT timing control
+DATA 4 0x63fd9008 0x12273030
+# ESDCTL power down control
+DATA 4 0x63fd9004 0x0002002d
+# Set registers in DDR memory chips
+DATA 4 0x63fd901c 0x00008032
+DATA 4 0x63fd901c 0x00008033
+DATA 4 0x63fd901c 0x00028031
+DATA 4 0x63fd901c 0x052080b0
+DATA 4 0x63fd901c 0x04008040
+# ESDCTL refresh control
+DATA 4 0x63fd9020 0x00005800
+# PHY ZQ HW control
+DATA 4 0x63fd9040 0x05380003
+# PHY ODT control
+DATA 4 0x63fd9058 0x00022222
+# start DDR3
+DATA 4 0x63fd901c 0x00000000
diff --git a/boards.cfg b/boards.cfg
index bf71a66..b9fc69a 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -197,6 +197,7 @@ mx53ard arm armv7 mx53ard freesca
mx53evk arm armv7 mx53evk freescale mx5 mx53evk:IMX_CONFIG=board/freescale/mx53evk/imximage.cfg
mx53loco arm armv7 mx53loco freescale mx5 mx53loco:IMX_CONFIG=board/freescale/mx53loco/imximage.cfg
mx53smd arm armv7 mx53smd freescale mx5 mx53smd:IMX_CONFIG=board/freescale/mx53smd/imximage.cfg
+ima3-mx53 arm armv7 ima3-mx53 esg mx5 ima3-mx53:IMX_CONFIG=board/esg/ima3-mx53/imximage.cfg
vision2 arm armv7 vision2 ttcontrol mx5 vision2:IMX_CONFIG=board/ttcontrol/vision2/imximage_hynix.cfg
mx6qarm2 arm armv7 mx6qarm2 freescale mx6 mx6qarm2:IMX_CONFIG=board/freescale/mx6qarm2/imximage.cfg
mx6qsabrelite arm armv7 mx6qsabrelite freescale mx6 mx6qsabrelite:IMX_CONFIG=board/freescale/mx6qsabrelite/imximage.cfg
diff --git a/include/configs/ima3-mx53.h b/include/configs/ima3-mx53.h
new file mode 100644
index 0000000..ea48d64
--- /dev/null
+++ b/include/configs/ima3-mx53.h
@@ -0,0 +1,269 @@
+/*
+ * (C) Copyright 2012, Stefano Babic <sbabic@denx.de>
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * Configuration settings for the MX53-EVK Freescale board.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/* SOC type must be included before imx-regs.h */
+#define CONFIG_MX53
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/mx5x_pins.h>
+
+#define CONFIG_SYS_MX5_HCLK 24000000
+#define CONFIG_SYS_MX5_CLK32 32768
+
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+
+#define CONFIG_OF_LIBFDT
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2 * 1024 * 1024)
+
+#define CONFIG_BOARD_EARLY_INIT_F
+
+/* Enable GPIOs */
+#define CONFIG_MXC_GPIO
+
+/* UART */
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE UART4_BASE_ADDR
+
+/* MMC */
+#define CONFIG_FSL_ESDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR 0
+#define CONFIG_SYS_FSL_ESDHC_NUM 1
+
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_DOS_PARTITION
+
+/* Ethernet on FEC */
+#define CONFIG_NET_MULTI
+#define CONFIG_MII
+#define CONFIG_DISCOVER_PHY
+
+#define CONFIG_FEC_MXC
+#define IMX_FEC_BASE FEC_BASE_ADDR
+#define CONFIG_FEC_MXC_PHYADDR 0x01
+#define CONFIG_PHY_ADDR CONFIG_FEC_MXC_PHYADDR
+#define CONFIG_RESET_PHY_R
+#define CONFIG_FEC_MXC_NO_ANEG
+#define CONFIG_PRIME "FEC0"
+
+/* SPI */
+#define CONFIG_HARD_SPI
+#define CONFIG_MXC_SPI
+#define CONFIG_DEFAULT_SPI_BUS 1
+#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0
+
+/* SPI FLASH - not used for environment */
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_CS (IOMUX_TO_GPIO(MX53_PIN_CSI0_D11) \
+ << 8) | 0
+#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED 25000000
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_CONS_INDEX 1
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200}
+
+/* Command definition */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_GPIO
+
+#define CONFIG_BOOTDELAY 3
+
+#define CONFIG_LOADADDR 0x70800000 /* loadaddr env var */
+#define CONFIG_SYS_TEXT_BASE 0xf0001400 /* uboot in nor flash */
+
+#define CONFIG_ARP_TIMEOUT 200UL
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+#define CONFIG_SYS_PROMPT "IMA3 MX53 U-Boot > "
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
+
+#define CONFIG_SYS_MEMTEST_START 0x70000000
+#define CONFIG_SYS_MEMTEST_END 0x10000
+
+#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
+
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_CMDLINE_EDITING
+
+/* Stack sizes */
+#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS 1
+#define PHYS_SDRAM_1 CSD0_BASE_ADDR
+#define PHYS_SDRAM_1_SIZE (1024 * 1024 * 1024)
+
+#define CONFIG_SYS_SDRAM_BASE (PHYS_SDRAM_1)
+#define CONFIG_SYS_INIT_RAM_ADDR (IRAM_BASE_ADDR)
+#define CONFIG_SYS_INIT_RAM_SIZE (IRAM_SIZE)
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+ (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+ (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
+#define MTDIDS_DEFAULT "nor0=f0000000.flash"
+
+/* FLASH and environment organization */
+
+#define CONFIG_SYS_FLASH_BASE 0xF0000000
+#define CONFIG_SYS_FLASH_CFI /* Flash is CFI conformant */
+#define CONFIG_FLASH_CFI_DRIVER /* Use the common driver */
+#define CONFIG_FLASH_CFI_MTD /* with MTD support */
+#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
+#define CONFIG_SYS_MAX_FLASH_BANKS 1
+#define CONFIG_SYS_MAX_FLASH_SECT 1024
+
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_MONITOR_LEN (512 * 1024)
+
+#define CONFIG_ENV_SIZE (8 * 1024)
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE + \
+ CONFIG_SYS_MONITOR_LEN)
+#define CONFIG_ENV_SECT_SIZE 0x20000
+#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + \
+ CONFIG_ENV_SECT_SIZE)
+#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE
+
+/*
+ * Default environment and default scripts
+ * to update uboot and load kernel
+ */
+
+#define HOSTNAME ima3-mx53
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define CONFIG_HOSTNAME ima3-mx53
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "nfsargs=setenv bootargs root=/dev/nfs rw " \
+ "nfsroot=${serverip}:${rootpath}\0" \
+ "ramargs=setenv bootargs root=/dev/ram0 rw\0" \
+ "addip_sta=setenv bootargs ${bootargs} " \
+ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
+ ":${hostname}:${netdev}:off panic=1\0" \
+ "addip_dyn=setenv bootargs ${bootargs} ip=dhcp\0" \
+ "addip=if test -n ${ipdyn};then run addip_dyn;" \
+ "else run addip_sta;fi\0" \
+ "addmtd=setenv bootargs ${bootargs} ${mtdparts}\0" \
+ "addtty=setenv bootargs ${bootargs}" \
+ " console=${console},${baudrate}\0" \
+ "addmisc=setenv bootargs ${bootargs} ${misc}\0" \
+ "console=ttymxc3\0" \
+ "loadaddr=70800000\0" \
+ "kernel_addr_r=70800000\0" \
+ "ramdisk_addr_r=71000000\0" \
+ "hostname=" xstr(CONFIG_HOSTNAME) "\0" \
+ "bootfile=" xstr(CONFIG_HOSTNAME) "/uImage\0" \
+ "ramdisk_file=" xstr(CONFIG_HOSTNAME) "/uRamdisk\0" \
+ "mmcargs=setenv bootargs root=${mmcroot} " \
+ "rootfstype=${mmcrootfstype}\0" \
+ "mmcroot=/dev/mmcblk0p3 rw\0" \
+ "mmcboot=echo Booting from mmc ...; " \
+ "run mmcargs addip addtty addmtd addmisc mmcload;" \
+ "bootm\0" \
+ "mmcload=fatload mmc ${mmcdev}:${mmcpart} " \
+ "${loadaddr} ${uimage}\0" \
+ "mmcrootfstype=ext3 rootwait\0" \
+ "flash_self=run ramargs addip addtty addmtd addmisc;" \
+ "bootm ${kernel_addr} ${ramdisk_addr}\0" \
+ "flash_nfs=run nfsargs addip addtty addmtd addmisc;" \
+ "bootm ${kernel_addr}\0" \
+ "net_nfs=tftp ${kernel_addr_r} ${bootfile}; " \
+ "run nfsargs addip addtty addmtd addmisc;" \
+ "bootm ${kernel_addr_r}\0" \
+ "net_self_load=tftp ${ramdisk_addr_r} ${ramdisk_file};" \
+ "tftp ${kernel_addr_r} ${bootfile}\0" \
+ "net_self=if run net_self_load;then " \
+ "run ramargs addip addtty addmtd addmisc;" \
+ "bootm ${kernel_addr_r} ${ramdisk_addr_r};" \
+ "else echo Images not loades;fi\0" \
+ "satargs=setenv bootargs root=/dev/sda1\0" \
+ "satafile=boot/uImage\0" \
+ "ssdboot=echo Booting from ssd ...; " \
+ "run satargs addip addtty addmtd addmisc;" \
+ "sata init;ext2load sata 0:1 ${kernel_addr_r} " \
+ "${satafile};bootm\0" \
+ "u-boot=" xstr(CONFIG_HOSTNAME) "/u-boot.imx\0" \
+ "uimage=uImage\0" \
+ "load=tftp ${loadaddr} ${u-boot}\0" \
+ "uboot_addr=0xf0001000\0" \
+ "update=protect off 0xf0000000 +60000;" \
+ "erase ${uboot_addr} +60000;" \
+ "cp.b ${loadaddr} ${uboot_addr} ${filesize}\0" \
+ "upd=if run load;then echo Updating u-boot;if run update;" \
+ "then echo U-Boot updated;" \
+ "else echo Error updating u-boot !;" \
+ "echo Board without bootloader !!;" \
+ "fi;" \
+ "else echo U-Boot not downloaded..exiting;fi\0" \
+ "bootcmd=run net_nfs\0"
+
+
+#define CONFIG_CMD_SATA
+#ifdef CONFIG_CMD_SATA
+ #define CONFIG_DWC_AHSATA
+ #define CONFIG_SYS_SATA_MAX_DEVICE 1
+ #define CONFIG_DWC_AHSATA_PORT_ID 0
+ #define CONFIG_DWC_AHSATA_BASE_ADDR SATA_BASE_ADDR
+ #define CONFIG_LBA48
+ #define CONFIG_LIBATA
+#endif
+
+#endif /* __CONFIG_H */
--
1.7.5.4
^ permalink raw reply related [flat|nested] 15+ messages in thread