From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F3F57C433EF for ; Wed, 15 Dec 2021 10:02:07 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D052283054; Wed, 15 Dec 2021 11:02:05 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=xilinx.onmicrosoft.com header.i=@xilinx.onmicrosoft.com header.b="OVTkcFTn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7E8EF83055; Wed, 15 Dec 2021 11:02:04 +0100 (CET) Received: from NAM12-DM6-obe.outbound.protection.outlook.com (mail-dm6nam12on20610.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe59::610]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DF76683053 for ; Wed, 15 Dec 2021 11:01:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=michals@xilinx.com ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=b8LMmPfDlKlNng1mEHlIApZOj56G0wcJ/tx7lfZXB+uGVv7e3zwSdFx0tlupRAvbI8kTPs4lJRaF1FamT5+zzZYqW3yoqKRlpXP2qkKtcS4NcL2WI9ORHRi8z2M5rdg7lUoSz/n6ErcWOsixaDi+0N6zkmcZm4I7s+C8760NpB+L0NY5J8JtS+LF34+VVy5uUpaPI6+FyMjC0j+pLurR6CFMXrKtW1NYDFLra1LaDgwhB8+cGSY/I3K3romUVh9rFUZ2LVs0vALasqZ9DvdfD45foi3K7wzS83Jhf778nQN4a453ODKDivoYTr71tfOJicf5i/Dl7r01QVm4T5eTaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=zaSiUPc+q71Czvv4MgDXZlKsHIOPl4Nv+bARuJ13PJM=; b=FOxXvtkTsjmuFSMBMKEzOnukF/m/qjwLaqeep0E/hr2bh/7F4iC+z87OC3Wziwbp2IRAdTXI/j2hr3EQIar5JOilMQSpHb70SSAqlM0Nfe5jDU8kA5Xx8P13C2PWMnQb/Y8Y4NEq6wtMDrcsOjW7ReF0mP/1Keyohkuvza40diU2d285ezxK3Z8C5ZExmyOoQv1FfEQEFmPKGfPdVtuUWgmfmT9hIJglZV9auybXW+id26NBFPKR8bx8Um58qiiCrTv0QRU2/e/Gqy5D0xm8v/X++kx/Dk+41NWOA59NW0pZ/UQSGmDiAKWNfyoB8OAg5SdmZIvo45+ErvMH0r4jmA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=seco.com smtp.mailfrom=xilinx.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=zaSiUPc+q71Czvv4MgDXZlKsHIOPl4Nv+bARuJ13PJM=; b=OVTkcFTn2yJcyJgx3jcnKNP+g52iQf0CADTuqbeRaEN+sqMhvI727dd0Uz3XdxXkzedzCTzyZ3qGKYC+AYtL/z/YsfjKr70IbReau9EmGp58QpQC0tzpU1etoP3pn8XeXZdLr4t770loHnLP5VZKUbnN93v8w05EIUK6ywCprlE= Received: from BN6PR18CA0014.namprd18.prod.outlook.com (2603:10b6:404:121::24) by BY5PR02MB6035.namprd02.prod.outlook.com (2603:10b6:a03:1b1::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4778.11; Wed, 15 Dec 2021 10:01:52 +0000 Received: from BN1NAM02FT047.eop-nam02.prod.protection.outlook.com (2603:10b6:404:121:cafe::fb) by BN6PR18CA0014.outlook.office365.com (2603:10b6:404:121::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4778.13 via Frontend Transport; Wed, 15 Dec 2021 10:01:52 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch01.xlnx.xilinx.com; Received: from xsj-pvapexch01.xlnx.xilinx.com (149.199.62.198) by BN1NAM02FT047.mail.protection.outlook.com (10.13.3.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.4801.14 via Frontend Transport; Wed, 15 Dec 2021 10:01:52 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.14; Wed, 15 Dec 2021 02:01:27 -0800 Received: from smtp.xilinx.com (172.19.127.95) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server id 15.1.2176.14 via Frontend Transport; Wed, 15 Dec 2021 02:01:27 -0800 Envelope-to: git@xilinx.com, sean.anderson@seco.com, u-boot@lists.denx.de, adouglas@cadence.com, jjhiblot@ti.com, joe.hershberger@ni.com, kishon@ti.com, lokeshvutla@ti.com, narmstrong@baylibre.com, sjg@chromium.org, stephan@gerhold.net, vigneshr@ti.com, weijie.gao@mediatek.com, ye.li@nxp.com Received: from [10.254.241.49] (port=55030) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1mxR69-000Fhm-5E; Wed, 15 Dec 2021 02:01:21 -0800 Message-ID: Date: Wed, 15 Dec 2021 11:01:17 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.4.0 Subject: Re: [PATCH] phy: zynqmp: Add serdes/psgtr driver Content-Language: en-US To: Sean Anderson , Michal Simek , , CC: Alan Douglas , Jean-Jacques Hiblot , Joe Hershberger , "Kishon Vijay Abraham I" , Lokesh Vutla , Neil Armstrong , Simon Glass , Stephan Gerhold , Vignesh Raghavendra , Weijie Gao , Ye Li References: <947922ceb12a7db388fc63eddd3dcc9b8a8a1208.1637238602.git.michal.simek@xilinx.com> <3d39c0c4-7858-5d5a-30de-c3e2364a8f6f@seco.com> <188ab67c-af2a-ced1-e791-fefee3c86af8@xilinx.com> From: Michal Simek In-Reply-To: Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2182423d-977c-4fa7-76ac-08d9bfb1eb00 X-MS-TrafficTypeDiagnostic: BY5PR02MB6035:EE_ X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:125; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: UKzkPu2Y8tl5HbWBAXBKRPgvOQxrDFmVH/HcqjY9ay97/qwR7TisQneHr82k0tvNPZX9kM6ZXKzPa6Az+7iRcR2gQic/DWe7TAHOwlKH+GHWdIJiyQlv8SJP8fMkSbXOx3EwqooEtai/OhJdph0epI0ILG7INfpV1S+qh0wDlCSuxkHnLAh1bQNuQ8tolH2vMQ6hgk9dSXlSavaV9dN03ktvuRXv2HWHYfQvFfxgN0XvySu5Dl33M1JkE9dyzVTqPicqsc7z1T5Hc7MZR4PoL2ipBsNSGHepMMkccenKMIlPOENLKQIw2DWGJROd3C5MfP1S3Kjjp8rjtRh3Akw9IIb337q2fqBn6UFuG6p1uwe2AsWiRlVAVqflAn8gkC9GJOqVkXOlAL757RMJfOWXrQ+PUJeAv8Hdj5Ic4fdDgSjL3Zvwx2GLqGMltXEIMLkp40c/+oyns/ph3dfpSICfHg0SHhtYpyXkgQSn/UtfDkOyai5PIXMy/M2t4TL8Ko98epJ0rkQADfKWNhrVBnuw56Y/jQRis0yqVffNDBM7RRu/s0YyPhjiUEpcjnbbGOPELRNrYuNnaTz5NmuDi91KlL5cTGg/dpsbh1NocCCKt896G6ZptTPQljc2tgY0FfeGKuydpFYrRns0azL9MLVB8HfPHNJ8RysREZS3SXiMFpp8R7wWK33FGR9CyDCG6ecAl8tESBMllUbOIjMc7GoUSsHaf+GbOZY26JsdE5UnpvBNhdkOEm594iCA9czm3rZBKqBP3viu+1w6mFo90VWLsQ== X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch01.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(46966006)(36840700001)(2906002)(4326008)(110136005)(8936002)(6666004)(54906003)(7416002)(36756003)(316002)(31686004)(356005)(47076005)(8676002)(36860700001)(9786002)(83380400001)(70206006)(30864003)(70586007)(26005)(31696002)(7636003)(82310400004)(6636002)(508600001)(44832011)(186003)(336012)(2616005)(5660300002)(53546011)(426003)(50156003)(43740500002); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Dec 2021 10:01:52.1022 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 2182423d-977c-4fa7-76ac-08d9bfb1eb00 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch01.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: BN1NAM02FT047.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR02MB6035 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.38 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" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean On 11/29/21 16:12, Sean Anderson wrote: > > > On 11/24/21 9:52 AM, Michal Simek wrote: >> >> >> On 11/22/21 22:53, Sean Anderson wrote: >>> >>> >>> On 11/18/21 7:30 AM, Michal Simek wrote: >>>> Add PSGTR driver for Xilinx ZynqMP. >>>> The most of configurations are taken from Linux kernel psgtr driver. >>>> >>>> USB3.0 and SGMII configurations are tested on SOM. In SGMII case also >>>> IOU_SLCR reg is updated to get proper clock setup and signal detection >>>> configuration. >>> >>> Are USB3 and SGMII all that's been tested? I noticed that the kernel >>> driver has DP- and SATA-specific stuff which has been left out. >>> Presumably they are not supported? >> >> I have tested USB3 and SGMII. I didn't test DP/SATA and there is missing some >> code for it. >> DP will be tested with u-boot driver which we will develop. >> >>> >>> Perhaps also note that the termination fix is not implemented. >> >> Terminanation fix was for v1 silicon which none is really using now that's why >> this code is not needed for newly written SW. >> >>> >>>> Signed-off-by: Michal Simek >>>> --- >>>> >>>>   MAINTAINERS              |   1 + >>>>   drivers/phy/Kconfig      |   7 + >>>>   drivers/phy/Makefile     |   1 + >>>>   drivers/phy/phy-zynqmp.c | 690 +++++++++++++++++++++++++++++++++++++++ >>>>   4 files changed, 699 insertions(+) >>>>   create mode 100644 drivers/phy/phy-zynqmp.c >>>> >>>> diff --git a/MAINTAINERS b/MAINTAINERS >>>> index 1eb71cbdad12..d1e9fbd4a279 100644 >>>> --- a/MAINTAINERS >>>> +++ b/MAINTAINERS >>>> @@ -611,6 +611,7 @@ F:    drivers/mmc/zynq_sdhci.c >>>>   F:    drivers/mtd/nand/raw/zynq_nand.c >>>>   F:    drivers/net/phy/xilinx_phy.c >>>>   F:    drivers/net/zynq_gem.c >>>> +F:    drivers/phy/phy-zynqmp.c >>>>   F:    drivers/serial/serial_zynq.c >>>>   F:    drivers/reset/reset-zynqmp.c >>>>   F:    drivers/rtc/zynqmp_rtc.c >>>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig >>>> index 4767d215f337..d79798429b18 100644 >>>> --- a/drivers/phy/Kconfig >>>> +++ b/drivers/phy/Kconfig >>>> @@ -281,6 +281,13 @@ config PHY_IMX8MQ_USB >>>>       help >>>>         Support the USB3.0 PHY in NXP i.MX8MQ SoC >>>> >>>> +config PHY_XILINX_ZYNQMP >>>> +    tristate "Xilinx ZynqMP PHY driver" >>>> +    depends on PHY && ARCH_ZYNQMP >>>> +    help >>>> +      Enable this to support ZynqMP High Speed Gigabit Transceiver >>>> +      that is part of ZynqMP SoC. >>>> + >>>>   source "drivers/phy/rockchip/Kconfig" >>>>   source "drivers/phy/cadence/Kconfig" >>>>   source "drivers/phy/ti/Kconfig" >>>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile >>>> index 13a8ade8919f..bf9b40932fe3 100644 >>>> --- a/drivers/phy/Makefile >>>> +++ b/drivers/phy/Makefile >>>> @@ -38,5 +38,6 @@ obj-$(CONFIG_MT76X8_USB_PHY) += mt76x8-usb-phy.o >>>>   obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o >>>>   obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o >>>>   obj-$(CONFIG_PHY_IMX8MQ_USB) += phy-imx8mq-usb.o >>>> +obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o >>>>   obj-y += cadence/ >>>>   obj-y += ti/ >>>> diff --git a/drivers/phy/phy-zynqmp.c b/drivers/phy/phy-zynqmp.c >>>> new file mode 100644 >>>> index 000000000000..d6fe8dcef74e >>>> --- /dev/null >>>> +++ b/drivers/phy/phy-zynqmp.c >>>> @@ -0,0 +1,690 @@ >>>> +// SPDX-License-Identifier: GPL-2.0 >>>> +/* >>>> + * phy-zynqmp.c - PHY driver for Xilinx ZynqMP GT. >>>> + * >>>> + * Copyright (C) 2018-2021 Xilinx Inc. >>>> + * >>>> + * Author: Anurag Kumar Vulisha >>>> + * Author: Subbaraya Sundeep >>>> + * Author: Laurent Pinchart >>>> + */ >>>> + >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> + >>>> +#include >>>> + >>>> +#include >>>> + >>>> +/* >>>> + * Lane Registers >>>> + */ >>>> + >>>> +/* TX De-emphasis parameters */ >>>> +#define L0_TX_ANA_TM_18            0x0048 >>>> +#define L0_TX_ANA_TM_118        0x01d8 >>>> +#define L0_TX_ANA_TM_118_FORCE_17_0    BIT(0) >>>> + >>>> +/* DN Resistor calibration code parameters */ >>>> +#define L0_TXPMA_ST_3            0x0b0c >>>> +#define L0_DN_CALIB_CODE        0x3f >>>> + >>>> +/* PMA control parameters */ >>>> +#define L0_TXPMD_TM_45            0x0cb4 >>>> +#define L0_TXPMD_TM_48            0x0cc0 >>>> +#define L0_TXPMD_TM_45_OVER_DP_MAIN    BIT(0) >>>> +#define L0_TXPMD_TM_45_ENABLE_DP_MAIN    BIT(1) >>>> +#define L0_TXPMD_TM_45_OVER_DP_POST1    BIT(2) >>>> +#define L0_TXPMD_TM_45_ENABLE_DP_POST1    BIT(3) >>>> +#define L0_TXPMD_TM_45_OVER_DP_POST2    BIT(4) >>>> +#define L0_TXPMD_TM_45_ENABLE_DP_POST2    BIT(5) >>>> + >>>> +/* PCS control parameters */ >>>> +#define L0_TM_DIG_6            0x106c >>>> +#define L0_TM_DIS_DESCRAMBLE_DECODER    0x0f >>>> +#define L0_TX_DIG_61            0x00f4 >>>> +#define L0_TM_DISABLE_SCRAMBLE_ENCODER    0x0f >>>> + >>>> +/* PLL Test Mode register parameters */ >>>> +#define L0_TM_PLL_DIG_37        0x2094 >>>> +#define L0_TM_COARSE_CODE_LIMIT        0x10 >>>> + >>>> +/* PLL SSC step size offsets */ >>>> +#define L0_PLL_SS_STEPS_0_LSB        0x2368 >>>> +#define L0_PLL_SS_STEPS_1_MSB        0x236c >>>> +#define L0_PLL_SS_STEP_SIZE_0_LSB    0x2370 >>>> +#define L0_PLL_SS_STEP_SIZE_1        0x2374 >>>> +#define L0_PLL_SS_STEP_SIZE_2        0x2378 >>>> +#define L0_PLL_SS_STEP_SIZE_3_MSB    0x237c >>>> +#define L0_PLL_STATUS_READ_1        0x23e4 >>>> + >>>> +/* SSC step size parameters */ >>>> +#define STEP_SIZE_0_MASK        0xff >>>> +#define STEP_SIZE_1_MASK        0xff >>>> +#define STEP_SIZE_2_MASK        0xff >>>> +#define STEP_SIZE_3_MASK        0x3 >>>> +#define STEP_SIZE_SHIFT            8 >>>> +#define FORCE_STEP_SIZE            0x10 >>>> +#define FORCE_STEPS            0x20 >>>> +#define STEPS_0_MASK            0xff >>>> +#define STEPS_1_MASK            0x07 >>>> + >>>> +/* Reference clock selection parameters */ >>>> +#define L0_Ln_REF_CLK_SEL(n)        (0x2860 + (n) * 4) >>>> +#define L0_REF_CLK_SEL_MASK        0x8f >>>> + >>>> +/* Calibration digital logic parameters */ >>>> +#define L3_TM_CALIB_DIG19        0xec4c >>>> +#define L3_CALIB_DONE_STATUS        0xef14 >>>> +#define L3_TM_CALIB_DIG18        0xec48 >>>> +#define L3_TM_CALIB_DIG19_NSW        0x07 >>>> +#define L3_TM_CALIB_DIG18_NSW        0xe0 >>>> +#define L3_TM_OVERRIDE_NSW_CODE         0x20 >>>> +#define L3_CALIB_DONE            0x02 >>>> +#define L3_NSW_SHIFT            5 >>>> +#define L3_NSW_PIPE_SHIFT        4 >>>> +#define L3_NSW_CALIB_SHIFT        3 >>>> + >>>> +#define PHY_REG_OFFSET            0x4000 >>>> + >>>> +/* >>>> + * Global Registers >>>> + */ >>>> + >>>> +/* Refclk selection parameters */ >>>> +#define PLL_REF_SEL(n)            (0x10000 + (n) * 4) >>>> +#define PLL_FREQ_MASK            0x1f >>>> +#define PLL_STATUS_LOCKED        0x10 >>>> + >>>> +/* Inter Connect Matrix parameters */ >>>> +#define ICM_CFG0            0x10010 >>>> +#define ICM_CFG1            0x10014 >>>> +#define ICM_CFG0_L0_MASK        0x07 >>>> +#define ICM_CFG0_L1_MASK        0x70 >>>> +#define ICM_CFG1_L2_MASK        0x07 >>>> +#define ICM_CFG2_L3_MASK        0x70 >>>> +#define ICM_CFG_SHIFT            4 >>>> + >>>> +/* Inter Connect Matrix allowed protocols */ >>>> +#define ICM_PROTOCOL_PD            0x0 >>>> +#define ICM_PROTOCOL_PCIE        0x1 >>>> +#define ICM_PROTOCOL_SATA        0x2 >>>> +#define ICM_PROTOCOL_USB        0x3 >>>> +#define ICM_PROTOCOL_DP            0x4 >>>> +#define ICM_PROTOCOL_SGMII        0x5 >>>> + >>>> +/* Test Mode common reset control  parameters */ >>>> +#define TM_CMN_RST            0x10018 >>>> +#define TM_CMN_RST_EN            0x1 >>>> +#define TM_CMN_RST_SET            0x2 >>>> +#define TM_CMN_RST_MASK            0x3 >>>> + >>>> +/* Bus width parameters */ >>>> +#define TX_PROT_BUS_WIDTH        0x10040 >>>> +#define RX_PROT_BUS_WIDTH        0x10044 >>>> +#define PROT_BUS_WIDTH_10        0x0 >>>> +#define PROT_BUS_WIDTH_20        0x1 >>>> +#define PROT_BUS_WIDTH_40        0x2 >>>> +#define PROT_BUS_WIDTH_MASK        0x3 >>>> +#define PROT_BUS_WIDTH_SHIFT        2 >>>> + >>>> +/* Number of GT lanes */ >>>> +#define NUM_LANES            4 >>>> + >>>> +/* SIOU SATA control register */ >>>> +#define SATA_CONTROL_OFFSET        0x0100 >>>> + >>>> +/* Total number of controllers */ >>>> +#define CONTROLLERS_PER_LANE        5 >>>> + >>>> +/* Protocol Type parameters */ >>>> +#define XPSGTR_TYPE_USB0        0  /* USB controller 0 */ >>>> +#define XPSGTR_TYPE_USB1        1  /* USB controller 1 */ >>>> +#define XPSGTR_TYPE_SATA_0        2  /* SATA controller lane 0 */ >>>> +#define XPSGTR_TYPE_SATA_1        3  /* SATA controller lane 1 */ >>>> +#define XPSGTR_TYPE_PCIE_0        4  /* PCIe controller lane 0 */ >>>> +#define XPSGTR_TYPE_PCIE_1        5  /* PCIe controller lane 1 */ >>>> +#define XPSGTR_TYPE_PCIE_2        6  /* PCIe controller lane 2 */ >>>> +#define XPSGTR_TYPE_PCIE_3        7  /* PCIe controller lane 3 */ >>>> +#define XPSGTR_TYPE_DP_0        8  /* Display Port controller lane 0 */ >>>> +#define XPSGTR_TYPE_DP_1        9  /* Display Port controller lane 1 */ >>>> +#define XPSGTR_TYPE_SGMII0        10 /* Ethernet SGMII controller 0 */ >>>> +#define XPSGTR_TYPE_SGMII1        11 /* Ethernet SGMII controller 1 */ >>>> +#define XPSGTR_TYPE_SGMII2        12 /* Ethernet SGMII controller 2 */ >>>> +#define XPSGTR_TYPE_SGMII3        13 /* Ethernet SGMII controller 3 */ >>>> + >>>> +/* Timeout values */ >>>> +#define TIMEOUT_US            1000 >>>> + >>>> +#define IOU_SLCR_GEM_CLK_CTRL        0x308 >>>> +#define GEM_CTRL_GEM_SGMII_MODE        BIT(2) >>>> +#define GEM_CTRL_GEM_REF_SRC_SEL    BIT(1) >>>> + >>>> +#define IOU_SLCR_GEM_CTRL        0x360 >>>> +#define GEM_CTRL_GEM_SGMII_SD        BIT(0) >>>> + >>>> +/** >>>> + * struct xpsgtr_ssc - structure to hold SSC settings for a lane >>>> + * @refclk_rate: PLL reference clock frequency >>>> + * @pll_ref_clk: value to be written to register for corresponding ref clk >>>> rate >>>> + * @steps: number of steps of SSC (Spread Spectrum Clock) >>>> + * @step_size: step size of each step >>>> + */ >>>> +struct xpsgtr_ssc { >>>> +    u32 refclk_rate; >>>> +    u8  pll_ref_clk; >>>> +    u32 steps; >>>> +    u32 step_size; >>>> +}; >>>> + >>>> +/** >>>> + * struct xpsgtr_phy - representation of a lane >>>> + * @dev: pointer to the xpsgtr_dev instance >>>> + * @refclk: reference clock index >>>> + * @type: controller which uses this lane >>>> + * @lane: lane number >>>> + * @protocol: protocol in which the lane operates >>>> + */ >>>> +struct xpsgtr_phy { >>>> +    struct xpsgtr_dev *dev; >>>> +    unsigned int refclk; >>>> +    u8 type; >>>> +    u8 lane; >>>> +    u8 protocol; >>>> +}; >>>> + >>>> +/** >>>> + * struct xpsgtr_dev - representation of a ZynMP GT device >>>> + * @dev: pointer to device >>>> + * @serdes: serdes base address >>>> + * @siou: siou base address >>>> + * @phys: PHY lanes >>>> + * @refclk_sscs: spread spectrum settings for the reference clocks >>>> + * @clk: reference clocks >>>> + */ >>>> +struct xpsgtr_dev { >>>> +    struct udevice *dev; >>>> +    u8 *serdes; >>>> +    u8 *siou; >>>> +    struct xpsgtr_phy phys[NUM_LANES]; >>>> +    const struct xpsgtr_ssc *refclk_sscs[NUM_LANES]; >>>> +    struct clk clk[NUM_LANES]; >>>> +}; >>>> + >>>> +/* >>>> + * Configuration Data >>>> + */ >>>> +/* lookup table to hold all settings needed for a ref clock frequency */ >>>> +static const struct xpsgtr_ssc ssc_lookup[] = { >>>> +    {  19200000, 0x05,  608, 264020 }, >>>> +    {  20000000, 0x06,  634, 243454 }, >>>> +    {  24000000, 0x07,  760, 168973 }, >>>> +    {  26000000, 0x08,  824, 143860 }, >>>> +    {  27000000, 0x09,  856,  86551 }, >>>> +    {  38400000, 0x0a, 1218,  65896 }, >>>> +    {  40000000, 0x0b,  634, 243454 }, >>>> +    {  52000000, 0x0c,  824, 143860 }, >>>> +    { 100000000, 0x0d, 1058,  87533 }, >>>> +    { 108000000, 0x0e,  856,  86551 }, >>>> +    { 125000000, 0x0f,  992, 119497 }, >>>> +    { 135000000, 0x10, 1070,  55393 }, >>>> +    { 150000000, 0x11,  792, 187091 } >>>> +}; >>>> + >>>> +/* >>>> + * I/O Accessors >>>> + */ >>>> + >>>> +static inline u32 xpsgtr_read(struct xpsgtr_dev *gtr_dev, u32 reg) >>>> +{ >>>> +    return readl(gtr_dev->serdes + reg); >>>> +} >>>> + >>>> +static inline void xpsgtr_write(struct xpsgtr_dev *gtr_dev, u32 reg, u32 >>>> value) >>>> +{ >>>> +    writel(value, gtr_dev->serdes + reg); >>>> +} >>>> + >>>> +static inline void xpsgtr_clr_set(struct xpsgtr_dev *gtr_dev, u32 reg, >>>> +                  u32 clr, u32 set) >>>> +{ >>>> +    u32 value = xpsgtr_read(gtr_dev, reg); >>>> + >>>> +    value &= ~clr; >>>> +    value |= set; >>>> +    xpsgtr_write(gtr_dev, reg, value); >>>> +} >>>> + >>>> +static inline u32 xpsgtr_read_phy(struct xpsgtr_phy *gtr_phy, u32 reg) >>>> +{ >>>> +    void __iomem *addr = gtr_phy->dev->serdes >>>> +               + gtr_phy->lane * PHY_REG_OFFSET + reg; >>>> + >>>> +    return readl(addr); >>>> +} >>>> + >>>> +static inline void xpsgtr_write_phy(struct xpsgtr_phy *gtr_phy, >>>> +                    u32 reg, u32 value) >>>> +{ >>>> +    void __iomem *addr = gtr_phy->dev->serdes >>>> +               + gtr_phy->lane * PHY_REG_OFFSET + reg; >>>> + >>>> +    writel(value, addr); >>>> +} >>>> + >>>> +static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy, >>>> +                      u32 reg, u32 clr, u32 set) >>>> +{ >>>> +    void __iomem *addr = gtr_phy->dev->serdes >>>> +               + gtr_phy->lane * PHY_REG_OFFSET + reg; >>>> + >>>> +    writel((readl(addr) & ~clr) | set, addr); >>>> +} >>>> + >>>> +/* Configure PLL and spread-sprectrum clock. */ >>>> +static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy) >>>> +{ >>>> +    const struct xpsgtr_ssc *ssc; >>>> +    u32 step_size; >>>> + >>>> +    ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk]; >>>> +    step_size = ssc->step_size; >>>> + >>>> +    xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane), >>>> +               PLL_FREQ_MASK, ssc->pll_ref_clk); >>>> + >>>> +    /* Enable lane clock sharing, if required */ >>>> +    if (gtr_phy->refclk != gtr_phy->lane) { >>>> +        /* Lane3 Ref Clock Selection Register */ >>>> +        xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane), >>>> +                   L0_REF_CLK_SEL_MASK, 1 << gtr_phy->refclk); >>>> +    } >>>> + >>>> +    /* SSC step size [7:0] */ >>>> +    xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_0_LSB, >>>> +               STEP_SIZE_0_MASK, step_size & STEP_SIZE_0_MASK); >>>> + >>>> +    /* SSC step size [15:8] */ >>>> +    step_size >>= STEP_SIZE_SHIFT; >>>> +    xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_1, >>>> +               STEP_SIZE_1_MASK, step_size & STEP_SIZE_1_MASK); >>>> + >>>> +    /* SSC step size [23:16] */ >>>> +    step_size >>= STEP_SIZE_SHIFT; >>>> +    xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_2, >>>> +               STEP_SIZE_2_MASK, step_size & STEP_SIZE_2_MASK); >>>> + >>>> +    /* SSC steps [7:0] */ >>>> +    xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEPS_0_LSB, >>>> +               STEPS_0_MASK, ssc->steps & STEPS_0_MASK); >>>> + >>>> +    /* SSC steps [10:8] */ >>>> +    xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEPS_1_MSB, >>>> +               STEPS_1_MASK, >>>> +               (ssc->steps >> STEP_SIZE_SHIFT) & STEPS_1_MASK); >>>> + >>>> +    /* SSC step size [24:25] */ >>>> +    step_size >>= STEP_SIZE_SHIFT; >>>> +    xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_3_MSB, >>>> +               STEP_SIZE_3_MASK, (step_size & STEP_SIZE_3_MASK) | >>>> +               FORCE_STEP_SIZE | FORCE_STEPS); >>>> +} >>>> + >>>> +/* Configure the lane protocol. */ >>>> +static void xpsgtr_lane_set_protocol(struct xpsgtr_phy *gtr_phy) >>>> +{ >>>> +    struct xpsgtr_dev *gtr_dev = gtr_phy->dev; >>>> +    u8 protocol = gtr_phy->protocol; >>>> + >>>> +    switch (gtr_phy->lane) { >>>> +    case 0: >>>> +        xpsgtr_clr_set(gtr_dev, ICM_CFG0, ICM_CFG0_L0_MASK, protocol); >>>> +        break; >>>> +    case 1: >>>> +        xpsgtr_clr_set(gtr_dev, ICM_CFG0, ICM_CFG0_L1_MASK, >>>> +                   protocol << ICM_CFG_SHIFT); >>>> +        break; >>>> +    case 2: >>>> +        xpsgtr_clr_set(gtr_dev, ICM_CFG1, ICM_CFG0_L0_MASK, protocol); >>>> +        break; >>>> +    case 3: >>>> +        xpsgtr_clr_set(gtr_dev, ICM_CFG1, ICM_CFG0_L1_MASK, >>>> +                   protocol << ICM_CFG_SHIFT); >>>> +        break; >>>> +    default: >>>> +        /* We already checked 0 <= lane <= 3 */ >>>> +        break; >>>> +    } >>>> +} >>>> + >>>> +/* Bypass (de)scrambler and 8b/10b decoder and encoder. */ >>>> +static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy) >>>> +{ >>>> +    xpsgtr_write_phy(gtr_phy, L0_TM_DIG_6, L0_TM_DIS_DESCRAMBLE_DECODER); >>>> +    xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61, L0_TM_DISABLE_SCRAMBLE_ENCODER); >>>> +} >>>> + >>>> +/* SGMII-specific initialization. */ >>>> +static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy) >>>> +{ >>>> +    struct xpsgtr_dev *gtr_dev = gtr_phy->dev; >>>> +    u32 shift = gtr_phy->lane * PROT_BUS_WIDTH_SHIFT; >>>> + >>>> +    /* Set SGMII protocol TX and RX bus width to 10 bits. */ >>>> +    xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, PROT_BUS_WIDTH_MASK << shift, >>>> +               PROT_BUS_WIDTH_10 << shift); >>>> + >>>> +    xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, PROT_BUS_WIDTH_MASK << shift, >>>> +               PROT_BUS_WIDTH_10 << shift); >>>> + >>>> +    xpsgtr_bypass_scrambler_8b10b(gtr_phy); >>>> + >>>> +    /* >>>> +     * Below code is just temporary solution till we have a way how to >>>> +     * do it via firmware interface in sync with Linux. Till that happen >>>> +     * this is the most sensible thing to do here. >>>> +     */ >>>> +    /* GEM I/O Clock Control */ >>>> +    clrsetbits_le32(ZYNQMP_IOU_SLCR_BASEADDR + IOU_SLCR_GEM_CLK_CTRL, >>>> +            0xf << shift, >>>> +            (GEM_CTRL_GEM_SGMII_MODE | GEM_CTRL_GEM_REF_SRC_SEL) << >>>> +            shift); >>>> + >>>> +    /* Setup signal detect */ >>>> +    clrsetbits_le32(ZYNQMP_IOU_SLCR_BASEADDR + IOU_SLCR_GEM_CTRL, >>>> +            PROT_BUS_WIDTH_MASK << shift, >>>> +            GEM_CTRL_GEM_SGMII_SD << shift); >>>> +} >>>> + >>>> +static int xpsgtr_init(struct phy *x) >>>> +{ >>>> +    struct xpsgtr_dev *gtr_dev = dev_get_priv(x->dev); >>>> +    struct xpsgtr_phy *gtr_phy; >>>> +    u32 phy_lane = x->id; >>>> + >>>> +    gtr_phy = >r_dev->phys[phy_lane]; >>>> + >>>> +    /* Enable coarse code saturation limiting logic. */ >>>> +    xpsgtr_write_phy(gtr_phy, L0_TM_PLL_DIG_37, L0_TM_COARSE_CODE_LIMIT); >>>> + >>>> +    /* >>>> +     * Configure the PLL, the lane protocol, and perform protocol-specific >>>> +     * initialization. >>>> +     */ >>>> +    xpsgtr_configure_pll(gtr_phy); >>>> +    xpsgtr_lane_set_protocol(gtr_phy); >>>> + >>>> +    switch (gtr_phy->protocol) { >>>> +    case ICM_PROTOCOL_SGMII: >>>> +        xpsgtr_phy_init_sgmii(gtr_phy); >>>> +        break; >>>> +    case ICM_PROTOCOL_DP: >>>> +    case ICM_PROTOCOL_SATA: >>>> +        return -EINVAL; >>>> +    } >>>> +    return 0; >>>> +} >>>> + >>>> +/* >>>> + * OF Xlate Support >>>> + */ >>>> + >>>> +/* Set the lane type and protocol based on the PHY type and instance >>>> number. */ >>>> +static int xpsgtr_set_lane_type(struct xpsgtr_phy *gtr_phy, u8 phy_type, >>>> +                unsigned int phy_instance) >>>> +{ >>>> +    unsigned int num_phy_types; >>>> +    const int *phy_types; >>>> + >>>> +    switch (phy_type) { >>>> +    case PHY_TYPE_SATA: { >>>> +        static const int types[] = { >>>> +            XPSGTR_TYPE_SATA_0, >>>> +            XPSGTR_TYPE_SATA_1, >>>> +        }; >>>> + >>>> +        phy_types = types; >>>> +        num_phy_types = ARRAY_SIZE(types); >>>> +        gtr_phy->protocol = ICM_PROTOCOL_SATA; >>>> +        break; >>>> +    } >>>> +    case PHY_TYPE_USB3: { >>>> +        static const int types[] = { >>>> +            XPSGTR_TYPE_USB0, >>>> +            XPSGTR_TYPE_USB1, >>>> +        }; >>>> + >>>> +        phy_types = types; >>>> +        num_phy_types = ARRAY_SIZE(types); >>>> +        gtr_phy->protocol = ICM_PROTOCOL_USB; >>>> +        break; >>>> +    } >>>> +    case PHY_TYPE_DP: { >>>> +        static const int types[] = { >>>> +            XPSGTR_TYPE_DP_0, >>>> +            XPSGTR_TYPE_DP_1, >>>> +        }; >>>> + >>>> +        phy_types = types; >>>> +        num_phy_types = ARRAY_SIZE(types); >>>> +        gtr_phy->protocol = ICM_PROTOCOL_DP; >>>> +        break; >>>> +    } >>>> +    case PHY_TYPE_PCIE: { >>>> +        static const int types[] = { >>>> +            XPSGTR_TYPE_PCIE_0, >>>> +            XPSGTR_TYPE_PCIE_1, >>>> +            XPSGTR_TYPE_PCIE_2, >>>> +            XPSGTR_TYPE_PCIE_3, >>>> +        }; >>>> + >>>> +        phy_types = types; >>>> +        num_phy_types = ARRAY_SIZE(types); >>>> +        gtr_phy->protocol = ICM_PROTOCOL_PCIE; >>>> +        break; >>>> +    } >>>> +    case PHY_TYPE_SGMII: { >>>> +        static const int types[] = { >>>> +            XPSGTR_TYPE_SGMII0, >>>> +            XPSGTR_TYPE_SGMII1, >>>> +            XPSGTR_TYPE_SGMII2, >>>> +            XPSGTR_TYPE_SGMII3, >>>> +        }; >>>> + >>>> +        phy_types = types; >>>> +        num_phy_types = ARRAY_SIZE(types); >>>> +        gtr_phy->protocol = ICM_PROTOCOL_SGMII; >>>> +        break; >>>> +    } >>>> +    default: >>>> +        return -EINVAL; >>>> +    } >>>> + >>>> +    if (phy_instance >= num_phy_types) >>>> +        return -EINVAL; >>>> + >>>> +    gtr_phy->type = phy_types[phy_instance]; >>>> +    return 0; >>>> +} >>>> + >>>> +/* >>>> + * Valid combinations of controllers and lanes (Interconnect Matrix). >>>> + */ >>>> +static const unsigned int icm_matrix[NUM_LANES][CONTROLLERS_PER_LANE] = { >>>> +    { XPSGTR_TYPE_PCIE_0, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0, >>>> +        XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII0 }, >>>> +    { XPSGTR_TYPE_PCIE_1, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB0, >>>> +        XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII1 }, >>>> +    { XPSGTR_TYPE_PCIE_2, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0, >>>> +        XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII2 }, >>>> +    { XPSGTR_TYPE_PCIE_3, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB1, >>>> +        XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII3 } >>>> +}; >>>> + >>>> +/* Translate OF phandle and args to PHY instance. */ >>>> +static int xpsgtr_of_xlate(struct phy *x, >>>> +               struct ofnode_phandle_args *args) >>>> +{ >>>> +    struct xpsgtr_dev *gtr_dev = dev_get_priv(x->dev); >>>> +    struct xpsgtr_phy *gtr_phy; >>>> +    struct udevice *dev = x->dev; >>>> +    unsigned int phy_instance; >>>> +    unsigned int phy_lane; >>>> +    unsigned int phy_type; >>>> +    unsigned int refclk; >>>> +    unsigned int i; >>>> +    int ret; >>>> + >>>> +    if (args->args_count != 4) { >>>> +        dev_err(dev, "Invalid number of cells in 'phy' property\n"); >>>> +        return -EINVAL; >>>> +    } >>>> + >>>> +    /* >>>> +     * Get the PHY parameters from the OF arguments and derive the lane >>>> +     * type. >>>> +     */ >>>> +    phy_lane = args->args[0]; >>>> +    if (phy_lane >= NUM_LANES) { >>>> +        dev_err(dev, "Invalid lane number %u\n", phy_lane); >>>> +        return -ENODEV; >>>> +    } >>>> + >>>> +    gtr_phy = >r_dev->phys[phy_lane]; >>>> +    phy_type = args->args[1]; >>>> +    phy_instance = args->args[2]; >>>> + >>>> +    ret = xpsgtr_set_lane_type(gtr_phy, phy_type, phy_instance); >>>> +    if (ret < 0) { >>>> +        dev_err(dev, "Invalid PHY type and/or instance\n"); >>>> +        return ret; >>>> +    } >>>> + >>>> +    refclk = args->args[3]; >>>> +    if (refclk >= ARRAY_SIZE(gtr_dev->refclk_sscs) || >>>> +        !gtr_dev->refclk_sscs[refclk]) { >>>> +        dev_err(dev, "Invalid reference clock number %u\n", refclk); >>>> +        return -EINVAL; >>>> +    } >>>> + >>>> +    gtr_phy->refclk = refclk; >>>> + >>>> +    /* This is difference compare to Linux */ >>>> +    gtr_phy->dev = gtr_dev; >>>> +    gtr_phy->lane = phy_lane; >>> >>> Why don't we set these in probe()? >> >> >> Because lane number is not the part of psgtr node but the part of node which >> is requesting phy. >> >> >>> >>>> + >>>> +    /* >>>> +     * Ensure that the Interconnect Matrix is obeyed, i.e a given lane type >>>> +     * is allowed to operate on the lane. >>>> +     */ >>>> +    for (i = 0; i < CONTROLLERS_PER_LANE; i++) { >>>> +        if (icm_matrix[phy_lane][i] == gtr_phy->type) { >>>> +            x->id = phy_lane; >>>> +            return 0; >>>> +        } >>>> +    } >>>> + >>>> +    return -EINVAL; >>>> +} >>>> + >>>> +/* >>>> + * Probe & Platform Driver >>>> + */ >>>> +static int xpsgtr_get_ref_clocks(struct udevice *dev) >>>> +{ >>>> +    unsigned int refclk; >>>> +    struct xpsgtr_dev *gtr_dev = dev_get_priv(dev); >>>> +    int ret; >>>> + >>>> +    for (refclk = 0; refclk < 4; ++refclk) { >>> >>> refclk < ARRAY_SIZE(gtr_dev->clk)? refclk < NUM_LANES? >> >> Will fix. >> >>> >>>> +        int i; >>>> +        u32 rate; >>>> +        char name[8]; >>>> +        struct clk *clk = >r_dev->clk[refclk]; >>>> + >>>> +        snprintf(name, sizeof(name), "ref%u", refclk); >>>> +        dev_dbg(dev, "Checking name: %s\n", name); >>>> +        ret = clk_get_by_name(dev, name, clk); >>>> +        if (ret) >>> >>> This should be >>> >>>      if (ret == -ENODATA) { >>>          continue; >>>      } else if (ret) { >>>          dev_dbg(dev, "couldn't get clock %s (err %d)", name, ret); >>>          return ret; >>>      } >> >> Nope. I don't want to fail if I can't access that clock. The reason is that >> not all clocks are wired. If clock is not there that's completely fine and I >> want to continue not end. It is really just for the record which clocks are >> used. The same logic is in linux driver too. > > If you don't get a clock, clk_get_by_name returns -ENODATA.  So this > does the same thing as your patch, but if there is an actual error (not > just clock missing) it is passed on. Linux has the same logic in > devm_clk_get_optional. > > --Sean > >>> >>> although we really should have a clk_get_by_name_optional wrapper in >>> U-Boot. I wonder if we need to clean up clocks as well... >>> >>>> +            continue; >>>> + >>>> +        rate = clk_get_rate(clk); >>>> + >>>> +        dev_dbg(dev, "clk rate %d\n", rate); >>>> + >>>> +        ret = clk_enable(clk); >>>> +        if (ret) { >>>> +            dev_err(dev, "failed to enable refclk %d clock\n", >>>> +                refclk); >>>> +            return ret; >>>> +        } >>>> + >>>> +        for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) { >>>> +            if (rate == ssc_lookup[i].refclk_rate) { >>>> +                gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i]; >>>> +                dev_dbg(dev, "Found rate %d\n", i); >>>> +                break; >>>> +            } >>>> +        } >>>> + >>>> +        if (i == ARRAY_SIZE(ssc_lookup)) { >>>> +            dev_err(dev, >>>> +                "Invalid rate %u for reference clock %u\n", >>>> +                rate, refclk); >>>> +            return -EINVAL; >>>> +        } >>>> +    } >>>> + >>>> +    return 0; >>>> +} >>>> + >>>> +static int xpsgtr_probe(struct udevice *dev) >>>> +{ >>>> +    struct xpsgtr_dev *gtr_dev = dev_get_priv(dev); >>>> + >>>> +    gtr_dev->serdes = (u8 *)dev_read_addr_name(dev, "serdes"); >>> >>> Why not dev_remap_addr_name? >> >> will use. >> >>> >>>> +    if (!gtr_dev->serdes) >>> >>> And this check is wrong because on failure you will get back >>> FDT_ADDR_T_NONE, not NULL. >> >> Using dev_remap_addr_name should solve this problem. >> >>> >>>> +        return -ENODEV; >>>> + >>>> +    gtr_dev->siou = (u8 *)dev_read_addr_name(dev, "siou"); >>>> +    if (!gtr_dev->siou) >>>> +        return -ENODEV; >>> >>> ditto >> >> Will fix. >> >>> >>>> +    gtr_dev->dev = dev; >>>> + >>>> +    return xpsgtr_get_ref_clocks(dev); >>>> +} >>>> + >>>> +static const struct udevice_id xpsgtr_phy_ids[] = { >>>> +    { .compatible = "xlnx,zynqmp-psgtr-v1.1", }, >>>> +    { } >>>> +}; >>>> + >>>> +static const struct phy_ops xpsgtr_phy_ops = { >>>> +    .init = xpsgtr_init, >>> >>> Why don't we need power_on? In Linux that calls xpsgtr_wait_pll_lock, >>> which seems important. >> >> In the case we have PLL are already locked all the time but that doesn't mean >> we can't add this checking. It should just go through on the first pass and >> never timeout. >> Will look. I have fixed all above and send new version also with power on implemented which checks if PLL is locked. Getting to PLL lock there is a need to perform IP reset that's why I have also updated gem driver to match this requirement. M