From patchwork Thu Jan 4 06:20:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siva Durga Prasad Paladugu X-Patchwork-Id: 855399 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=xilinx.onmicrosoft.com header.i=@xilinx.onmicrosoft.com header.b="qOAOlMRL"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zByST2QKgz9s7M for ; Thu, 4 Jan 2018 17:24:25 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id EAFFAC21DDE; Thu, 4 Jan 2018 06:21:18 +0000 (UTC) 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=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id E9DC7C21DF1; Thu, 4 Jan 2018 06:20:00 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 93AD7C21C4F; Thu, 4 Jan 2018 06:19:56 +0000 (UTC) Received: from NAM02-BL2-obe.outbound.protection.outlook.com (mail-bl2nam02on0082.outbound.protection.outlook.com [104.47.38.82]) by lists.denx.de (Postfix) with ESMTPS id 7C782C21C4F for ; Thu, 4 Jan 2018 06:19:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector1-xilinx-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=zdAUC9c7XraBQVUNNvQnqn8tTwpsrWi4SooKPkfXExc=; b=qOAOlMRLcVMvoWLH6DFqFMQBw+hBdI6S676FbC6I9UfaxhwNI8LTIP+wWKqno/mGlVyaYL42CnvjNBi/WNX607JIPFL+iaDMFXBuYwJv1/PDsrYoHtK3XDive7FVafOcUxOtpvja+G2y/1Yat0V7VqyTOjw/80ymlAyoqI1u558= Received: from BY2PR02CA0096.namprd02.prod.outlook.com (10.163.44.150) by MWHPR02MB3389.namprd02.prod.outlook.com (10.164.187.166) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.386.5; Thu, 4 Jan 2018 06:19:51 +0000 Received: from CY1NAM02FT044.eop-nam02.prod.protection.outlook.com (2a01:111:f400:7e45::202) by BY2PR02CA0096.outlook.office365.com (2a01:111:e400:5261::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.386.5 via Frontend Transport; Thu, 4 Jan 2018 06:19:51 +0000 Authentication-Results: spf=pass (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; samsung.com; dkim=none (message not signed) header.d=none;samsung.com; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.60.100 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.60.100; helo=xsj-pvapsmtpgw02; Received: from xsj-pvapsmtpgw02 (149.199.60.100) by CY1NAM02FT044.mail.protection.outlook.com (10.152.75.137) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.345.12 via Frontend Transport; Thu, 4 Jan 2018 06:19:50 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66]:43358 helo=xsj-pvapsmtp01) by xsj-pvapsmtpgw02 with esmtp (Exim 4.63) (envelope-from ) id 1eWysX-0006KU-R2; Wed, 03 Jan 2018 22:19:49 -0800 Received: from [127.0.0.1] (helo=localhost) by xsj-pvapsmtp01 with smtp (Exim 4.63) (envelope-from ) id 1eWysX-0004Kr-OR; Wed, 03 Jan 2018 22:19:49 -0800 Received: from xsj-pvapsmtp01 (xsj-smtp.xilinx.com [149.199.38.66]) by xsj-smtp-dlp1.xlnx.xilinx.com (8.13.8/8.13.1) with ESMTP id w046JlRT012805; Wed, 3 Jan 2018 22:19:47 -0800 Received: from [172.23.37.99] (helo=xhdsivadur40.xilinx.com) by xsj-pvapsmtp01 with esmtp (Exim 4.63) (envelope-from ) id 1eWysU-0004Gi-VR; Wed, 03 Jan 2018 22:19:47 -0800 From: Siva Durga Prasad Paladugu To: Date: Thu, 4 Jan 2018 11:50:15 +0530 Message-ID: <1515046816-27217-7-git-send-email-sivadur@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515046816-27217-1-git-send-email-sivadur@xilinx.com> References: <1515046816-27217-1-git-send-email-sivadur@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.2.0.1013-23570.006 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.60.100; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(39860400002)(376002)(396003)(39380400002)(346002)(2980300002)(438002)(189003)(199004)(81166006)(2950100002)(305945005)(106002)(6666003)(81156014)(2351001)(36756003)(106466001)(356003)(8936002)(6916009)(8676002)(9786002)(107886003)(54906003)(5660300001)(16586007)(48376002)(7696005)(77096006)(47776003)(59450400001)(50226002)(316002)(51416003)(63266004)(4326008)(478600001)(2906002)(36386004)(76176011)(50466002)(107986001)(5001870100001); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR02MB3389; H:xsj-pvapsmtpgw02; FPR:; SPF:Pass; PTR:xapps1.xilinx.com,unknown-60-100.xilinx.com; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; CY1NAM02FT044; 1:7eUtjgw8VUZVxFNY8XO0Yqgfliof8B0TQmr2SM9QBezcqtCjrMXpIBXWdH0PSo82+z7ZENP3ex1IoQ3MLxBeEwgTbtDYgNWk3RIzWlevUkvuq8ZteamEttFv5Pv5S3a0 MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 3959bbc3-4efb-431e-19f2-08d5533b2973 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4608076)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603307)(7153060); SRVR:MWHPR02MB3389; X-Microsoft-Exchange-Diagnostics: 1; MWHPR02MB3389; 3:NlYINUikTCXGLe8xz9wg1xCCmvK1BZnc5SET1gVgEb4bdJ4IKfyz2hWrKaVeCy50wBs5TNBT+a5Bm2GcHNsa5ago7wumSxXpm9MMKekAx02Bbpi6O8ayiUu05dd+5Xy6oa0xljgMvm9xSx7lAoLXtGFRsO2xH+bs7kd8oYcAib7UCrqxa1XzvmqPUZ8lrE59HJfM8+MObF+HFX7s0100zuWMww4KC/xtn/Fv+Z1UoTHRNKj93Bzbmgh1w3GTr8qjpqU9v6l7zTnKDbasihvyqpe0RPtaHcC45gWi8B7P1Fh9YeiRlprr2RKpBi2E+VPVHJnm/XpBcuUTntoaWfu8Lv7iW0/nHF8a9zlg3849Z0E=; 25:44fS7nLCKozYHzGoK20Ur8IJkli7abpVy8ebJU9wmxwU9Gi+twzncbhYXa4XZMLaCkTub5U2fgpGXw6EviUn35S6rl3KKB4pxwz2iTj3Sht0lrYnC5GA1eCx1FoBZj36UIJ63quQ/QKFywMc/IeEjiqNnnGP+lR9nmNm3dhI22V2wSa/zQ1hBrg5TSlcUn/JePaDSYuaSyXp0jV9JLidymkEbtKGQyucCb/GjCAYMYqIhAwJoA06Yffst0OIabNc2xnZKHZFFXpoC2SbTZ68u5STfzQyJVQhapFLyImHdpHH+LJJHtk1P5SXsZpiq5aVYRYylB8C1c4YMimh+ouMOg== X-MS-TrafficTypeDiagnostic: MWHPR02MB3389: X-Microsoft-Exchange-Diagnostics: 1; MWHPR02MB3389; 31:OfIvm5oIoe/D0fRaBeoM/zgi9zMX2z6OFWXfjTq/oTilOZZQQg2atFwfMPocjfXYKscAMNfL2i1aSIg+5T+pAEotz8uGtKIok2UDPTlyztl9LvS0oo4rFQCwZuH98IlAqOgcS6RcXp34pzggSt0N6JJL4FpFyfSpoTr/y2Q17IWXiX4JbFjif8evDNU2U1nNtbbuFKX219N5sOghfZd+slZqc6Mo2U0EWnXTZXcvsOI=; 20:WvqktJPJ11IY5sZJrUVYhDStXghvYycvWMET6Z86SwgSXcOi0fvlmIQVqX5yCprrog024cSZaJWSqxQvR2TlEWWReDmhKn7SxcKEQZ7mhsVtrugJVzFb3VAvjQScijgJRkS8bFbpaRFlS//rH70BOu8GK6L0NPJ+1hdpMafMa1xEwP6E9st2QMM4S+lpFvUDEqtO+UomH80wDk0Q0qVA+F9zc4OgFyYb/QDj3+2xWkdgNGKuaJNgeN7JxGwIbBpfNa2VBYWUDysSyZTxRyhck5W9yXysHVtvtsSzNt0Wu6ClkNFAyKH+4b6rFNHIO8bAnRydgMlN1tMtJT/oUlezZvtIoTYhHW2YUEJGPhJlTcCfQUloWEcujxJws/8Wj2LIJmAQx7MVab6yOS4/C3v2hG2dTnoLzVIOcMOWtqE9v4QAk7KPgwDqVdeyjoyqfPPVPKDe4Vdh232d+HZNJo2hDoHB+P0SlTP8OUT0N2gwuSHWINnK0KymvBYXvKC+9Jx9 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040470)(2401047)(5005006)(8121501046)(3231023)(944501075)(93006095)(93004095)(3002001)(10201501046)(6055026)(6041268)(20161123558120)(20161123564045)(20161123562045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011); SRVR:MWHPR02MB3389; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:MWHPR02MB3389; X-Microsoft-Exchange-Diagnostics: 1; MWHPR02MB3389; 4:POCX6FTh+lu/9kPxu1YxNhg0MP7p9T8Zu1W4KQLtMHlw5V7k+IIA8YZ9INn94S1SSc0OgTkz+Z84PiT+E3tJJm6kDjReAGpJ0rmxhWrEzMrnfwNaqA6CRkV+QVhS9xO4pgdh5Zb48jjQPbjoWyQAtclTV5dxe3LyFfRnVAfAv6Ng0njyiomWif1NGxSX/yBJNk19cyzhfmuQubxapEGVpB8TLGBMkVn1JrBQuWE5j+h0Tyy6ACDIfYMTugpu7UcarcpKEgTxmSFq27YR13RzxU/oJbPnFptztyVjE8K3xmgxchM1beyOx3Yvdk+4pEUD X-Forefront-PRVS: 054231DC40 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR02MB3389; 23:Ru3JMoFxovAT/rNLS6OwwPiDTHjs2/Jyq+5FNss8u?= 1V2V87lr8PfwFUlyV/V4orhMYRsKwvgN/szsGShIi/mQ07IzSwyTFtbjgwS6E3qen2eDoF+KrJGT7mfcMzuOk5wCGBwXP3hg2tPvZxCV0IlXBCxqRiFNA1SGFQ7WxZ2ovl+EMB39RTRJSP2j1+1MHFLKGL97jDCBYbbjCb6Yov1sfvGA9m/lRzqrOerpAP5hV+Ak0xB6Pt5aH8zVx6GF93WWdFbuO0Mbx3NkC75mQeeLPI3aVuvwJfoLIHD0mad/nyzdBmmeDj8emVIkpTxHKTrUHHmkn6Wny7sCPYYLVyfdtur1igt6dD2hsHF6T0Jepk6jUNCOOi/D2YE0nF/wbZu/lhHi7gaghBmMw5CbIFXrnMDSsY7KnBGf86ewcEiTXy+BRZTl7C1jyrHgOAGGLZtcISIE6cLqcPFST04OE2WREfiRYCl6LtcGLB2FyM8Iu7qE2Xu4G6wEogOiak2BuSjdwx2NsKXVYsuJaqDdow/a4pxqpnfDvtXxucZaSVO95PtMLfaHWvSO80t7ViBwYhVhihg2qZFLG+RIsA7F9iLPm+pVoWWlLzdhUP/MFSV0g0ieqH6VjkFSemAXFDqDDqN5Nj7/1Caw29ilY8XAAgsqfe2YNuXgfrPPLmxx/JW2V/RKUnG4QeqoAKLVaAxwdrPTsfx1nfo//v57zzByt9L3UWrPHNxH4fDSfpcYPPRjMoiBoyGW8aSQKYkIwDdrwO2W8kkGWCohO1AysQpqYBkYfnUAPA0+Rg6aEw5ClIhOKMlJs6nv50nsSkb9mMdA1jI9/7fwWtnwTHadVl2dvoVVMMzDZY5FYVbjeo0ZOZKghTQ6MpVbM2/AD9UehimNsMsoJtRGlrnLj8qT4jLzdTb00L8I1OyXvXTtmmsuJUkvzaLcnzsrHvNpJ28k4WN649vAxoKyxnTKTRC1Af2q8ln78QYTZZTbvX6RIY42PQNVmWtwC3Gz/5o2wBeaS5SodG25+AZyudtxgqEOP3zQa9w1yolX2PtHWFysnE4QoKpMvg= X-Microsoft-Exchange-Diagnostics: 1; MWHPR02MB3389; 6:94/Y4oRH96iEhnYWkjshGDnW0IvvVV4WUpL8S6xHe5H89VQnVXOGTnckyhMYkU0MikkNz3bpXLNlIvEaHyqYlh8K3pZx3eYVIKaP3uBwOY0HDH3feug037vQ/uYQpcPq3c9W52+BKj8WZ0koiurkVhi+SgEwZbqBKGDkWyCjWGycrTAhOtL/ElQRGBkdCx5GSzmnXDp49KO3WClqgkpaPSBqbWXz7DFzRF1XhpuMk8dI+T7vvTpZSG4bvESfJTzCGTMj9H1jLoqLS/jNgKKLh8n1tAs5YYEXntFnOAv7UkAlN4JM1p92B46FzOu3rZgajBa+zKp9/y2dwWSA4Bw0GeO6Bo/ufZssJWYZ5ez8dhI=; 5:gh3f+MQdRzrDGhTc8IJatvyttpjYOJ3l5bUX8vlckAZ88TMyk3I45fnGlMko5MDeqOo9Jx2CuaWsDHE8lafEb7uOg4icHmIC3tZHfcLwvbrOsj9yKMj5sbATzEcLQbBfE1s330edYsksU5uIx1Ib0jfpslzCD3u6pZyH+5Gpcg4=; 24:QUSrrQlmxa/Na/KKluf9yXiZIVkSwgVHx49kznntrzXAY492mdEBZnlE4bjVdCcu5cKRtZy3DaJiNZXwSrN596neL1jiojfVHCRBcX+gZjo=; 7:7lRbaxuiBke0mXpl3D/SJvc5spGovEwbWf8+g8lL5qn9oLluF2eKnLJnPwTBYIjn6ZunpPB3J0FZykajXmAeqWfypHnEuu7pYv2JgmoHXNoba/tG12rPR364sx1XU93gWlVhLMSlePJon4S0swwHX23gXPvw1G43iq2n/EzEixn8+w66W9Wzz9xnCjHI8q8L0o4FGKisMhcf8zY3Majxwf1zYav/gxMOLumUXbjFzgyfomdiBHScQ1xiEBUg1TfZ SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Jan 2018 06:19:50.3253 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 3959bbc3-4efb-431e-19f2-08d5533b2973 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.60.100]; Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR02MB3389 Cc: Siva Durga Prasad Paladugu Subject: [U-Boot] [PATCH 6/7] mmc: zynq_sdhci: Add support for SD3.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds support of SD3.0 for ZynqMP. Signed-off-by: Siva Durga Prasad Paladugu --- board/xilinx/zynqmp/Makefile | 2 + board/xilinx/zynqmp/tap_delays.c | 230 +++++++++++++++++++++++++++++++++++++++ drivers/mmc/zynq_sdhci.c | 230 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 board/xilinx/zynqmp/tap_delays.c diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 75aab92..f2e4d26 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -26,6 +26,8 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),) obj-y += $(init-objs) endif +obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o + # Suppress "warning: function declaration isn't a prototype" CFLAGS_REMOVE_psu_init_gpl.o := -Wstrict-prototypes diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c new file mode 100644 index 0000000..9c93291 --- /dev/null +++ b/board/xilinx/zynqmp/tap_delays.c @@ -0,0 +1,230 @@ +/* + * Xilinx ZynqMP SoC Tap Delay Programming + * + * Copyright (C) 2016 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#define SD_DLL_CTRL 0xFF180358 +#define SD_ITAP_DLY 0xFF180314 +#define SD_OTAP_DLY 0xFF180318 +#define SD0_DLL_RST_MASK 0x00000004 +#define SD0_DLL_RST 0x00000004 +#define SD1_DLL_RST_MASK 0x00040000 +#define SD1_DLL_RST 0x00040000 +#define SD0_ITAPCHGWIN_MASK 0x00000200 +#define SD0_ITAPCHGWIN 0x00000200 +#define SD1_ITAPCHGWIN_MASK 0x02000000 +#define SD1_ITAPCHGWIN 0x02000000 +#define SD0_ITAPDLYENA_MASK 0x00000100 +#define SD0_ITAPDLYENA 0x00000100 +#define SD1_ITAPDLYENA_MASK 0x01000000 +#define SD1_ITAPDLYENA 0x01000000 +#define SD0_ITAPDLYSEL_MASK 0x000000FF +#define SD0_ITAPDLYSEL_HSD 0x00000015 +#define SD0_ITAPDLYSEL_SD_DDR50 0x0000003D +#define SD0_ITAPDLYSEL_MMC_DDR50 0x00000012 + +#define SD1_ITAPDLYSEL_MASK 0x00FF0000 +#define SD1_ITAPDLYSEL_HSD 0x00150000 +#define SD1_ITAPDLYSEL_SD_DDR50 0x003D0000 +#define SD1_ITAPDLYSEL_MMC_DDR50 0x00120000 + +#define SD0_OTAPDLYSEL_MASK 0x0000003F +#define SD0_OTAPDLYSEL_MMC_HSD 0x00000006 +#define SD0_OTAPDLYSEL_SD_HSD 0x00000005 +#define SD0_OTAPDLYSEL_SDR50 0x00000003 +#define SD0_OTAPDLYSEL_SDR104_B0 0x00000003 +#define SD0_OTAPDLYSEL_SDR104_B2 0x00000002 +#define SD0_OTAPDLYSEL_SD_DDR50 0x00000004 +#define SD0_OTAPDLYSEL_MMC_DDR50 0x00000006 + +#define SD1_OTAPDLYSEL_MASK 0x003F0000 +#define SD1_OTAPDLYSEL_MMC_HSD 0x00060000 +#define SD1_OTAPDLYSEL_SD_HSD 0x00050000 +#define SD1_OTAPDLYSEL_SDR50 0x00030000 +#define SD1_OTAPDLYSEL_SDR104_B0 0x00030000 +#define SD1_OTAPDLYSEL_SDR104_B2 0x00020000 +#define SD1_OTAPDLYSEL_SD_DDR50 0x00040000 +#define SD1_OTAPDLYSEL_MMC_DDR50 0x00060000 + +#define MMC_BANK2 0x2 + +#define MMC_TIMING_UHS_SDR25 1 +#define MMC_TIMING_UHS_SDR50 2 +#define MMC_TIMING_UHS_SDR104 3 +#define MMC_TIMING_UHS_DDR50 4 +#define MMC_TIMING_MMC_HS200 5 +#define MMC_TIMING_SD_HS 6 +#define MMC_TIMING_MMC_DDR52 7 +#define MMC_TIMING_MMC_HS 8 + +void zynqmp_dll_reset(u8 deviceid) +{ + /* Issue DLL Reset */ + if (deviceid == 0) + zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, + SD0_DLL_RST); + else + zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, + SD1_DLL_RST); + + mdelay(1); + + /* Release DLL Reset */ + if (deviceid == 0) + zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0); + else + zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0); +} + +static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank) +{ + if (deviceid == 0) { + /* Program OTAP */ + if (bank == MMC_BANK2) + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_SDR104_B2); + else + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_SDR104_B0); + } else { + /* Program OTAP */ + if (bank == MMC_BANK2) + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_SDR104_B2); + else + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_SDR104_B0); + } +} + +static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank) +{ + if (deviceid == 0) { + /* Program ITAP */ + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, + SD0_ITAPCHGWIN); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK, + SD0_ITAPDLYENA); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, + SD0_ITAPDLYSEL_HSD); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0); + /* Program OTAP */ + if (timing == MMC_TIMING_MMC_HS) + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_MMC_HSD); + else + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_SD_HSD); + } else { + /* Program ITAP */ + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, + SD1_ITAPCHGWIN); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK, + SD1_ITAPDLYENA); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, + SD1_ITAPDLYSEL_HSD); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0); + /* Program OTAP */ + if (timing == MMC_TIMING_MMC_HS) + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_MMC_HSD); + else + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_SD_HSD); + } +} + +static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank) +{ + if (deviceid == 0) { + /* Program ITAP */ + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, + SD0_ITAPCHGWIN); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK, + SD0_ITAPDLYENA); + if (timing == MMC_TIMING_UHS_DDR50) + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, + SD0_ITAPDLYSEL_SD_DDR50); + else + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, + SD0_ITAPDLYSEL_MMC_DDR50); + zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0); + /* Program OTAP */ + if (timing == MMC_TIMING_UHS_DDR50) + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_SD_DDR50); + else + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_MMC_DDR50); + } else { + /* Program ITAP */ + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, + SD1_ITAPCHGWIN); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK, + SD1_ITAPDLYENA); + if (timing == MMC_TIMING_UHS_DDR50) + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, + SD1_ITAPDLYSEL_SD_DDR50); + else + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, + SD1_ITAPDLYSEL_MMC_DDR50); + zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0); + /* Program OTAP */ + if (timing == MMC_TIMING_UHS_DDR50) + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_SD_DDR50); + else + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_MMC_DDR50); + } +} + +static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank) +{ + if (deviceid == 0) { + /* Program OTAP */ + zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, + SD0_OTAPDLYSEL_SDR50); + } else { + /* Program OTAP */ + zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, + SD1_OTAPDLYSEL_SDR50); + } +} + +void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank) +{ + if (deviceid == 0) + zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, + SD0_DLL_RST); + else + zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, + SD1_DLL_RST); + + switch (timing) { + case MMC_TIMING_UHS_SDR25: + arasan_zynqmp_tap_hs(deviceid, timing, bank); + break; + case MMC_TIMING_UHS_SDR50: + arasan_zynqmp_tap_sdr50(deviceid, timing, bank); + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + arasan_zynqmp_tap_sdr104(deviceid, timing, bank); + break; + case MMC_TIMING_UHS_DDR50: + arasan_zynqmp_tap_ddr50(deviceid, timing, bank); + break; + } + + if (deviceid == 0) + zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0); + else + zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0); +} diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 0fddb42..34d9b66 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -12,7 +12,9 @@ #include #include #include +#include "mmc_private.h" #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -26,15 +28,211 @@ struct arasan_sdhci_plat { unsigned int f_max; }; +struct arasan_sdhci_priv { + struct sdhci_host *host; + u8 deviceid; + u8 bank; + u8 no_1p8; + bool pwrseq; +}; + +#if defined(CONFIG_ARCH_ZYNQMP) +static const u8 mode2timing[] = { + [UHS_SDR12] = UHS_SDR12_BUS_SPEED, + [UHS_SDR25] = UHS_SDR25_BUS_SPEED, + [UHS_SDR50] = UHS_SDR50_BUS_SPEED, + [UHS_SDR104] = UHS_SDR104_BUS_SPEED, + [UHS_DDR50] = UHS_DDR50_BUS_SPEED, +}; + +#define SDHCI_HOST_CTRL2 0x3E +#define SDHCI_CTRL2_MODE_MASK 0x7 +#define SDHCI_18V_SIGNAL 0x8 +#define SDHCI_CTRL_EXEC_TUNING 0x0040 +#define SDHCI_CTRL_TUNED_CLK 0x80 + +static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid) +{ + u16 clk; + unsigned long timeout; + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + clk &= ~(SDHCI_CLOCK_CARD_EN); + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Issue DLL Reset */ + zynqmp_dll_reset(deviceid); + + /* Wait max 20 ms */ + timeout = 100; + while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) + & SDHCI_CLOCK_INT_STABLE)) { + if (timeout == 0) { + dev_err(mmc_dev(host->mmc), + ": Internal clock never stabilised.\n"); + return; + } + timeout--; + udelay(1000); + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +} + +static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) +{ + struct mmc_cmd cmd; + struct mmc_data data; + u32 ctrl; + struct sdhci_host *host; + struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev); + u8 tuning_loop_counter = 40; + u8 deviceid; + + printf("%s\n", __func__); + + host = priv->host; + deviceid = priv->deviceid; + + ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2); + ctrl |= SDHCI_CTRL_EXEC_TUNING; + sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2); + + mdelay(1); + + arasan_zynqmp_dll_reset(host, deviceid); + + sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); + sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); + + do { + cmd.cmdidx = opcode; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 0; + + data.blocksize = 64; + data.blocks = 1; + data.flags = MMC_DATA_READ; + + if (tuning_loop_counter-- == 0) + break; + + if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 && + mmc->bus_width == 8) + data.blocksize = 128; + + sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, + data.blocksize), + SDHCI_BLOCK_SIZE); + sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT); + sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); + + mmc_send_cmd(mmc, &cmd, NULL); + ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2); + + if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK) + udelay(1); + + } while (ctrl & SDHCI_CTRL_EXEC_TUNING); + + if (tuning_loop_counter < 0) { + ctrl &= ~SDHCI_CTRL_TUNED_CLK; + sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2); + } + + if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { + printf("%s:Tuning failed\n", __func__); + return -1; + } + + udelay(1); + arasan_zynqmp_dll_reset(host, deviceid); + + /* Enable only interrupts served by the SD controller */ + sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, + SDHCI_INT_ENABLE); + /* Mask all sdhci interrupt sources */ + sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE); + + return 0; +} + +static void arasan_sdhci_set_tapdelay(struct sdhci_host *host) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct mmc *mmc = (struct mmc *)host->mmc; + u8 uhsmode; + + if (IS_SD(mmc)) + uhsmode = mode2timing[mmc->selected_mode]; + else + return; + + if (uhsmode >= UHS_SDR25_BUS_SPEED) + arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode, + priv->bank); +} + +static void arasan_sdhci_set_control_reg(struct sdhci_host *host) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + u32 reg; + + if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { + reg = sdhci_readw(host, SDHCI_HOST_CTRL2); + reg |= SDHCI_18V_SIGNAL; + sdhci_writew(host, reg, SDHCI_HOST_CTRL2); + } + + if (mmc->selected_mode > SD_HS && + mmc->selected_mode <= UHS_DDR50) { + reg = sdhci_readw(host, SDHCI_HOST_CTRL2); + reg &= ~SDHCI_CTRL2_MODE_MASK; + switch (mmc->selected_mode) { + case UHS_SDR12: + reg |= UHS_SDR12_BUS_SPEED; + break; + case UHS_SDR25: + reg |= UHS_SDR25_BUS_SPEED; + break; + case UHS_SDR50: + reg |= UHS_SDR50_BUS_SPEED; + break; + case UHS_SDR104: + reg |= UHS_SDR104_BUS_SPEED; + break; + case UHS_DDR50: + reg |= UHS_DDR50_BUS_SPEED; + break; + default: + break; + } + sdhci_writew(host, reg, SDHCI_HOST_CTRL2); + } +} +#endif + +#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP) +const struct sdhci_ops arasan_ops = { + .platform_execute_tuning = &arasan_sdhci_execute_tuning, + .set_delay = &arasan_sdhci_set_tapdelay, + .set_control_reg = &arasan_sdhci_set_control_reg, +}; +#endif + static int arasan_sdhci_probe(struct udevice *dev) { struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); - struct sdhci_host *host = dev_get_priv(dev); + struct arasan_sdhci_priv *priv = dev_get_priv(dev); + struct sdhci_host *host; struct clk clk; unsigned long clock; int ret; + host = priv->host; + ret = clk_get_by_index(dev, 0, &clk); if (ret < 0) { dev_err(dev, "failed to get clock\n"); @@ -46,7 +244,6 @@ static int arasan_sdhci_probe(struct udevice *dev) dev_err(dev, "failed to get rate\n"); return clock; } - debug("%s: CLK %ld\n", __func__, clock); ret = clk_enable(&clk); if (ret && ret != -ENOSYS) { @@ -61,6 +258,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif + if (priv->no_1p8) + host->quirks |= SDHCI_QUIRK_NO_1_8_V; + host->max_clk = clock; ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, @@ -78,10 +278,28 @@ static int arasan_sdhci_probe(struct udevice *dev) static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) { struct arasan_sdhci_plat *plat = dev_get_platdata(dev); - struct sdhci_host *host = dev_get_priv(dev); + struct arasan_sdhci_priv *priv = dev_get_priv(dev); + + priv->host = calloc(1, sizeof(struct sdhci_host)); + if (!priv->host) + return -1; - host->name = dev->name; - host->ioaddr = (void *)devfdt_get_addr(dev); + priv->host->name = dev->name; + priv->host->ioaddr = (void *)devfdt_get_addr(dev); + + priv->deviceid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "xlnx,device_id", -1); + priv->bank = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "xlnx,mio_bank", -1); + if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), + "no-1-8-v", NULL)) + priv->no_1p8 = 1; + else + priv->no_1p8 = 0; + +#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP) + priv->host->ops = &arasan_ops; +#endif plat->f_max = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ); @@ -109,6 +327,6 @@ U_BOOT_DRIVER(arasan_sdhci_drv) = { .ops = &sdhci_ops, .bind = arasan_sdhci_bind, .probe = arasan_sdhci_probe, - .priv_auto_alloc_size = sizeof(struct sdhci_host), + .priv_auto_alloc_size = sizeof(struct arasan_sdhci_priv), .platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat), };