Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1066768/?format=api
{ "id": 1066768, "url": "http://patchwork.ozlabs.org/api/patches/1066768/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20190327092503.44281-1-peng.ma@nxp.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20190327092503.44281-1-peng.ma@nxp.com>", "list_archive_url": null, "date": "2019-03-27T09:23:23", "name": "[U-Boot,1/4] ata: fsl_ahci: Add sata DM support for Freescale powerpc socs", "commit_ref": null, "pull_url": null, "state": "awaiting-upstream", "archived": false, "hash": "002f410d32e5894bf28b1643dbf8fdff0ea0d2cb", "submitter": { "id": 74390, "url": "http://patchwork.ozlabs.org/api/people/74390/?format=api", "name": "Peng Ma", "email": "peng.ma@nxp.com" }, "delegate": { "id": 2467, "url": "http://patchwork.ozlabs.org/api/users/2467/?format=api", "username": "prabhu_kush", "first_name": "Prabhakar", "last_name": "Kushwaha", "email": "prabhakar@freescale.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20190327092503.44281-1-peng.ma@nxp.com/mbox/", "series": [ { "id": 99439, "url": "http://patchwork.ozlabs.org/api/series/99439/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=99439", "date": "2019-03-27T09:23:23", "name": "[U-Boot,1/4] ata: fsl_ahci: Add sata DM support for Freescale powerpc socs", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/99439/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1066768/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1066768/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=nxp.com", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=nxp.com header.i=@nxp.com header.b=\"vb3+nDlU\";\n\tdkim-atps=neutral", "spf=none (sender IP is )\n\tsmtp.mailfrom=peng.ma@nxp.com; " ], "Received": [ "from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 44TjH55sn0z9sRf\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 27 Mar 2019 20:23:45 +1100 (AEDT)", "by lists.denx.de (Postfix, from userid 105)\n\tid 7FB30C21E3B; Wed, 27 Mar 2019 09:23:44 +0000 (UTC)", "from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id 68AF6C21DB6;\n\tWed, 27 Mar 2019 09:23:38 +0000 (UTC)", "by lists.denx.de (Postfix, from userid 105)\n\tid 1A4ADC21DB6; Wed, 27 Mar 2019 09:23:30 +0000 (UTC)", "from EUR04-DB3-obe.outbound.protection.outlook.com\n\t(mail-eopbgr60044.outbound.protection.outlook.com [40.107.6.44])\n\tby lists.denx.de (Postfix) with ESMTPS id 1720BC21E36\n\tfor <u-boot@lists.denx.de>; Wed, 27 Mar 2019 09:23:26 +0000 (UTC)", "from VI1PR04MB4431.eurprd04.prod.outlook.com (20.177.55.159) by\n\tVI1PR04MB3136.eurprd04.prod.outlook.com (10.170.229.22) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n\t15.20.1750.15; Wed, 27 Mar 2019 09:23:23 +0000", "from VI1PR04MB4431.eurprd04.prod.outlook.com\n\t([fe80::c44:db60:6fde:37ec]) by\n\tVI1PR04MB4431.eurprd04.prod.outlook.com\n\t([fe80::c44:db60:6fde:37ec%4]) with mapi id 15.20.1750.014;\n\tWed, 27 Mar 2019 09:23:23 +0000" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=0.0 required=5.0 tests=SPF_HELO_PASS, T_DKIM_INVALID\n\tautolearn=unavailable autolearn_force=no version=3.4.0", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n\tbh=AjrTUuemDXnNWniWaLCRqoAwJXLjpBME5Kw7XnfgpEc=;\n\tb=vb3+nDlU13mruMRd9tcPjgNQa8cy+8T6tWgL1s8aM7dgQi3DUjFUT2KEPHvzmKFYyh197OeJVxEdo1gknOPF95ieecf+7BjKYsKkTuh7qN18A9EeO3lWI0et2VP76hS5g5Mmof74b1tGRA1/QTifdb/VrBv+HgEGylAFHio8gK8=", "From": "Peng Ma <peng.ma@nxp.com>", "To": "Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>, Shengzhou Liu\n\t<shengzhou.liu@nxp.com>, Ruchika Gupta <ruchika.gupta@nxp.com>", "Thread-Topic": "[PATCH 1/4] ata: fsl_ahci: Add sata DM support for Freescale\n\tpowerpc socs", "Thread-Index": "AQHU5H65epBZ8QXorkqghs61XgAecg==", "Date": "Wed, 27 Mar 2019 09:23:23 +0000", "Message-ID": "<20190327092503.44281-1-peng.ma@nxp.com>", "Accept-Language": "zh-CN, en-US", "Content-Language": "en-US", "X-MS-Has-Attach": "", "X-MS-TNEF-Correlator": "", "x-clientproxiedby": "HK0P153CA0005.APCP153.PROD.OUTLOOK.COM\n\t(2603:1096:203:18::17) To VI1PR04MB4431.eurprd04.prod.outlook.com\n\t(2603:10a6:803:6e::31)", "authentication-results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=nxp.com", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=nxp.com header.i=@nxp.com header.b=\"vb3+nDlU\";\n\tdkim-atps=neutral", "spf=none (sender IP is )\n\tsmtp.mailfrom=peng.ma@nxp.com; " ], "x-ms-exchange-messagesentrepresentingtype": "1", "x-mailer": "git-send-email 2.17.1", "x-originating-ip": "[119.31.174.73]", "x-ms-publictraffictype": "Email", "x-ms-office365-filtering-correlation-id": "5a7be7e2-22b4-4736-b9fb-08d6b295dbef", "x-ms-office365-filtering-ht": "Tenant", "x-microsoft-antispam": "BCL:0; PCL:0;\n\tRULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(4618075)(2017052603328)(7153060)(7193020);\n\tSRVR:VI1PR04MB3136; ", "x-ms-traffictypediagnostic": "VI1PR04MB3136:", "x-ms-exchange-purlcount": "2", "x-microsoft-antispam-prvs": "<VI1PR04MB313662B3865A0CF32CFC3FB9ED580@VI1PR04MB3136.eurprd04.prod.outlook.com>", "x-forefront-prvs": "0989A7979C", "x-forefront-antispam-report": "SFV:NSPM;\n\tSFS:(10009020)(346002)(136003)(366004)(39860400002)(376002)(396003)(199004)(189003)(86362001)(6116002)(3846002)(186003)(26005)(36756003)(81166006)(81156014)(1076003)(6636002)(8676002)(71200400001)(71190400001)(6436002)(30864003)(99286004)(6486002)(66066001)(5660300002)(8936002)(50226002)(68736007)(6306002)(53936002)(44832011)(6512007)(110136005)(53946003)(54906003)(7736002)(476003)(305945005)(486006)(478600001)(4326008)(316002)(386003)(6506007)(106356001)(105586002)(10056002)(52116002)(256004)(14444005)(2906002)(102836004)(2616005)(25786009)(966005)(14454004)(97736004)(559001)(579004);\n\tDIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR04MB3136;\n\tH:VI1PR04MB4431.eurprd04.prod.outlook.com; FPR:; SPF:None; LANG:en;\n\tPTR:InfoNoRecords; A:1; MX:1; ", "received-spf": "None (protection.outlook.com: nxp.com does not designate\n\tpermitted sender hosts)", "x-ms-exchange-senderadcheck": "1", "x-microsoft-antispam-message-info": "D0acJ7jYpapwbukDmD7l3zHIWVXn+70178ZDHZtNqckhvq5dyYH67h4ULilvW5ZkyEImQCQ4kuZVgPCEvxxvbqsaYesZLFAopIAFkAMyr3Rx+hkkBk8gx3Gllb5XMnIOE8950uDOJNTME48imCTLxFBJhCjyzJVahAd1hCEe+T6+d9NtKe10DhY7oW7o7keRxQ5jBlKGxMJCuDfhf4+pZ0iRmyCnmMIjkX9caM0GTFcjgRO5PzcTY9jq4kvzAaCd6WQS70QLRfMUiL7sX2gselOztID05GXt9yF1TZq1SLuEmf3F/Imj8HBOV0ET6EWNRW+7Tcp05go+w4vy0MYufUb36/BptbviP3tlQaPYm2bk93VRZA+KVW3+oTBbEgK7d7dJ/nEBuAd3CZ/gZSDoQlyAgeOSAjk6rZjiY5isDlM=", "MIME-Version": "1.0", "X-OriginatorOrg": "nxp.com", "X-MS-Exchange-CrossTenant-Network-Message-Id": "5a7be7e2-22b4-4736-b9fb-08d6b295dbef", "X-MS-Exchange-CrossTenant-originalarrivaltime": "27 Mar 2019 09:23:23.4029\n\t(UTC)", "X-MS-Exchange-CrossTenant-fromentityheader": "Hosted", "X-MS-Exchange-CrossTenant-id": "686ea1d3-bc2b-4c6f-a92c-d99c5c301635", "X-MS-Exchange-CrossTenant-mailboxtype": "HOSTED", "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "VI1PR04MB3136", "Cc": "Andy Tang <andy.tang@nxp.com>, \"make@marvell.com\" <make@marvell.com>,\n\tPeng Ma <peng.ma@nxp.com>,\n\t\"u-boot@lists.denx.de\" <u-boot@lists.denx.de>, \n\tYinbo Zhu <yinbo.zhu@nxp.com>, \"sr@denx.de\" <sr@denx.de>,\n\tYork Sun <york.sun@nxp.com>", "Subject": "[U-Boot] [PATCH 1/4] ata: fsl_ahci: Add sata DM support for\n\tFreescale powerpc socs", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.18", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<http://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>" }, "content": "This patch is to support Freescale sata driver with dts initialized.\nAlso resolved the following problems.", "diff": "===================== WARNING ======================\nThis board does not use CONFIG_DM_SCSI. Please update\nthe storage controller to use CONFIG_DM_SCSI before the v2019.07 release.\nFailure to update by the deadline may result in board removal.\nSee doc/driver-model/MIGRATION.txt for more info.\n====================================================\n\nSigned-off-by: Peng Ma <peng.ma@nxp.com>\n---\ndepends on:\n\t- https://patchwork.ozlabs.org/project/uboot/list/?series=99168\n\t- https://patchwork.ozlabs.org/project/uboot/list/?series=99167\n\n drivers/ata/Kconfig | 10 +\n drivers/ata/Makefile | 1 +\n drivers/ata/fsl_ahci.c | 1030 ++++++++++++++++++++++++++++++++++++++++\n drivers/ata/fsl_sata.h | 1 +\n 4 files changed, 1042 insertions(+)\n create mode 100644 drivers/ata/fsl_ahci.c\n\ndiff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig\nindex 49a056e941..efac29c709 100644\n--- a/drivers/ata/Kconfig\n+++ b/drivers/ata/Kconfig\n@@ -59,6 +59,16 @@ config DWC_AHCI\n \t Enable this driver to support Sata devices through\n \t Synopsys DWC AHCI module.\n \n+config FSL_AHCI\n+\tbool \"Enable Freescale AHCI driver support\"\n+\tselect SCSI_AHCI\n+\tdepends on AHCI\n+\tdepends on DM_SCSI\n+\thelp\n+\t Enable this driver to support Sata devices found in\n+\t some Freescale PowerPC SoCs.\n+\n+\n config DWC_AHSATA\n \tbool \"Enable DWC AHSATA driver support\"\n \tselect LIBATA\ndiff --git a/drivers/ata/Makefile b/drivers/ata/Makefile\nindex 10bed53bb3..93aabf34c7 100644\n--- a/drivers/ata/Makefile\n+++ b/drivers/ata/Makefile\n@@ -4,6 +4,7 @@\n # Wolfgang Denk, DENX Software Engineering, wd@denx.de.\n \n obj-$(CONFIG_DWC_AHCI) += dwc_ahci.o\n+obj-$(CONFIG_FSL_AHCI) += fsl_ahci.o\n obj-$(CONFIG_AHCI) += ahci-uclass.o\n obj-$(CONFIG_AHCI_PCI) += ahci-pci.o\n obj-$(CONFIG_SCSI_AHCI) += ahci.o\ndiff --git a/drivers/ata/fsl_ahci.c b/drivers/ata/fsl_ahci.c\nnew file mode 100644\nindex 0000000000..16c6f7a335\n--- /dev/null\n+++ b/drivers/ata/fsl_ahci.c\n@@ -0,0 +1,1030 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * NXP PPC SATA platform driver\n+ *\n+ * (C) Copyright 2019 NXP, Inc.\n+ *\n+ */\n+#include <common.h>\n+#include <asm/fsl_serdes.h>\n+#include <dm/lists.h>\n+#include <dm.h>\n+#include <ahci.h>\n+#include <scsi.h>\n+#include <libata.h>\n+#include <sata.h>\n+#include <malloc.h>\n+#include <memalign.h>\n+#include <fis.h>\n+\n+#include \"fsl_sata.h\"\n+\n+struct fsl_ahci_priv {\n+\tu32 base;\n+\tu32 flag;\n+\tu32 number;\n+\tfsl_sata_t *fsl_sata;\n+};\n+\n+static int fsl_ahci_bind(struct udevice *dev)\n+{\n+\treturn device_bind_driver(dev, \"fsl_ahci_scsi\", \"fsl_ahci_scsi\", NULL);\n+}\n+\n+static int fsl_ahci_ofdata_to_platdata(struct udevice *dev)\n+{\n+\tstruct fsl_ahci_priv *priv = dev_get_priv(dev);\n+\n+\tpriv->number = dev_read_u32_default(dev, \"sata-number\", -1);\n+\tpriv->flag = dev_read_u32_default(dev, \"sata-fpdma\", -1);\n+\n+\tpriv->base = dev_read_addr(dev);\n+\tif (priv->base == FDT_ADDR_T_NONE)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static int ata_wait_register(unsigned __iomem *addr, u32 mask,\n+\t\t\t u32 val, u32 timeout_msec)\n+{\n+\tint i;\n+\n+\tfor (i = 0; ((in_le32(addr) & mask) != val) && i < timeout_msec; i++)\n+\t\tmdelay(1);\n+\n+\treturn (i < timeout_msec) ? 0 : -1;\n+}\n+\n+static void fsl_sata_dump_sfis(struct sata_fis_d2h *s)\n+{\n+\tprintf(\"Status FIS dump:\\n\\r\");\n+\tprintf(\"fis_type:\t\t%02x\\n\\r\", s->fis_type);\n+\tprintf(\"pm_port_i:\t\t%02x\\n\\r\", s->pm_port_i);\n+\tprintf(\"status:\t\t\t%02x\\n\\r\", s->status);\n+\tprintf(\"error:\t\t\t%02x\\n\\r\", s->error);\n+\tprintf(\"lba_low:\t\t%02x\\n\\r\", s->lba_low);\n+\tprintf(\"lba_mid:\t\t%02x\\n\\r\", s->lba_mid);\n+\tprintf(\"lba_high:\t\t%02x\\n\\r\", s->lba_high);\n+\tprintf(\"device:\t\t\t%02x\\n\\r\", s->device);\n+\tprintf(\"lba_low_exp:\t\t%02x\\n\\r\", s->lba_low_exp);\n+\tprintf(\"lba_mid_exp:\t\t%02x\\n\\r\", s->lba_mid_exp);\n+\tprintf(\"lba_high_exp:\t\t%02x\\n\\r\", s->lba_high_exp);\n+\tprintf(\"res1:\t\t\t%02x\\n\\r\", s->res1);\n+\tprintf(\"sector_count:\t\t%02x\\n\\r\", s->sector_count);\n+\tprintf(\"sector_count_exp:\t%02x\\n\\r\", s->sector_count_exp);\n+}\n+\n+static void fsl_sata_dump_regs(fsl_sata_reg_t __iomem *reg)\n+{\n+\tprintf(\"\\n\\rSATA: %08x\\n\\r\", (u32)reg);\n+\tprintf(\"CQR: %08x\\n\\r\", in_le32(®->cqr));\n+\tprintf(\"CAR: %08x\\n\\r\", in_le32(®->car));\n+\tprintf(\"CCR: %08x\\n\\r\", in_le32(®->ccr));\n+\tprintf(\"CER: %08x\\n\\r\", in_le32(®->cer));\n+\tprintf(\"CQR: %08x\\n\\r\", in_le32(®->cqr));\n+\tprintf(\"DER: %08x\\n\\r\", in_le32(®->der));\n+\tprintf(\"CHBA: %08x\\n\\r\", in_le32(®->chba));\n+\tprintf(\"HStatus: %08x\\n\\r\", in_le32(®->hstatus));\n+\tprintf(\"HControl: %08x\\n\\r\", in_le32(®->hcontrol));\n+\tprintf(\"CQPMP: %08x\\n\\r\", in_le32(®->cqpmp));\n+\tprintf(\"SIG: %08x\\n\\r\", in_le32(®->sig));\n+\tprintf(\"ICC: %08x\\n\\r\", in_le32(®->icc));\n+\tprintf(\"SStatus: %08x\\n\\r\", in_le32(®->sstatus));\n+\tprintf(\"SError: %08x\\n\\r\", in_le32(®->serror));\n+\tprintf(\"SControl: %08x\\n\\r\", in_le32(®->scontrol));\n+\tprintf(\"SNotification: %08x\\n\\r\", in_le32(®->snotification));\n+\tprintf(\"TransCfg: %08x\\n\\r\", in_le32(®->transcfg));\n+\tprintf(\"TransStatus: %08x\\n\\r\", in_le32(®->transstatus));\n+\tprintf(\"LinkCfg: %08x\\n\\r\", in_le32(®->linkcfg));\n+\tprintf(\"LinkCfg1: %08x\\n\\r\", in_le32(®->linkcfg1));\n+\tprintf(\"LinkCfg2: %08x\\n\\r\", in_le32(®->linkcfg2));\n+\tprintf(\"LinkStatus: %08x\\n\\r\", in_le32(®->linkstatus));\n+\tprintf(\"LinkStatus1: %08x\\n\\r\", in_le32(®->linkstatus1));\n+\tprintf(\"PhyCtrlCfg: %08x\\n\\r\", in_le32(®->phyctrlcfg));\n+\tprintf(\"SYSPR: %08x\\n\\r\", in_be32(®->syspr));\n+}\n+\n+static int init_sata(struct fsl_ahci_priv *priv)\n+{\n+\tint i;\n+\tu32 cda;\n+\tu32 val32;\n+\tu32 sig;\n+\tfsl_sata_t *sata;\n+\tu32 length, align;\n+\tcmd_hdr_tbl_t *cmd_hdr;\n+\tfsl_sata_reg_t __iomem *reg;\n+\n+\tint dev = priv->number;\n+\n+\tif (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {\n+\t\tprintf(\"the sata index %d is out of ranges\\n\\r\", dev);\n+\t\treturn -EINVAL;\n+\t}\n+\n+#ifdef CONFIG_MPC85xx\n+\tif (dev == 0 && (!is_serdes_configured(SATA1))) {\n+\t\tprintf(\"SATA%d [dev = %d] is not enabled\\n\", dev + 1, dev);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (dev == 1 && (!is_serdes_configured(SATA2))) {\n+\t\tprintf(\"SATA%d [dev = %d] is not enabled\\n\", dev + 1, dev);\n+\t\treturn -EINVAL;\n+\t}\n+#endif\n+\n+\t/* Allocate SATA device driver struct */\n+\tsata = (fsl_sata_t *)malloc(sizeof(fsl_sata_t));\n+\tif (!sata) {\n+\t\tprintf(\"alloc the sata device struct failed\\n\\r\");\n+\t\treturn -ENOMEM;\n+\t}\n+\t/* Zero all of the device driver struct */\n+\tmemset((void *)sata, 0, sizeof(fsl_sata_t));\n+\n+\tsata->dma_flag = priv->flag;\n+\tsnprintf(sata->name, 12, \"SATA%d\", dev);\n+\n+\t/* Set the controller register base address to device struct */\n+\treg = (fsl_sata_reg_t *)priv->base;\n+\tsata->reg_base = reg;\n+\n+\t/* Allocate the command header table, 4 bytes aligned */\n+\tlength = sizeof(struct cmd_hdr_tbl);\n+\talign = SATA_HC_CMD_HDR_TBL_ALIGN;\n+\tsata->cmd_hdr_tbl_offset = (void *)malloc(length + align);\n+\tif (!sata->cmd_hdr_tbl_offset) {\n+\t\tprintf(\"alloc the command header failed\\n\\r\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tcmd_hdr = (cmd_hdr_tbl_t *)(((u32)sata->cmd_hdr_tbl_offset + align)\n+\t\t\t\t\t\t& ~(align - 1));\n+\tsata->cmd_hdr = cmd_hdr;\n+\n+\t/* Zero all of the command header table */\n+\tmemset((void *)sata->cmd_hdr_tbl_offset, 0, length + align);\n+\n+\t/* Allocate command descriptor for all command */\n+\tlength = sizeof(struct cmd_desc) * SATA_HC_MAX_CMD;\n+\talign = SATA_HC_CMD_DESC_ALIGN;\n+\tsata->cmd_desc_offset = (void *)malloc(length + align);\n+\tif (!sata->cmd_desc_offset) {\n+\t\tprintf(\"alloc the command descriptor failed\\n\\r\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tsata->cmd_desc = (cmd_desc_t *)(((u32)sata->cmd_desc_offset + align)\n+\t\t\t\t\t\t& ~(align - 1));\n+\t/* Zero all of command descriptor */\n+\tmemset((void *)sata->cmd_desc_offset, 0, length + align);\n+\n+\t/* Link the command descriptor to command header */\n+\tfor (i = 0; i < SATA_HC_MAX_CMD; i++) {\n+\t\tcda = ((u32)sata->cmd_desc + SATA_HC_CMD_DESC_SIZE * i)\n+\t\t\t\t\t & ~(CMD_HDR_CDA_ALIGN - 1);\n+\t\tcmd_hdr->cmd_slot[i].cda = cpu_to_le32(cda);\n+\t}\n+\n+\t/* To have safe state, force the controller offline */\n+\tval32 = in_le32(®->hcontrol);\n+\tval32 &= ~HCONTROL_ONOFF;\n+\tval32 |= HCONTROL_FORCE_OFFLINE;\n+\tout_le32(®->hcontrol, val32);\n+\n+\t/* Wait the controller offline */\n+\tata_wait_register(®->hstatus, HSTATUS_ONOFF, 0, 1000);\n+\n+\t/* Set the command header base address to CHBA register to tell DMA */\n+\tout_le32(®->chba, (u32)cmd_hdr & ~0x3);\n+\n+\t/* Snoop for the command header */\n+\tval32 = in_le32(®->hcontrol);\n+\tval32 |= HCONTROL_HDR_SNOOP;\n+\tout_le32(®->hcontrol, val32);\n+\n+\t/* Disable all of interrupts */\n+\tval32 = in_le32(®->hcontrol);\n+\tval32 &= ~HCONTROL_INT_EN_ALL;\n+\tout_le32(®->hcontrol, val32);\n+\n+\t/* Clear all of interrupts */\n+\tval32 = in_le32(®->hstatus);\n+\tout_le32(®->hstatus, val32);\n+\n+\t/* Set the ICC, no interrupt coalescing */\n+\tout_le32(®->icc, 0x01000000);\n+\n+\t/* No PM attatched, the SATA device direct connect */\n+\tout_le32(®->cqpmp, 0);\n+\n+\t/* Clear SError register */\n+\tval32 = in_le32(®->serror);\n+\tout_le32(®->serror, val32);\n+\n+\t/* Clear CER register */\n+\tval32 = in_le32(®->cer);\n+\tout_le32(®->cer, val32);\n+\n+\t/* Clear DER register */\n+\tval32 = in_le32(®->der);\n+\tout_le32(®->der, val32);\n+\n+\t/* No device detection or initialization action requested */\n+\tout_le32(®->scontrol, 0x00000300);\n+\n+\t/* Configure the transport layer, default value */\n+\tout_le32(®->transcfg, 0x08000016);\n+\n+\t/* Configure the link layer, default value */\n+\tout_le32(®->linkcfg, 0x0000ff34);\n+\n+\t/* Bring the controller online */\n+\tval32 = in_le32(®->hcontrol);\n+\tval32 |= HCONTROL_ONOFF;\n+\tout_le32(®->hcontrol, val32);\n+\n+\tmdelay(100);\n+\n+\t/* print sata device name */\n+\tprintf(\"%s \", sata->name);\n+\n+\t/* Wait PHY RDY signal changed for 500ms */\n+\tata_wait_register(®->hstatus, HSTATUS_PHY_RDY,\n+\t\t\t HSTATUS_PHY_RDY, 500);\n+\n+\t/* Check PHYRDY */\n+\tval32 = in_le32(®->hstatus);\n+\tif (val32 & HSTATUS_PHY_RDY) {\n+\t\tsata->link = 1;\n+\t} else {\n+\t\tsata->link = 0;\n+\t\tprintf(\"(No RDY)\\n\\r\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Wait for signature updated, which is 1st D2H */\n+\tata_wait_register(®->hstatus, HSTATUS_SIGNATURE,\n+\t\t\t HSTATUS_SIGNATURE, 10000);\n+\n+\tif (val32 & HSTATUS_SIGNATURE) {\n+\t\tsig = in_le32(®->sig);\n+\t\tdebug(\"Signature updated, the sig =%08x\\n\\r\", sig);\n+\t\tsata->ata_device_type = ata_dev_classify(sig);\n+\t}\n+\n+\t/* Check the speed */\n+\tval32 = in_le32(®->sstatus);\n+\tif ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN1)\n+\t\tprintf(\"(1.5 Gbps)\\n\\r\");\n+\telse if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN2)\n+\t\tprintf(\"(3 Gbps)\\n\\r\");\n+\n+\tpriv->fsl_sata = sata;\n+\n+\treturn 0;\n+}\n+\n+static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata,\n+\t\t\t\tstruct sata_fis_h2d *cfis,\n+\t\t\t\tint is_ncq, int tag,\n+\t\t\t\tu8 *buffer, u32 len)\n+{\n+\tcmd_hdr_entry_t *cmd_hdr;\n+\tcmd_desc_t *cmd_desc;\n+\tsata_fis_h2d_t *h2d;\n+\tprd_entry_t *prde;\n+\tu32 ext_c_ddc;\n+\tu32 prde_count;\n+\tu32 val32;\n+\tu32 ttl;\n+\tu32 der;\n+\tint i;\n+\n+\tfsl_sata_reg_t *reg = sata->reg_base;\n+\n+\t/* Check xfer length */\n+\tif (len > SATA_HC_MAX_XFER_LEN) {\n+\t\tprintf(\"max transfer length is 64MB\\n\\r\");\n+\t\treturn 0;\n+\t}\n+\n+\t/* Setup the command descriptor */\n+\tcmd_desc = sata->cmd_desc + tag;\n+\n+\t/* Get the pointer cfis of command descriptor */\n+\th2d = (sata_fis_h2d_t *)cmd_desc->cfis;\n+\n+\t/* Zero the cfis of command descriptor */\n+\tmemset((void *)h2d, 0, SATA_HC_CMD_DESC_CFIS_SIZE);\n+\n+\t/* Copy the cfis from user to command descriptor */\n+\th2d->fis_type = cfis->fis_type;\n+\th2d->pm_port_c = cfis->pm_port_c;\n+\th2d->command = cfis->command;\n+\n+\th2d->features = cfis->features;\n+\th2d->features_exp = cfis->features_exp;\n+\n+\th2d->lba_low = cfis->lba_low;\n+\th2d->lba_mid = cfis->lba_mid;\n+\th2d->lba_high = cfis->lba_high;\n+\th2d->lba_low_exp = cfis->lba_low_exp;\n+\th2d->lba_mid_exp = cfis->lba_mid_exp;\n+\th2d->lba_high_exp = cfis->lba_high_exp;\n+\n+\tif (!is_ncq) {\n+\t\th2d->sector_count = cfis->sector_count;\n+\t\th2d->sector_count_exp = cfis->sector_count_exp;\n+\t} else { /* NCQ */\n+\t\th2d->sector_count = (u8)(tag << 3);\n+\t}\n+\n+\th2d->device = cfis->device;\n+\th2d->control = cfis->control;\n+\n+\t/* Setup the PRD table */\n+\tprde = (prd_entry_t *)cmd_desc->prdt;\n+\tmemset((void *)prde, 0, sizeof(struct prdt));\n+\n+\tprde_count = 0;\n+\tttl = len;\n+\tfor (i = 0; i < SATA_HC_MAX_PRD_DIRECT; i++) {\n+\t\tif (!len)\n+\t\t\tbreak;\n+\t\tprde->dba = cpu_to_le32((u32)buffer & ~0x3);\n+\t\tdebug(\"dba = %08x\\n\\r\", (u32)buffer);\n+\n+\t\tif (len < PRD_ENTRY_MAX_XFER_SZ) {\n+\t\t\text_c_ddc = PRD_ENTRY_DATA_SNOOP | len;\n+\t\t\tdebug(\"ext_c_ddc1 = %08x, len = %08x\\n\\r\",\n+\t\t\t ext_c_ddc, len);\n+\t\t\tprde->ext_c_ddc = cpu_to_le32(ext_c_ddc);\n+\t\t\tprde_count++;\n+\t\t\tprde++;\n+\t\t} else {\n+\t\t\text_c_ddc = PRD_ENTRY_DATA_SNOOP; /* 4M bytes */\n+\t\t\tdebug(\"ext_c_ddc2 = %08x, len = %08x\\n\\r\",\n+\t\t\t ext_c_ddc, len);\n+\t\t\tprde->ext_c_ddc = cpu_to_le32(ext_c_ddc);\n+\t\t\tbuffer += PRD_ENTRY_MAX_XFER_SZ;\n+\t\t\tlen -= PRD_ENTRY_MAX_XFER_SZ;\n+\t\t\tprde_count++;\n+\t\t\tprde++;\n+\t\t}\n+\t}\n+\n+\t/* Setup the command slot of cmd hdr */\n+\tcmd_hdr = (cmd_hdr_entry_t *)&sata->cmd_hdr->cmd_slot[tag];\n+\n+\tcmd_hdr->cda = cpu_to_le32((u32)cmd_desc & ~0x3);\n+\n+\tval32 = prde_count << CMD_HDR_PRD_ENTRY_SHIFT;\n+\tval32 |= sizeof(sata_fis_h2d_t);\n+\tcmd_hdr->prde_fis_len = cpu_to_le32(val32);\n+\n+\tcmd_hdr->ttl = cpu_to_le32(ttl);\n+\n+\tif (!is_ncq)\n+\t\tval32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP;\n+\telse\n+\t\tval32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP |\n+\t\t\tCMD_HDR_ATTR_FPDMA;\n+\n+\ttag &= CMD_HDR_ATTR_TAG;\n+\tval32 |= tag;\n+\n+\tdebug(\"attribute = %08x\\n\\r\", val32);\n+\tcmd_hdr->attribute = cpu_to_le32(val32);\n+\n+\t/* Make sure cmd desc and cmd slot valid before command issue */\n+\tsync();\n+\n+\t/* PMP*/\n+\tval32 = (u32)(h2d->pm_port_c & 0x0f);\n+\tout_le32(®->cqpmp, val32);\n+\n+\t/* Wait no active */\n+\tif (ata_wait_register(®->car, (1 << tag), 0, 10000))\n+\t\tprintf(\"Wait no active time out\\n\\r\");\n+\n+\t/* Issue command */\n+\tif (!(in_le32(®->cqr) & (1 << tag))) {\n+\t\tval32 = 1 << tag;\n+\t\tout_le32(®->cqr, val32);\n+\t}\n+\n+\t/* Wait command completed for 10s */\n+\tif (ata_wait_register(®->ccr, (1 << tag), (1 << tag), 10000)) {\n+\t\tif (!is_ncq)\n+\t\t\tprintf(\"Non-NCQ command time out\\n\\r\");\n+\t\telse\n+\t\t\tprintf(\"NCQ command time out\\n\\r\");\n+\t}\n+\n+\tval32 = in_le32(®->cer);\n+\n+\tif (val32) {\n+\t\tfsl_sata_dump_sfis((struct sata_fis_d2h *)cmd_desc->sfis);\n+\t\tprintf(\"CE at device\\n\\r\");\n+\t\tfsl_sata_dump_regs(reg);\n+\t\tder = in_le32(®->der);\n+\t\tout_le32(®->cer, val32);\n+\t\tout_le32(®->der, der);\n+\t}\n+\n+\t/* Clear complete flags */\n+\tval32 = in_le32(®->ccr);\n+\tout_le32(®->ccr, val32);\n+\n+\treturn len;\n+}\n+\n+static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,\n+\t\t\t enum cmd_type command_type, int tag, u8 *buffer,\n+\t\t\t u32 len)\n+{\n+\tint rc;\n+\n+\tif (tag > SATA_HC_MAX_CMD || tag < 0) {\n+\t\tprintf(\"tag is out of range, tag=%d\\n\\r\", tag);\n+\t\treturn -1;\n+\t}\n+\n+\tswitch (command_type) {\n+\tcase CMD_ATA:\n+\t\trc = fsl_ata_exec_ata_cmd(sata, cfis, 0, tag, buffer, len);\n+\t\treturn rc;\n+\tcase CMD_NCQ:\n+\t\trc = fsl_ata_exec_ata_cmd(sata, cfis, 1, tag, buffer, len);\n+\t\treturn rc;\n+\tcase CMD_ATAPI:\n+\tcase CMD_VENDOR_BIST:\n+\tcase CMD_BIST:\n+\t\tprintf(\"not support now\\n\\r\");\n+\t\treturn -1;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static void fsl_sata_identify(fsl_sata_t *sata, u16 *id)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\tcfis->command = ATA_CMD_ID_ATA;\n+\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, (u8 *)id, ATA_ID_WORDS * 2);\n+\tata_swap_buf_le16(id, ATA_ID_WORDS);\n+}\n+\n+static void fsl_sata_xfer_mode(fsl_sata_t *sata, u16 *id)\n+{\n+\tsata->pio = id[ATA_ID_PIO_MODES];\n+\tsata->mwdma = id[ATA_ID_MWDMA_MODES];\n+\tsata->udma = id[ATA_ID_UDMA_MODES];\n+\tdebug(\"pio %04x, mwdma %04x, udma %04x\\n\\r\", sata->pio,\n+\t sata->mwdma, sata->udma);\n+}\n+\n+static void fsl_sata_init_wcache(fsl_sata_t *sata, u16 *id)\n+{\n+\tif (ata_id_has_wcache(id) && ata_id_wcache_enabled(id))\n+\t\tsata->wcache = 1;\n+\tif (ata_id_has_flush(id))\n+\t\tsata->flush = 1;\n+\tif (ata_id_has_flush_ext(id))\n+\t\tsata->flush_ext = 1;\n+}\n+\n+static void fsl_sata_set_features(fsl_sata_t *sata)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\tu8 udma_cap;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\tcfis->command = ATA_CMD_SET_FEATURES;\n+\tcfis->features = SETFEATURES_XFER;\n+\n+\t/* First check the device capablity */\n+\tudma_cap = (u8)(sata->udma & 0xff);\n+\tdebug(\"udma_cap %02x\\n\\r\", udma_cap);\n+\n+\tif (udma_cap == ATA_UDMA6)\n+\t\tcfis->sector_count = XFER_UDMA_6;\n+\tif (udma_cap == ATA_UDMA5)\n+\t\tcfis->sector_count = XFER_UDMA_5;\n+\tif (udma_cap == ATA_UDMA4)\n+\t\tcfis->sector_count = XFER_UDMA_4;\n+\tif (udma_cap == ATA_UDMA3)\n+\t\tcfis->sector_count = XFER_UDMA_3;\n+\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);\n+}\n+\n+static u32 fsl_sata_rw_cmd(fsl_sata_t *sata, u32 start, u32 blkcnt,\n+\t\t\t u8 *buffer, int is_write)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\tu32 block;\n+\n+\tblock = start;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\tcfis->command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ;\n+\tcfis->device = ATA_LBA;\n+\n+\tcfis->device |= (block >> 24) & 0xf;\n+\tcfis->lba_high = (block >> 16) & 0xff;\n+\tcfis->lba_mid = (block >> 8) & 0xff;\n+\tcfis->lba_low = block & 0xff;\n+\tcfis->sector_count = (u8)(blkcnt & 0xff);\n+\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer,\n+\t\t\t ATA_SECT_SIZE * blkcnt);\n+\treturn blkcnt;\n+}\n+\n+static void fsl_sata_flush_cache(fsl_sata_t *sata)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\tcfis->command = ATA_CMD_FLUSH;\n+\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);\n+}\n+\n+static u32 fsl_sata_rw_cmd_ext(fsl_sata_t *sata, u32 start,\n+\t\t\t u32 blkcnt, u8 *buffer, int is_write)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\tu64 block;\n+\n+\tblock = (u64)start;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\n+\tcfis->command = (is_write) ? ATA_CMD_WRITE_EXT\n+\t\t\t\t : ATA_CMD_READ_EXT;\n+\n+\tcfis->lba_high_exp = (block >> 40) & 0xff;\n+\tcfis->lba_mid_exp = (block >> 32) & 0xff;\n+\tcfis->lba_low_exp = (block >> 24) & 0xff;\n+\tcfis->lba_high = (block >> 16) & 0xff;\n+\tcfis->lba_mid = (block >> 8) & 0xff;\n+\tcfis->lba_low = block & 0xff;\n+\tcfis->device = ATA_LBA;\n+\tcfis->sector_count_exp = (blkcnt >> 8) & 0xff;\n+\tcfis->sector_count = blkcnt & 0xff;\n+\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer,\n+\t\t\t ATA_SECT_SIZE * blkcnt);\n+\treturn blkcnt;\n+}\n+\n+static u32 fsl_sata_rw_ncq_cmd(fsl_sata_t *sata, u32 start, u32 blkcnt,\n+\t\t\t u8 *buffer,\n+\t\t\t int is_write)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\tint ncq_channel;\n+\tu64 block;\n+\n+\tif (sata->lba48 != 1) {\n+\t\tprintf(\"execute FPDMA command on non-LBA48 hard disk\\n\\r\");\n+\t\treturn -1;\n+\t}\n+\n+\tblock = (u64)start;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\n+\tcfis->command = (is_write) ? ATA_CMD_FPDMA_WRITE\n+\t\t\t\t : ATA_CMD_FPDMA_READ;\n+\n+\tcfis->lba_high_exp = (block >> 40) & 0xff;\n+\tcfis->lba_mid_exp = (block >> 32) & 0xff;\n+\tcfis->lba_low_exp = (block >> 24) & 0xff;\n+\tcfis->lba_high = (block >> 16) & 0xff;\n+\tcfis->lba_mid = (block >> 8) & 0xff;\n+\tcfis->lba_low = block & 0xff;\n+\n+\tcfis->device = ATA_LBA;\n+\tcfis->features_exp = (blkcnt >> 8) & 0xff;\n+\tcfis->features = blkcnt & 0xff;\n+\n+\tif (sata->queue_depth >= SATA_HC_MAX_CMD)\n+\t\tncq_channel = SATA_HC_MAX_CMD - 1;\n+\telse\n+\t\tncq_channel = sata->queue_depth - 1;\n+\n+\t/* Use the latest queue */\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_NCQ, ncq_channel, buffer,\n+\t\t\t ATA_SECT_SIZE * blkcnt);\n+\treturn blkcnt;\n+}\n+\n+static void fsl_sata_flush_cache_ext(fsl_sata_t *sata)\n+{\n+\tstruct sata_fis_h2d h2d, *cfis = &h2d;\n+\n+\tmemset(cfis, 0, sizeof(struct sata_fis_h2d));\n+\n+\tcfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;\n+\tcfis->pm_port_c = 0x80; /* is command */\n+\tcfis->command = ATA_CMD_FLUSH_EXT;\n+\n+\tfsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);\n+}\n+\n+static u32 ata_low_level_rw_lba48(fsl_sata_t *sata, u32 blknr, lbaint_t blkcnt,\n+\t\t\t\t const void *buffer, int is_write)\n+{\n+\tu32 start, blks;\n+\tu8 *addr;\n+\tint max_blks;\n+\n+\tstart = blknr;\n+\tblks = blkcnt;\n+\taddr = (u8 *)buffer;\n+\n+\tmax_blks = ATA_MAX_SECTORS_LBA48;\n+\tdo {\n+\t\tif (blks > max_blks) {\n+\t\t\tif (sata->dma_flag != FLAGS_FPDMA)\n+\t\t\t\tfsl_sata_rw_cmd_ext(sata, start, max_blks,\n+\t\t\t\t\t\t addr, is_write);\n+\t\t\telse\n+\t\t\t\tfsl_sata_rw_ncq_cmd(sata, start, max_blks,\n+\t\t\t\t\t\t addr, is_write);\n+\t\t\tstart += max_blks;\n+\t\t\tblks -= max_blks;\n+\t\t\taddr += ATA_SECT_SIZE * max_blks;\n+\t\t} else {\n+\t\t\tif (sata->dma_flag != FLAGS_FPDMA)\n+\t\t\t\tfsl_sata_rw_cmd_ext(sata, start, blks,\n+\t\t\t\t\t\t addr, is_write);\n+\t\t\telse\n+\t\t\t\tfsl_sata_rw_ncq_cmd(sata, start, blks,\n+\t\t\t\t\t\t addr, is_write);\n+\t\t\tstart += blks;\n+\t\t\tblks = 0;\n+\t\t\taddr += ATA_SECT_SIZE * blks;\n+\t\t}\n+\t} while (blks != 0);\n+\n+\treturn blks;\n+}\n+\n+static u32 ata_low_level_rw_lba28(fsl_sata_t *sata, u32 blknr, u32 blkcnt,\n+\t\t\t\t const void *buffer, int is_write)\n+{\n+\tu32 start, blks;\n+\tu8 *addr;\n+\tint max_blks;\n+\n+\tstart = blknr;\n+\tblks = blkcnt;\n+\taddr = (u8 *)buffer;\n+\n+\tmax_blks = ATA_MAX_SECTORS;\n+\tdo {\n+\t\tif (blks > max_blks) {\n+\t\t\tfsl_sata_rw_cmd(sata, start, max_blks, addr, is_write);\n+\t\t\tstart += max_blks;\n+\t\t\tblks -= max_blks;\n+\t\t\taddr += ATA_SECT_SIZE * max_blks;\n+\t\t} else {\n+\t\t\tfsl_sata_rw_cmd(sata, start, blks, addr, is_write);\n+\t\t\tstart += blks;\n+\t\t\tblks = 0;\n+\t\t\taddr += ATA_SECT_SIZE * blks;\n+\t\t}\n+\t} while (blks != 0);\n+\n+\treturn blks;\n+}\n+\n+/*\n+ * SATA interface between low level driver and command layer\n+ */\n+static int sata_read(fsl_sata_t *sata, ulong blknr, lbaint_t blkcnt,\n+\t\t void *buffer)\n+{\n+\tu32 rc;\n+\n+\tif (sata->lba48)\n+\t\trc = ata_low_level_rw_lba48(sata, blknr, blkcnt, buffer,\n+\t\t\t\t\t READ_CMD);\n+\telse\n+\t\trc = ata_low_level_rw_lba28(sata, blknr, blkcnt, buffer,\n+\t\t\t\t\t READ_CMD);\n+\treturn rc;\n+}\n+\n+static int sata_write(fsl_sata_t *sata, ulong blknr, lbaint_t blkcnt,\n+\t\t const void *buffer)\n+{\n+\tu32 rc;\n+\n+\tif (sata->lba48) {\n+\t\trc = ata_low_level_rw_lba48(sata, blknr, blkcnt, buffer,\n+\t\t\t\t\t WRITE_CMD);\n+\t\tif (sata->wcache && sata->flush_ext)\n+\t\t\tfsl_sata_flush_cache_ext(sata);\n+\t} else {\n+\t\trc = ata_low_level_rw_lba28(sata, blknr, blkcnt, buffer,\n+\t\t\t\t\t WRITE_CMD);\n+\t\tif (sata->wcache && sata->flush)\n+\t\t\tfsl_sata_flush_cache(sata);\n+\t}\n+\n+\treturn rc;\n+}\n+\n+int sata_getinfo(fsl_sata_t *sata, u16 *id)\n+{\n+\t/* if no detected link */\n+\tif (!sata->link)\n+\t\treturn -EINVAL;\n+\n+#ifdef CONFIG_LBA48\n+\t/* Check if support LBA48 */\n+\tif (ata_id_has_lba48(id)) {\n+\t\tsata->lba48 = 1;\n+\t\tdebug(\"Device support LBA48\\n\\r\");\n+\t} else {\n+\t\tdebug(\"Device supports LBA28\\n\\r\");\n+\t}\n+#endif\n+\n+\t/* Get the NCQ queue depth from device */\n+\tsata->queue_depth = ata_id_queue_depth(id);\n+\n+\t/* Get the xfer mode from device */\n+\tfsl_sata_xfer_mode(sata, id);\n+\n+\t/* Get the write cache status from device */\n+\tfsl_sata_init_wcache(sata, id);\n+\n+\t/* Set the xfer mode to highest speed */\n+\tfsl_sata_set_features(sata);\n+\n+\treturn 0;\n+}\n+\n+static int fsl_scsi_exec(fsl_sata_t *sata, struct scsi_cmd *pccb,\n+\t\t\t bool is_write)\n+{\n+\tint ret;\n+\tu32 temp;\n+\tu16 blocks = 0;\n+\tlbaint_t start = 0;\n+\tu8 *buffer = pccb->pdata;\n+\n+\t/* Retrieve the base LBA number from the ccb structure. */\n+\tif (pccb->cmd[0] == SCSI_READ16) {\n+\t\tmemcpy(&start, pccb->cmd + 2, 8);\n+\t\tstart = be64_to_cpu(start);\n+\t} else {\n+\t\tmemcpy(&temp, pccb->cmd + 2, 4);\n+\t\tstart = be32_to_cpu(temp);\n+\t}\n+\n+\tif (pccb->cmd[0] == SCSI_READ16)\n+\t\tblocks = (((u16)pccb->cmd[13]) << 8) | ((u16)pccb->cmd[14]);\n+\telse\n+\t\tblocks = (((u16)pccb->cmd[7]) << 8) | ((u16)pccb->cmd[8]);\n+\n+\tdebug(\"scsi_ahci: %s %u blocks starting from lba 0x\" LBAFU \"\\n\",\n+\t is_write ? \"write\" : \"read\", blocks, start);\n+\n+\tif (is_write)\n+\t\tret = sata_write(sata, start, blocks, buffer);\n+\telse\n+\t\tret = sata_read(sata, start, blocks, buffer);\n+\n+\treturn ret;\n+}\n+\n+static char *fsl_ata_id_strcpy(u16 *target, u16 *src, int len)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < len / 2; i++)\n+\t\ttarget[i] = src[i];\n+\n+\treturn (char *)target;\n+}\n+\n+static int fsl_ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv,\n+\t\t\t\t struct scsi_cmd *pccb,\n+\t\t\t\t fsl_sata_t *sata)\n+{\n+\tu8 port;\n+\tu16 *idbuf;\n+\n+\tALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS);\n+\n+\t/* Clean ccb data buffer */\n+\tmemset(pccb->pdata, 0, pccb->datalen);\n+\n+\tif (pccb->datalen <= 35)\n+\t\treturn 0;\n+\n+\t/* Read id from sata */\n+\tport = pccb->target;\n+\n+\tfsl_sata_identify(sata, (u16 *)tmpid);\n+\n+\tif (!uc_priv->ataid[port]) {\n+\t\tuc_priv->ataid[port] = malloc(ATA_ID_WORDS * 2);\n+\t\tif (!uc_priv->ataid[port]) {\n+\t\t\tprintf(\"%s: No memory for ataid[port]\\n\", __func__);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t}\n+\n+\tidbuf = uc_priv->ataid[port];\n+\n+\tmemcpy(idbuf, tmpid, ATA_ID_WORDS * 2);\n+\n+\tmemcpy(&pccb->pdata[8], \"ATA \", 8);\n+\tfsl_ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], 16);\n+\tfsl_ata_id_strcpy((u16 *)&pccb->pdata[32], &idbuf[ATA_ID_FW_REV], 4);\n+\n+\tsata_getinfo(sata, (u16 *)idbuf);\n+#ifdef DEBUG\n+\tata_dump_id(idbuf);\n+#endif\n+\treturn 0;\n+}\n+\n+/*\n+ * SCSI READ CAPACITY10 command operation.\n+ */\n+static int fsl_ata_scsiop_read_capacity10(struct ahci_uc_priv *uc_priv,\n+\t\t\t\t\t struct scsi_cmd *pccb)\n+{\n+\tu32 cap;\n+\tu64 cap64;\n+\tu32 block_size;\n+\n+\tif (!uc_priv->ataid[pccb->target]) {\n+\t\tprintf(\"scsi_ahci: SCSI READ CAPACITY10 command failure.\"\n+\t\t \"\\tNo ATA info!\\n\"\n+\t\t \"\\tPlease run SCSI command INQUIRY first!\\n\");\n+\t\treturn -EPERM;\n+\t}\n+\n+\tcap64 = ata_id_n_sectors(uc_priv->ataid[pccb->target]);\n+\tif (cap64 > 0x100000000ULL)\n+\t\tcap64 = 0xffffffff;\n+\n+\tcap = cpu_to_be32(cap64);\n+\tmemcpy(pccb->pdata, &cap, sizeof(cap));\n+\n+\tblock_size = cpu_to_be32((u32)512);\n+\tmemcpy(&pccb->pdata[4], &block_size, 4);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * SCSI READ CAPACITY16 command operation.\n+ */\n+static int fsl_ata_scsiop_read_capacity16(struct ahci_uc_priv *uc_priv,\n+\t\t\t\t\t struct scsi_cmd *pccb)\n+{\n+\tu64 cap;\n+\tu64 block_size;\n+\n+\tif (!uc_priv->ataid[pccb->target]) {\n+\t\tprintf(\"scsi_ahci: SCSI READ CAPACITY16 command failure.\"\n+\t\t \"\\tNo ATA info!\\n\"\n+\t\t \"\\tPlease run SCSI command INQUIRY first!\\n\");\n+\t\treturn -EPERM;\n+\t}\n+\n+\tcap = ata_id_n_sectors(uc_priv->ataid[pccb->target]);\n+\tcap = cpu_to_be64(cap);\n+\tmemcpy(pccb->pdata, &cap, sizeof(cap));\n+\n+\tblock_size = cpu_to_be64((u64)512);\n+\tmemcpy(&pccb->pdata[8], &block_size, 8);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * SCSI TEST UNIT READY command operation.\n+ */\n+static int fsl_ata_scsiop_test_unit_ready(struct ahci_uc_priv *uc_priv,\n+\t\t\t\t\t struct scsi_cmd *pccb)\n+{\n+\treturn (uc_priv->ataid[pccb->target]) ? 0 : -EPERM;\n+}\n+\n+static int fsl_ahci_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb)\n+{\n+\tstruct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev->parent);\n+\tstruct fsl_ahci_priv *priv = dev_get_priv(dev->parent);\n+\tfsl_sata_t *sata = priv->fsl_sata;\n+\tint ret;\n+\n+\tswitch (pccb->cmd[0]) {\n+\tcase SCSI_READ16:\n+\tcase SCSI_READ10:\n+\t\tret = fsl_scsi_exec(sata, pccb, 0);\n+\t\tbreak;\n+\tcase SCSI_WRITE10:\n+\t\tret = fsl_scsi_exec(sata, pccb, 1);\n+\t\tbreak;\n+\tcase SCSI_RD_CAPAC10:\n+\t\tret = fsl_ata_scsiop_read_capacity10(uc_priv, pccb);\n+\t\tbreak;\n+\tcase SCSI_RD_CAPAC16:\n+\t\tret = fsl_ata_scsiop_read_capacity16(uc_priv, pccb);\n+\t\tbreak;\n+\tcase SCSI_TST_U_RDY:\n+\t\tret = fsl_ata_scsiop_test_unit_ready(uc_priv, pccb);\n+\t\tbreak;\n+\tcase SCSI_INQUIRY:\n+\t\tret = fsl_ata_scsiop_inquiry(uc_priv, pccb, sata);\n+\t\tbreak;\n+\tdefault:\n+\t\tprintf(\"Unsupport SCSI command 0x%02x\\n\", pccb->cmd[0]);\n+\t\treturn -ENOTSUPP;\n+\t}\n+\n+\tif (ret) {\n+\t\tdebug(\"SCSI command 0x%02x ret errno %d\\n\", pccb->cmd[0], ret);\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int fsl_ahci_probe(struct udevice *dev)\n+{\n+\tstruct fsl_ahci_priv *priv = dev_get_priv(dev);\n+\tstruct udevice *child_dev;\n+\tstruct scsi_platdata *uc_plat;\n+\n+\tdevice_find_first_child(dev, &child_dev);\n+\tif (!child_dev)\n+\t\treturn -ENODEV;\n+\tuc_plat = dev_get_uclass_platdata(child_dev);\n+\tuc_plat->base = priv->base;\n+\tuc_plat->max_lun = 1;\n+\tuc_plat->max_id = 1;\n+\n+\treturn init_sata(priv);\n+}\n+\n+struct scsi_ops fsl_scsi_ops = {\n+\t.exec\t\t= fsl_ahci_scsi_exec,\n+};\n+\n+static const struct udevice_id fsl_ahci_ids[] = {\n+\t{ .compatible = \"fsl,pq-sata-v2\" },\n+\t{ }\n+};\n+\n+U_BOOT_DRIVER(fsl_ahci_scsi) = {\n+\t.name\t\t= \"fsl_ahci_scsi\",\n+\t.id\t\t= UCLASS_SCSI,\n+\t.ops\t\t= &fsl_scsi_ops,\n+};\n+\n+U_BOOT_DRIVER(fsl_ahci) = {\n+\t.name\t= \"fsl_ahci\",\n+\t.id\t= UCLASS_AHCI,\n+\t.of_match = fsl_ahci_ids,\n+\t.bind\t= fsl_ahci_bind,\n+\t.ofdata_to_platdata = fsl_ahci_ofdata_to_platdata,\n+\t.probe\t= fsl_ahci_probe,\n+\t.priv_auto_alloc_size = sizeof(struct fsl_ahci_priv),\n+};\ndiff --git a/drivers/ata/fsl_sata.h b/drivers/ata/fsl_sata.h\nindex 1e2da10b02..a4ee83d187 100644\n--- a/drivers/ata/fsl_sata.h\n+++ b/drivers/ata/fsl_sata.h\n@@ -312,6 +312,7 @@ typedef struct fsl_sata {\n \tint\t\twcache;\n \tint\t\tflush;\n \tint\t\tflush_ext;\n+\tu32\t\tdma_flag;\n } fsl_sata_t;\n \n #define READ_CMD\t0\n", "prefixes": [ "U-Boot", "1/4" ] }