Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp773634imm; Wed, 20 Jun 2018 06:26:48 -0700 (PDT) X-Google-Smtp-Source: ADUXVKIjxFgE2XT5wi2xoF85vDX/YzbsEmgRs5PO6mvkHk1zYA1QSVY8L0XUj5zXkoYXCtgyT7ge X-Received: by 2002:a17:902:8b8c:: with SMTP id ay12-v6mr23754063plb.74.1529501208727; Wed, 20 Jun 2018 06:26:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529501208; cv=none; d=google.com; s=arc-20160816; b=B364b69DdUzplRs/2mhmJx2dDjD1J6gN7SyqYkkcVUdd/Lloz5X0EZMe/1IBFI3x6W GNV+4sW4xq9Iw4I0vDrMTOS+oLb3oyPTqzG/Qs8BkM8ExmRifYWe6v/aHlI7TU0NSk6Y qi4WBW3eO8Ji+3pPvXGGwDFtEvpc7ZVTlDQHhEZ77XTR8ZQG8Bqyoupxk8uTrleD+8Na iO1c8xrloZtriYKaOCHMdHOlGpH0i7MayrFBjPW2Bgb06ed3j21XGUbvRDetJXNcIQ9f iFGPCUvsTZ7SKxWzlH2t1Yns4POSfgoT0tJKnkRv8vI5LCWI/iCJ62noCp4EMZpl+3jV M2TQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:arc-authentication-results; bh=sv9onCiMDygEI+YJE/eeXxGDtLjDADlLnppOxrgC9xE=; b=LZAwiWYI4H6DetuVtCpnyCl4rkemWes5CifmDUMGbuDZtfqYRqGMKLJO/A61i+C+X2 WR9gH5D3xOtusXZWptyIb+Tac9vtMqh3w/nfc52WGSZenbt73nV75Vc/F+fFyTjSG8oK E3rFawrzf2NKjmYd27sbiLfRamfwKnjjHXBGEzQrTJcxtUssnVKkG1o1p58ImdK4MyP+ tLWb05XL3nWsdiOwvDtOMYNNovfk0wR3L3QLVX56yLDPB2w7LlQkLXFKrS2ZdkDLBeKA okcxYbEi0/FLqCK0tIOluP8vmJj5E3pD1uZIG2990HUqQGPhnpcO0TEZQWA4Cbxghdey nI6w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 11-v6si2414706plc.466.2018.06.20.06.26.33; Wed, 20 Jun 2018 06:26:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753893AbeFTNYv (ORCPT + 99 others); Wed, 20 Jun 2018 09:24:51 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:43651 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752725AbeFTNYt (ORCPT ); Wed, 20 Jun 2018 09:24:49 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w5KDNWLD018781; Wed, 20 Jun 2018 15:24:12 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2jqqgq82fe-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 20 Jun 2018 15:24:12 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id CA74F42; Wed, 20 Jun 2018 13:24:08 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node1.st.com [10.75.127.16]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 9951C2B6F; Wed, 20 Jun 2018 13:24:08 +0000 (GMT) Received: from [10.48.0.237] (10.75.127.45) by SFHDAG6NODE1.st.com (10.75.127.16) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 20 Jun 2018 15:24:07 +0200 Subject: Re: [PATCH V2 1/3] watchdog: stm32: add pclk feature for stm32mp1 To: Guenter Roeck , Wim Van Sebroeck , Rob Herring CC: Maxime Coquelin , Alexandre Torgue , , , , References: <1529481238-15277-1-git-send-email-ludovic.Barre@st.com> <1529481238-15277-2-git-send-email-ludovic.Barre@st.com> <6162d701-2afd-5a22-d38f-7fb9e726cff7@roeck-us.net> From: Ludovic BARRE Message-ID: Date: Wed, 20 Jun 2018 15:24:07 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: <6162d701-2afd-5a22-d38f-7fb9e726cff7@roeck-us.net> Content-Type: text/plain; charset="utf-8"; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG1NODE3.st.com (10.75.127.3) To SFHDAG6NODE1.st.com (10.75.127.16) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-06-20_06:,, signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 06/20/2018 11:19 AM, Guenter Roeck wrote: > On 06/20/2018 12:53 AM, Ludovic Barre wrote: >> From: Ludovic Barre >> >> This patch adds config data to manage specific properties by >> compatible. Adds stm32mp1 config which requires pclk clock. >> >> Signed-off-by: Ludovic Barre >> --- >>   .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++- >>   drivers/watchdog/stm32_iwdg.c                      | 132 >> ++++++++++++++------- >>   2 files changed, 104 insertions(+), 49 deletions(-) >> >> diff --git >> a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt >> b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt >> index cc13b10a..f07f6d89 100644 >> --- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt >> +++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt >> @@ -2,18 +2,31 @@ STM32 Independent WatchDoG (IWDG) >>   --------------------------------- >>   Required properties: >> -- compatible: "st,stm32-iwdg" >> -- reg: physical base address and length of the registers set for the >> device >> -- clocks: must contain a single entry describing the clock input >> +- compatible: Should be either "st,stm32-iwdg" or "st,stm32mp1-iwdg" >> +- reg: Physical base address and length of the registers set for the >> device >> +- clocks: Reference to the clock entry lsi. Additional pclk clock entry >> +  is required only for st,stm32mp1-iwdg. >> +- clock-names: Name of the clocks used. >> +  "lsi" for st,stm32-iwdg >> +  "pclk", "lsi" for st,stm32mp1-iwdg >>   Optional Properties: >>   - timeout-sec: Watchdog timeout value in seconds. >> -Example: >> +Examples: >>   iwdg: watchdog@40003000 { >>       compatible = "st,stm32-iwdg"; >>       reg = <0x40003000 0x400>; >>       clocks = <&clk_lsi>; >> +    clock-names = "lsi"; >> +    timeout-sec = <32>; >> +}; >> + >> +iwdg: iwdg@5a002000 { >> +    compatible = "st,stm32mp1-iwdg"; >> +    reg = <0x5a002000 0x400>; >> +    clocks = <&rcc IWDG2>, <&clk_lsi>; >> +    clock-names = "pclk", "lsi"; >>       timeout-sec = <32>; >>   }; >> diff --git a/drivers/watchdog/stm32_iwdg.c >> b/drivers/watchdog/stm32_iwdg.c >> index c97ad56..fc96670 100644 >> --- a/drivers/watchdog/stm32_iwdg.c >> +++ b/drivers/watchdog/stm32_iwdg.c >> @@ -11,12 +11,13 @@ >>   #include >>   #include >> -#include >> -#include >>   #include >>   #include >>   #include >> +#include >> +#include >>   #include >> +#include >>   #include >>   #include >> @@ -54,11 +55,17 @@ >>   #define TIMEOUT_US    100000 >>   #define SLEEP_US    1000 >> +struct stm32_iwdg_config { >> +    bool has_pclk; >> +}; >> + > > This data structure is unnecessary. Just assign the boolean directly to > .data > and ... > Ok, I send a v3, with boolean directly to .data like: #define NO_PCLK false #define HAS_PCLK true ... static const struct of_device_id stm32_iwdg_of_match[] = { { .compatible = "st,stm32-iwdg", .data = (void *) NO_PCLK }, { .compatible = "st,stm32mp1-iwdg", .data = (void *) HAS_PCLK }, { /* end node */ } }; Note: V3, because I sent my original version with V2 (it's mistake) >>   struct stm32_iwdg { >> -    struct watchdog_device    wdd; >> -    void __iomem        *regs; >> -    struct clk        *clk; >> -    unsigned int        rate; >> +    struct watchdog_device        wdd; >> +    void __iomem            *regs; >> +    struct stm32_iwdg_config    *config; > > declare bool has_pclk here. > >> +    struct clk            *clk_lsi; >> +    struct clk            *clk_pclk; >> +    unsigned int            rate; >>   }; >>   static inline u32 reg_read(void __iomem *base, u32 reg) >> @@ -133,6 +140,44 @@ static int stm32_iwdg_set_timeout(struct >> watchdog_device *wdd, >>       return 0; >>   } >> +static int stm32_iwdg_clk_init(struct platform_device *pdev, >> +                   struct stm32_iwdg *wdt) >> +{ >> +    u32 ret; >> + >> +    wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi"); >> +    if (IS_ERR(wdt->clk_lsi)) { >> +        dev_err(&pdev->dev, "Unable to get lsi clock\n"); >> +        return PTR_ERR(wdt->clk_lsi); >> +    } >> + >> +    /* optional peripheral clock */ >> +    if (wdt->config->has_pclk) { >> +        wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk"); >> +        if (IS_ERR(wdt->clk_pclk)) { >> +            dev_err(&pdev->dev, "Unable to get pclk clock\n"); >> +            return PTR_ERR(wdt->clk_pclk); >> +        } >> + >> +        ret = clk_prepare_enable(wdt->clk_pclk); >> +        if (ret) { >> +            dev_err(&pdev->dev, "Unable to prepare pclk clock\n"); >> +            return ret; >> +        } >> +    } >> + >> +    ret = clk_prepare_enable(wdt->clk_lsi); >> +    if (ret) { >> +        dev_err(&pdev->dev, "Unable to prepare lsi clock\n"); >> +        clk_disable_unprepare(wdt->clk_pclk); >> +        return ret; >> +    } >> + >> +    wdt->rate = clk_get_rate(wdt->clk_lsi); >> + >> +    return 0; >> +} >> + >>   static const struct watchdog_info stm32_iwdg_info = { >>       .options    = WDIOF_SETTIMEOUT | >>                 WDIOF_MAGICCLOSE | >> @@ -147,49 +192,50 @@ static const struct watchdog_ops stm32_iwdg_ops = { >>       .set_timeout    = stm32_iwdg_set_timeout, >>   }; >> +static const struct stm32_iwdg_config stm32_iwdg_cfg = { >> +    .has_pclk = false, >> +}; >> + >> +static const struct stm32_iwdg_config stm32mp1_iwdg_cfg = { >> +    .has_pclk = true, >> +}; >> + >> +static const struct of_device_id stm32_iwdg_of_match[] = { >> +    { .compatible = "st,stm32-iwdg", .data = &stm32_iwdg_cfg }, >> +    { .compatible = "st,stm32mp1-iwdg", .data = &stm32mp1_iwdg_cfg }, >> +    { /* end node */ } >> +}; >> +MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); >> + >>   static int stm32_iwdg_probe(struct platform_device *pdev) >>   { >>       struct watchdog_device *wdd; >> +    const struct of_device_id *match; >>       struct stm32_iwdg *wdt; >>       struct resource *res; >> -    void __iomem *regs; >> -    struct clk *clk; >>       int ret; >> +    match = of_match_device(stm32_iwdg_of_match, &pdev->dev); >> +    if (!match || !match->data) >> +        return -ENODEV; >> + >> +    wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); >> +    if (!wdt) >> +        return -ENOMEM; >> + >> +    wdt->config = (struct stm32_iwdg_config *)match->data; >> + >>       /* This is the timer base. */ >>       res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >> -    regs = devm_ioremap_resource(&pdev->dev, res); >> -    if (IS_ERR(regs)) { >> +    wdt->regs = devm_ioremap_resource(&pdev->dev, res); >> +    if (IS_ERR(wdt->regs)) { >>           dev_err(&pdev->dev, "Could not get resource\n"); >> -        return PTR_ERR(regs); >> +        return PTR_ERR(wdt->regs); >>       } >> -    clk = devm_clk_get(&pdev->dev, NULL); >> -    if (IS_ERR(clk)) { >> -        dev_err(&pdev->dev, "Unable to get clock\n"); >> -        return PTR_ERR(clk); >> -    } >> - >> -    ret = clk_prepare_enable(clk); >> -    if (ret) { >> -        dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk); >> +    ret = stm32_iwdg_clk_init(pdev, wdt); >> +    if (ret) >>           return ret; >> -    } >> - >> -    /* >> -     * Allocate our watchdog driver data, which has the >> -     * struct watchdog_device nested within it. >> -     */ >> -    wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); >> -    if (!wdt) { >> -        ret = -ENOMEM; >> -        goto err; >> -    } >> - >> -    /* Initialize struct stm32_iwdg. */ >> -    wdt->regs = regs; >> -    wdt->clk = clk; >> -    wdt->rate = clk_get_rate(clk); >>       /* Initialize struct watchdog_device. */ >>       wdd = &wdt->wdd; >> @@ -217,7 +263,8 @@ static int stm32_iwdg_probe(struct platform_device >> *pdev) >>       return 0; >>   err: >> -    clk_disable_unprepare(clk); >> +    clk_disable_unprepare(wdt->clk_lsi); >> +    clk_disable_unprepare(wdt->clk_pclk); >>       return ret; >>   } >> @@ -227,23 +274,18 @@ static int stm32_iwdg_remove(struct >> platform_device *pdev) >>       struct stm32_iwdg *wdt = platform_get_drvdata(pdev); >>       watchdog_unregister_device(&wdt->wdd); >> -    clk_disable_unprepare(wdt->clk); >> +    clk_disable_unprepare(wdt->clk_lsi); >> +    clk_disable_unprepare(wdt->clk_pclk); >>       return 0; >>   } >> -static const struct of_device_id stm32_iwdg_of_match[] = { >> -    { .compatible = "st,stm32-iwdg" }, >> -    { /* end node */ } >> -}; >> -MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); >> - >>   static struct platform_driver stm32_iwdg_driver = { >>       .probe        = stm32_iwdg_probe, >>       .remove        = stm32_iwdg_remove, >>       .driver = { >>           .name    = "iwdg", >> -        .of_match_table = stm32_iwdg_of_match, >> +        .of_match_table = of_match_ptr(stm32_iwdg_of_match), >>       }, >>   }; >>   module_platform_driver(stm32_iwdg_driver); >> >