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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 665B6C433EF for ; Wed, 6 Oct 2021 14:23:13 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id B251661056 for ; Wed, 6 Oct 2021 14:23:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B251661056 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=xilinx.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C5AF583152; Wed, 6 Oct 2021 16:23:10 +0200 (CEST) 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="VgJGr8ci"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 35EB483173; Wed, 6 Oct 2021 16:23:09 +0200 (CEST) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on20628.outbound.protection.outlook.com [IPv6:2a01:111:f400:7eab::628]) (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 08C5382DF9 for ; Wed, 6 Oct 2021 16:23:04 +0200 (CEST) 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=VmeAIpUv0caMmU+v/y0ZB453HTUWRpOfGSWVE701sCNG3V0CFQ50sdUpLqmtOg6/lQYHTUaBJODXZQtTjb9KpO8Qou2Et5gSmxqdrWTHh/5BaFlThYEZPIj6iqE2lR+KND5zqswa46brKctti/rkERqYfNe9wUaQeTThtX9Xt398w6WMoBxIElgKRLp6vU8V8lKwB/YO8CC48pj6Y00H8d2g8On+lDyOJXkMmPXjLdaXYUVsF0nh/OTyoEMjVAABq7JxqnUeYtzW1CYhHr5OLErnUePEX6z3AUuaYM/p74Qj645/1AFdKO7C19N3grGedVmTCCfR18ZV9B6+miZ+sQ== 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=QEcQkSPTo9VtSov9DP9wmSzDe5ub4Jil7RjBunrIcLo=; b=gxb/DOpEoyMhbgEs9UDgkjzYQZol6q0pjY2Zx/MQ+zavUbUbN7HbdO8pRYLiAb4VRDCfhhuWB5zOygWDhjbKfVyX06u/qcVkrvyHCfP7jB5a7Sr8LKstkL1H4RQnUStIuYlCtIYnComY7Q36CiYCAcAHOhMNJZuCIlaK2RTW4BwCbeGz6wByNjb3XpgVGfduCczT5oqTfWF1HUyObD31aihFO5hmx9OjlD02VNxkYkiaR4B2OajSgVWhBAYT0KQ30NYcpA4qDKok6VWO7tgk3B4DMpDgn79alVCX1u427ifmdFxnASwG3KJvDUiw1+G0rt6VPwTkynj9Q/7xescGhg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=chromium.org 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=QEcQkSPTo9VtSov9DP9wmSzDe5ub4Jil7RjBunrIcLo=; b=VgJGr8cixO1+WgJPz7Ol4cveWGOuXzFdhFS11qgmGRYkbI/p7MmLwUZMW0t5UCDmMct8jpg1S6faRNucTnNlwl0Drv6OIf6bZxqIDZ7IbrsDJu8FS71qjZfsEaXchI0fR/tgOuZkIXDJw+y7VTVUhUIbyCPwkm6XW3gE5FRCdQE= Received: from BN8PR04CA0057.namprd04.prod.outlook.com (2603:10b6:408:d4::31) by DM5PR02MB2396.namprd02.prod.outlook.com (2603:10b6:3:4f::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.15; Wed, 6 Oct 2021 14:23:00 +0000 Received: from BN1NAM02FT020.eop-nam02.prod.protection.outlook.com (2603:10b6:408:d4:cafe::45) by BN8PR04CA0057.outlook.office365.com (2603:10b6:408:d4::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.15 via Frontend Transport; Wed, 6 Oct 2021 14:23:00 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; chromium.org; dkim=none (message not signed) header.d=none;chromium.org; 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 BN1NAM02FT020.mail.protection.outlook.com (10.13.2.135) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.4566.22 via Frontend Transport; Wed, 6 Oct 2021 14:23:00 +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, 6 Oct 2021 07:22:54 -0700 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, 6 Oct 2021 07:22:54 -0700 Envelope-to: git@xilinx.com, sjg@chromium.org, narmstrong@baylibre.com, dariobin@libero.it, alpernebiyasak@gmail.com, u-boot@lists.denx.de, sean.anderson@seco.com Received: from [10.254.241.49] (port=37844) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1mY7or-000Eia-BK; Wed, 06 Oct 2021 07:22:53 -0700 Subject: Re: [PATCH v2] pwm: Add driver for cadence TTC To: Sean Anderson , Michal Simek , , CC: Alper Nebi Yasak , Dario Binacchi , Neil Armstrong , Simon Glass References: <592c6436-8b49-79fa-402c-68ba2f9e42ea@seco.com> From: Michal Simek Message-ID: <594a298b-b09b-db5c-b84a-3ecc9c268e85@xilinx.com> Date: Wed, 6 Oct 2021 16:22:51 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <592c6436-8b49-79fa-402c-68ba2f9e42ea@seco.com> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 288ce5e1-9a78-4ae5-ce98-08d988d4cd17 X-MS-TrafficTypeDiagnostic: DM5PR02MB2396: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 5fEuqrPXvFsv3M8KEvp0vb9o5S3FNDVxxrreZAI34JGIkx7iJiXCyGdDIXJDB3cM+4FCn2hR6oaJ6ERbZQm8c7N3GtCw8zHI8Naw16OhPPsNLpO/Fncd3qAM2LmvHdfH+LL50yWW2LxpseAI0/lVpCj/Iil78vSVxrDB68uvdfonIRm+53JAunTHWrjRAS9inTSJAfkzd/0MPIhnR5CJF6HietquAkAT3Wk1YlW+ShAY3hEsFBU2f436vAazn/HEYQrcIolLisvTJ6Pfnm8AS6ZQqsvpd3IqQ6tpKV/XEB09bSpLLjM7jUdSYdEIzL+PSugjJXCpEvIcFZad8CRBSr6H4HYed6EpVgt4jWBB7gRwiWqvqMyLGF10lWvZmdm+ev/GY9Y3JdGMOIeJ4SaZOd6yJHiXXVKWzRGVNCmZLG1LCi+k22rVzk8lNuq4UyjqeVtUZi/8ZDaSdsvz0LoY6BWf8Uyek9Jiz510MjzMZ7vCv9dQkJM/UuO1bpShy1bqg0jFqeXwY6Gkk810JRxFjNVnKTR76WJGyBJ5F3T3VOUEpYsBhYX5w8dCxsZMe2Jb/QYvJi4gOtTfvp2fHKJvZHFGVaOfiGOdM9du9Hsj15j6aDnFAZrBhV4EqL5yRNAbl/L59RNCRT5LTyQD1o3p0L+YrxLknIPsjhWTbepSyUBbDriiNiqDunFrTN0V+jtOeIqwaYeyzVq87L70UctLj75bvTW8KsmOO47nD3GEZO0gUR2OSAgOtw/8+HsZQb1f1gJxQbbCQSP/33FP/mUuXQ== 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:(36840700001)(46966006)(31686004)(336012)(31696002)(36906005)(6636002)(47076005)(9786002)(2906002)(5660300002)(70206006)(30864003)(36756003)(8936002)(316002)(36860700001)(70586007)(44832011)(2616005)(508600001)(426003)(4326008)(356005)(110136005)(26005)(53546011)(54906003)(186003)(82310400003)(83380400001)(8676002)(7636003)(50156003)(43740500002); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2021 14:23:00.3560 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 288ce5e1-9a78-4ae5-ce98-08d988d4cd17 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: BN1NAM02FT020.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR02MB2396 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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 8/30/21 6:03 PM, Sean Anderson wrote: > > > On 8/30/21 5:38 AM, Michal Simek wrote: >> TTC has three modes of operations. Timer, PWM and input counters. >> >> There is already driver for timer under CADENCE_TTC_TIMER which is >> used for >> ZynqMP R5 configuration. >> This driver is targeting PWM which is for example configuration which can >> be used for fan control. >> The driver has been tested on Xilinx Kria SOM platform where fan is >> connected to one PL pin. When TTC output is connected via EMIO to PL pin >> TTC pwm can be configured and tested for example like this: >> pwm config 0 0 10000 1200 >> pwm enable 0 0 >> pwm config 0 0 10000 1400 >> pwm config 0 0 10000 1600 >> >> Signed-off-by: Michal Simek >> --- >> >> Changes in v2: >> - Detect pwm-cells property for PWM driver >> - Fix all macro names >> - Use BIT and GENMASK macros >> - Introduce TTC_REG macro for reg offsets >> - Use FIELD_PREP >> - Move cadence_ttc_pwm_of_to_plat() below probe >> - Introduce struct cadence_ttc_pwm_plat >> - Read timer-width from DT >> - Use NSEC_PER_SEC macro >> - Use clock_ctrl variable instead of x - all reported by Sean >> >>   MAINTAINERS                   |   1 + >>   drivers/pwm/Kconfig           |   7 + >>   drivers/pwm/Makefile          |   1 + >>   drivers/pwm/pwm-cadence-ttc.c | 247 ++++++++++++++++++++++++++++++++++ >>   4 files changed, 256 insertions(+) >>   create mode 100644 drivers/pwm/pwm-cadence-ttc.c >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index 4cf0c33c5d58..889813382249 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -600,6 +600,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/pwm/pwm-cadence-ttc.c >>   F:    drivers/serial/serial_zynq.c >>   F:    drivers/reset/reset-zynqmp.c >>   F:    drivers/rtc/zynqmp_rtc.c >> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig >> index cf7f4c6840ce..176e703c8fbb 100644 >> --- a/drivers/pwm/Kconfig >> +++ b/drivers/pwm/Kconfig >> @@ -9,6 +9,13 @@ config DM_PWM >>         frequency/period can be controlled along with the proportion >> of that >>         time that the signal is high. >> >> +config PWM_CADENCE_TTC >> +    bool "Enable support for the Cadence TTC PWM" >> +    depends on DM_PWM && !CADENCE_TTC_TIMER >> +    help >> +      Cadence TTC can be configured as timer which is done via >> +      CONFIG_CADENCE_TTC_TIMER or as PWM. This is covering only PWM now. >> + >>   config PWM_CROS_EC >>       bool "Enable support for the Chrome OS EC PWM" >>       depends on DM_PWM >> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile >> index 10d244bfb79d..abf5af41d2cc 100644 >> --- a/drivers/pwm/Makefile >> +++ b/drivers/pwm/Makefile >> @@ -10,6 +10,7 @@ >> >>   obj-$(CONFIG_DM_PWM)        += pwm-uclass.o >> >> +obj-$(CONFIG_PWM_CADENCE_TTC)    += pwm-cadence-ttc.o >>   obj-$(CONFIG_PWM_CROS_EC)    += cros_ec_pwm.o >>   obj-$(CONFIG_PWM_EXYNOS)    += exynos_pwm.o >>   obj-$(CONFIG_PWM_IMX)        += pwm-imx.o pwm-imx-util.o >> diff --git a/drivers/pwm/pwm-cadence-ttc.c >> b/drivers/pwm/pwm-cadence-ttc.c >> new file mode 100644 >> index 000000000000..99aaaa6a8ab6 >> --- /dev/null >> +++ b/drivers/pwm/pwm-cadence-ttc.c >> @@ -0,0 +1,247 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * (C) Copyright 2021 Xilinx, Inc. Michal Simek >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define CLOCK_CONTROL        0 >> +#define COUNTER_CONTROL        0xc >> +#define INTERVAL_COUNTER    0x24 >> +#define MATCH_1_COUNTER        0x30 >> + >> +#define CLK_FALLING_EDGE    BIT(6) >> +#define CLK_SRC_EXTERNAL    BIT(5) >> +#define CLK_PRESCALE_MASK    GENMASK(4, 1) >> +#define CLK_PRESCALE_ENABLE    BIT(0) >> + >> +#define COUNTER_WAVE_POL        BIT(6) >> +#define COUNTER_WAVE_DISABLE        BIT(5) >> +#define COUNTER_RESET            BIT(4) >> +#define COUNTER_MATCH_ENABLE        BIT(3) >> +#define COUNTER_DECREMENT_ENABLE    BIT(2) >> +#define COUNTER_INTERVAL_ENABLE        BIT(1) >> +#define COUNTER_COUNTING_DISABLE    BIT(0) >> + >> +#define NSEC_PER_SEC    1000000000L >> + >> +#define TTC_REG(reg, channel) ((reg) + (channel) * sizeof(u32)) >> +#define TTC_CLOCK_CONTROL(reg, channel) \ >> +    TTC_REG((reg) + CLOCK_CONTROL, (channel)) >> +#define TTC_COUNTER_CONTROL(reg, channel) \ >> +    TTC_REG((reg) + COUNTER_CONTROL, (channel)) >> +#define TTC_INTERVAL_COUNTER(reg, channel) \ >> +    TTC_REG((reg) + INTERVAL_COUNTER, (channel)) >> +#define TTC_MATCH_1_COUNTER(reg, channel) \ >> +    TTC_REG((reg) + MATCH_1_COUNTER, (channel)) >> + >> +struct cadence_ttc_pwm_plat { >> +    u8 *regs; >> +    u32 timer_mask; >> +}; >> + >> +struct cadence_ttc_pwm_priv { >> +    u8 *regs; >> +    u32 timer_mask; >> +    unsigned long frequency; >> +    bool invert[2]; >> +}; >> + >> +static int cadence_ttc_pwm_set_invert(struct udevice *dev, uint channel, >> +                      bool polarity) >> +{ >> +    struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); >> + >> +    if (channel > 2) { >> +        dev_err(dev, "Unsupported channel number %d(max 2)\n", channel); >> +        return -EINVAL; >> +    } >> + >> +    priv->invert[channel] = polarity; >> + >> +    dev_dbg(dev, "polarity=%u. Please config PWM again\n", polarity); >> + >> +    return 0; >> +} >> + >> +static int cadence_ttc_pwm_set_config(struct udevice *dev, uint channel, >> +                      uint period_ns, uint duty_ns) >> +{ >> +    struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); >> +    u32 counter_ctrl, clock_ctrl; >> +    int period_clocks, duty_clocks, prescaler; >> + >> +    dev_dbg(dev, "channel %d, duty %d/ period %d ns\n", channel, >> +        duty_ns, period_ns); >> + >> +    if (channel > 2) { >> +        dev_err(dev, "Unsupported channel number %d(max 2)\n", channel); >> +        return -EINVAL; >> +    } >> + >> +    /* Make sure counter is stopped */ >> +    counter_ctrl = readl(TTC_COUNTER_CONTROL(priv->regs, channel)); >> +    setbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), >> +             COUNTER_COUNTING_DISABLE); > > Why disable it? it should be better to disable it then changing values with output enabled. > >> + >> +    /* Calculate period, prescaler and set clock control register */ >> +    period_clocks = div64_u64(((int64_t)period_ns * priv->frequency), >> +                  NSEC_PER_SEC); >> + >> +    prescaler = ilog2(period_clocks) + 1 - 16; > > This 16 should be based off of priv->timer_mask. done in v2 > >> +    if (prescaler < 0) >> +        prescaler = 0; >> + >> +    clock_ctrl = readl(TTC_CLOCK_CONTROL(priv->regs, channel)); >> + >> +    if (!prescaler) { >> +        clock_ctrl &= ~(CLK_PRESCALE_ENABLE | CLK_PRESCALE_MASK); >> +    } else { >> +        clock_ctrl &= ~CLK_PRESCALE_MASK; >> +        clock_ctrl |= CLK_PRESCALE_ENABLE; >> +        clock_ctrl |= FIELD_PREP(CLK_PRESCALE_MASK, prescaler - 1); >> +    }; >> + >> +    /* External source is not handled by this driver now */ >> +    clock_ctrl &= ~CLK_SRC_EXTERNAL; >> + >> +    writel(clock_ctrl, TTC_CLOCK_CONTROL(priv->regs, channel)); >> + >> +    /* Calculate interval and set counter control value */ >> +    duty_clocks = div64_u64(((int64_t)duty_ns * priv->frequency), >> +                NSEC_PER_SEC); >> + >> +    writel((period_clocks >> prescaler) & priv->timer_mask, >> +           TTC_INTERVAL_COUNTER(priv->regs, channel)); >> +    writel((duty_clocks >> prescaler) & priv->timer_mask, >> +           TTC_MATCH_1_COUNTER(priv->regs, channel)); >> + >> +    /* Restore/reset counter */ >> +    counter_ctrl &= ~COUNTER_DECREMENT_ENABLE; >> +    counter_ctrl |= COUNTER_INTERVAL_ENABLE | >> +            COUNTER_RESET | >> +            COUNTER_MATCH_ENABLE; >> + >> +    if (priv->invert[channel]) >> +        counter_ctrl |= COUNTER_WAVE_POL; >> +    else >> +        counter_ctrl &= ~COUNTER_WAVE_POL; >> + >> +    writel(counter_ctrl, TTC_COUNTER_CONTROL(priv->regs, channel)); >> + >> +    dev_dbg(dev, "%d/%d clocks, prescaler 2^%d\n", duty_clocks, >> +        period_clocks, prescaler); >> + >> +    return 0; >> +}; >> + >> +static int cadence_ttc_pwm_set_enable(struct udevice *dev, uint channel, >> +                      bool enable) >> +{ >> +    struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); >> + >> +    if (channel > 2) { >> +        dev_err(dev, "Unsupported channel number %d(max 2)\n", channel); >> +        return -EINVAL; >> +    } >> + >> +    dev_dbg(dev, "Enable: %d, channel %d\n", enable, channel); >> + >> +    if (enable) { >> +        clrbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), >> +                 COUNTER_COUNTING_DISABLE | >> +                 COUNTER_WAVE_DISABLE); >> +        setbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), >> +                 COUNTER_RESET); >> +    } else { >> +        setbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), >> +                 COUNTER_COUNTING_DISABLE | >> +                 COUNTER_WAVE_DISABLE); >> +    } >> + >> +    return 0; >> +}; >> + >> +static int cadence_ttc_pwm_probe(struct udevice *dev) >> +{ >> +    struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); >> +    struct cadence_ttc_pwm_plat *plat = dev_get_plat(dev); >> +    struct clk clk; >> +    int ret; >> + >> +    priv->regs = plat->regs; >> +    priv->timer_mask = plat->timer_mask; >> + >> +    ret = clk_get_by_index(dev, 0, &clk); >> +    if (ret < 0) { >> +        dev_err(dev, "failed to get clock\n"); >> +        return ret; >> +    } >> + >> +    priv->frequency = clk_get_rate(&clk); >> +    if (IS_ERR_VALUE(priv->frequency)) { >> +        dev_err(dev, "failed to get rate\n"); >> +        return priv->frequency; >> +    } >> +    dev_dbg(dev, "Clk frequency: %ld\n", priv->frequency); >> + >> +    ret = clk_enable(&clk); >> +    if (ret) { >> +        dev_err(dev, "failed to enable clock\n"); >> +        return ret; >> +    } >> + >> +    return 0; >> +} >> + >> +static int cadence_ttc_pwm_of_to_plat(struct udevice *dev) >> +{ >> +    struct cadence_ttc_pwm_plat *plat = dev_get_plat(dev); >> +    const char *cells; >> +    u32 timer_width; >> + >> +    cells = dev_read_prop(dev, "#pwm-cells", NULL); >> +    if (!cells) >> +        return -EINVAL; > > Sorry, I was not precise enough with my feedback last time. This check > needs to happen in bind() (and return -ENODEV) so that lists_bind_fdt > tries another driver. I took a look at it and core doesn't support it without patching. When one driver returns -ENODEV core won't try to find another driver. But I have sent v3 series with small changes in the core to handle this case better. Also update cadence ttc timer driver to check pwm-cells and ignore it in that case. Even that's situation which is not a problem on arm64 which is not enabling CONFIG_TIMER. Thanks, Michal