[{"id":1773191,"web_url":"http://patchwork.ozlabs.org/comment/1773191/","msgid":"<20170921233609.t65nskglysn4v4qp@rob-hp-laptop>","list_archive_url":null,"date":"2017-09-21T23:36:09","subject":"Re: [PATCH V5] clk: qcom: Add spmi_pmic clock divider support","submitter":{"id":62529,"url":"http://patchwork.ozlabs.org/api/people/62529/","name":"Rob Herring","email":"robh@kernel.org"},"content":"On Tue, Sep 19, 2017 at 04:04:46PM +0530, Tirupathi Reddy wrote:\n> Clkdiv module provides a clock output on the PMIC with CXO as\n> the source. This clock can be routed through PMIC GPIOs. Add\n> a device driver to configure this clkdiv module.\n> \n> Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>\n> ---\n>  .../bindings/clock/clk-spmi-pmic-div.txt           |  56 ++++\n\nAcked-by: Rob Herring <robh@kernel.org>\n\n>  drivers/clk/qcom/Kconfig                           |   9 +\n>  drivers/clk/qcom/Makefile                          |   1 +\n>  drivers/clk/qcom/clk-spmi-pmic-div.c               | 343 +++++++++++++++++++++\n>  4 files changed, 409 insertions(+)\n>  create mode 100644 Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt\n>  create mode 100644 drivers/clk/qcom/clk-spmi-pmic-div.c\n--\nTo unsubscribe from this list: send the line \"unsubscribe devicetree\" in\nthe body of a message to majordomo@vger.kernel.org\nMore majordomo info at  http://vger.kernel.org/majordomo-info.html","headers":{"Return-Path":"<devicetree-owner@vger.kernel.org>","X-Original-To":"incoming-dt@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-dt@bilbo.ozlabs.org","Authentication-Results":"ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=devicetree-owner@vger.kernel.org; receiver=<UNKNOWN>)","Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xytcW0DXhz9t5x\n\tfor <incoming-dt@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 09:49:15 +1000 (AEST)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751898AbdIUXgN (ORCPT\n\t<rfc822;incoming-dt@patchwork.ozlabs.org>);\n\tThu, 21 Sep 2017 19:36:13 -0400","from mail-pf0-f195.google.com ([209.85.192.195]:36948 \"EHLO\n\tmail-pf0-f195.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751728AbdIUXgL (ORCPT\n\t<rfc822; devicetree@vger.kernel.org>); Thu, 21 Sep 2017 19:36:11 -0400","by mail-pf0-f195.google.com with SMTP id e69so3049803pfg.4;\n\tThu, 21 Sep 2017 16:36:10 -0700 (PDT)","from localhost ([2620:0:1000:fd28:e83d:5428:912b:b325])\n\tby smtp.gmail.com with ESMTPSA id\n\td126sm4758712pgc.85.2017.09.21.16.36.09\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tThu, 21 Sep 2017 16:36:09 -0700 (PDT)"],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:in-reply-to:user-agent;\n\tbh=hUioI+T+7LbTdoYbe4mceJEbYnUiKL/V4WWPFttBv30=;\n\tb=slIj3q7cSJXQDF4kQkvrGI8h9YcOcjx7YjEpi3/d0+sZ6+/7jv2nz8v6YA4HSrUOZv\n\tRrHkCNqpr2fAmq6rxXBWaYLCfTMUji3C4iTQ8/sKlRQoW/44net/DkSLKhFEX/nLPvB6\n\tLk19GVvqInv9yD84zoiJyM5E7KhGzymRzaiQlk1Seyw5H3qF8ntn2GeBgQeNn5twK/OR\n\t/oaW27dEcBCDEgoaQCZmsFn4YbxY3d1BxuRGPtDpij62zMWC54dMOKX6oXRFWIjCCZZ+\n\tqYB4qU7fjvnKJfW9Rk5AgZnH+ZthHp3r7sgZL2SqG6s2sa8oxEhYU3AaCxMYQ0AejWri\n\tepyw==","X-Gm-Message-State":"AHPjjUjMh5g4zinawBlMer+k7fMeO1Hgg3fLW3lyUGLiy7ZURZgvT4/D\n\tHl1I9LlAzLf/G20mBYgqPQ==","X-Google-Smtp-Source":"AOwi7QDjNW262NZAmfNw8tpnOtxLv/awVyg/VSwuIA5fDTSInLxM6+A9FyCZch7cWwaN/7Poe8ZKYQ==","X-Received":"by 10.98.102.142 with SMTP id s14mr7185784pfj.174.1506036970515; \n\tThu, 21 Sep 2017 16:36:10 -0700 (PDT)","Date":"Thu, 21 Sep 2017 18:36:09 -0500","From":"Rob Herring <robh@kernel.org>","To":"Tirupathi Reddy <tirupath@codeaurora.org>","Cc":"sboyd@codeaurora.org, mturquette@baylibre.com,\n\tmark.rutland@arm.com, andy.gross@linaro.org,\n\tdavid.brown@linaro.org, linux-clk@vger.kernel.org,\n\tdevicetree@vger.kernel.org, linux-kernel@vger.kernel.org,\n\tlinux-arm-msm@vger.kernel.org, linux-soc@vger.kernel.org","Subject":"Re: [PATCH V5] clk: qcom: Add spmi_pmic clock divider support","Message-ID":"<20170921233609.t65nskglysn4v4qp@rob-hp-laptop>","References":"<1505817286-12445-1-git-send-email-tirupath@codeaurora.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<1505817286-12445-1-git-send-email-tirupath@codeaurora.org>","User-Agent":"NeoMutt/20170113 (1.7.2)","Sender":"devicetree-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<devicetree.vger.kernel.org>","X-Mailing-List":"devicetree@vger.kernel.org"}},{"id":1785986,"web_url":"http://patchwork.ozlabs.org/comment/1785986/","msgid":"<9d5af4da-4c6e-74c8-cf0e-4a480e817707@codeaurora.org>","list_archive_url":null,"date":"2017-10-13T04:16:17","subject":"Re: [PATCH V5] clk: qcom: Add spmi_pmic clock divider support","submitter":{"id":71968,"url":"http://patchwork.ozlabs.org/api/people/71968/","name":"Tirupathi Reddy","email":"tirupath@codeaurora.org"},"content":"Hi Stephen,\n\nCould you please pick the patch ?  All the comments given on older patch \nsets were addressed and the patch is Acked-by Rob Herring.\n\nThanks\nTirupathi\n\nOn 9/19/2017 4:04 PM, Tirupathi Reddy wrote:\n> Clkdiv module provides a clock output on the PMIC with CXO as\n> the source. This clock can be routed through PMIC GPIOs. Add\n> a device driver to configure this clkdiv module.\n>\n> Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>\n> ---\n>   .../bindings/clock/clk-spmi-pmic-div.txt           |  56 ++++\n>   drivers/clk/qcom/Kconfig                           |   9 +\n>   drivers/clk/qcom/Makefile                          |   1 +\n>   drivers/clk/qcom/clk-spmi-pmic-div.c               | 343 +++++++++++++++++++++\n>   4 files changed, 409 insertions(+)\n>   create mode 100644 Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt\n>   create mode 100644 drivers/clk/qcom/clk-spmi-pmic-div.c\n>\n> diff --git a/Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt b/Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt\n> new file mode 100644\n> index 0000000..e37a136\n> --- /dev/null\n> +++ b/Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt\n> @@ -0,0 +1,56 @@\n> +Qualcomm Technologies, Inc. SPMI PMIC clock divider (clkdiv)\n> +\n> +clkdiv configures the clock frequency of a set of outputs on the PMIC.\n> +These clocks are typically wired through alternate functions on\n> +gpio pins.\n> +\n> +=======================\n> +Properties\n> +=======================\n> +\n> +- compatible\n> +\tUsage:      required\n> +\tValue type: <string>\n> +\tDefinition: must be one of:\n> +\t\t    \"qcom,spmi-clkdiv\"\n> +\t\t    \"qcom,pm8998-clkdiv\"\n> +\n> +- reg\n> +\tUsage:      required\n> +\tValue type: <prop-encoded-array>\n> +\tDefinition: Addresses and sizes for the memory of this CLKDIV\n> +\t\t    peripheral.\n> +\n> +- clocks:\n> +\tUsage: required\n> +\tValue type: <prop-encoded-array>\n> +\tDefinition: reference to the xo clock.\n> +\n> +- clock-names:\n> +\tUsage: required\n> +\tValue type: <stringlist>\n> +\tDefinition: must be \"xo\".\n> +\n> +- clock-cells:\n> +\tUsage: required\n> +\tValue type: <u32>\n> +\tDefinition: shall contain 1.\n> +\n> +=======\n> +Example\n> +=======\n> +\n> +pm8998_clk_divs: qcom,clock@5b00 {\n> +\tcompatible = \"qcom,pm8998-clkdiv\";\n> +\treg = <0x5b00>;\n> +\t#clock-cells = <1>;\n> +\tclocks = <&xo_board>;\n> +\tclock-names = \"xo\";\n> +\n> +\tassigned-clocks = <&pm8998_clk_divs 1>,\n> +\t\t\t  <&pm8998_clk_divs 2>,\n> +\t\t\t  <&pm8998_clk_divs 3>;\n> +\tassigned-clock-rates = <9600000>,\n> +\t\t\t       <9600000>,\n> +\t\t\t       <9600000>;\n> +};\n> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig\n> index 9f6c278..dd5b18e 100644\n> --- a/drivers/clk/qcom/Kconfig\n> +++ b/drivers/clk/qcom/Kconfig\n> @@ -196,3 +196,12 @@ config MSM_MMCC_8996\n>   \t  Support for the multimedia clock controller on msm8996 devices.\n>   \t  Say Y if you want to support multimedia devices such as display,\n>   \t  graphics, video encode/decode, camera, etc.\n> +\n> +config SPMI_PMIC_CLKDIV\n> +\ttristate \"spmi pmic clkdiv driver\"\n> +\tdepends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST\n> +\thelp\n> +\t  This driver supports the clkdiv functionality on the Qualcomm\n> +\t  Technologies, Inc. SPMI PMIC. It configures the frequency of\n> +\t  clkdiv outputs on the PMIC. These clocks are typically wired\n> +\t  through alternate functions on gpio pins.\n> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile\n> index 3f3aff2..4d4c62b 100644\n> --- a/drivers/clk/qcom/Makefile\n> +++ b/drivers/clk/qcom/Makefile\n> @@ -33,3 +33,4 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o\n>   obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o\n>   obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o\n>   obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o\n> +obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o\n> diff --git a/drivers/clk/qcom/clk-spmi-pmic-div.c b/drivers/clk/qcom/clk-spmi-pmic-div.c\n> new file mode 100644\n> index 0000000..af343ad\n> --- /dev/null\n> +++ b/drivers/clk/qcom/clk-spmi-pmic-div.c\n> @@ -0,0 +1,343 @@\n> +/* Copyright (c) 2017, The Linux Foundation. All rights reserved.\n> + *\n> + * This program is free software; you can redistribute it and/or modify\n> + * it under the terms of the GNU General Public License version 2 and\n> + * only version 2 as published by the Free Software Foundation.\n> + *\n> + * This program is distributed in the hope that it will be useful,\n> + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n> + * GNU General Public License for more details.\n> + */\n> +\n> +#include <linux/bitops.h>\n> +#include <linux/clk.h>\n> +#include <linux/clk-provider.h>\n> +#include <linux/delay.h>\n> +#include <linux/err.h>\n> +#include <linux/log2.h>\n> +#include <linux/module.h>\n> +#include <linux/of.h>\n> +#include <linux/platform_device.h>\n> +#include <linux/regmap.h>\n> +#include <linux/slab.h>\n> +#include <linux/types.h>\n> +\n> +#define REG_DIV_CTL1\t\t\t0x43\n> +#define DIV_CTL1_DIV_FACTOR_MASK\tGENMASK(2, 0)\n> +\n> +#define REG_EN_CTL\t\t\t0x46\n> +#define REG_EN_MASK\t\t\tBIT(7)\n> +\n> +#define ENABLE_DELAY_NS(cxo_ns, div)\t((2 + 3 * div) * cxo_ns)\n> +#define DISABLE_DELAY_NS(cxo_ns, div)\t((3 * div) * cxo_ns)\n> +\n> +#define CLK_SPMI_PMIC_DIV_OFFSET\t1\n> +\n> +#define CLKDIV_XO_DIV_1_0\t\t0\n> +#define CLKDIV_XO_DIV_1\t\t\t1\n> +#define CLKDIV_XO_DIV_2\t\t\t2\n> +#define CLKDIV_XO_DIV_4\t\t\t3\n> +#define CLKDIV_XO_DIV_8\t\t\t4\n> +#define CLKDIV_XO_DIV_16\t\t5\n> +#define CLKDIV_XO_DIV_32\t\t6\n> +#define CLKDIV_XO_DIV_64\t\t7\n> +#define CLKDIV_MAX_ALLOWED\t\t8\n> +\n> +struct clkdiv {\n> +\tstruct regmap\t\t*regmap;\n> +\tu16\t\t\tbase;\n> +\tspinlock_t\t\tlock;\n> +\n> +\t/* clock properties */\n> +\tstruct clk_hw\t\thw;\n> +\tunsigned int\t\tdiv_factor;\n> +\tunsigned int\t\tcxo_period_ns;\n> +};\n> +\n> +static inline struct clkdiv *to_clkdiv(struct clk_hw *hw)\n> +{\n> +\treturn container_of(hw, struct clkdiv, hw);\n> +}\n> +\n> +static inline unsigned int div_factor_to_div(unsigned int div_factor)\n> +{\n> +\tif (div_factor == CLKDIV_XO_DIV_1_0)\n> +\t\treturn 1;\n> +\n> +\treturn 1 << (div_factor - CLK_SPMI_PMIC_DIV_OFFSET);\n> +}\n> +\n> +static inline unsigned int div_to_div_factor(unsigned int div)\n> +{\n> +\treturn min(ilog2(div) + CLK_SPMI_PMIC_DIV_OFFSET,\n> +\t\t   CLKDIV_MAX_ALLOWED - 1);\n> +}\n> +\n> +static bool is_spmi_pmic_clkdiv_enabled(struct clkdiv *clkdiv)\n> +{\n> +\tunsigned int val = 0;\n> +\n> +\tregmap_read(clkdiv->regmap, clkdiv->base + REG_EN_CTL,\n> +\t\t\t &val);\n> +\treturn (val & REG_EN_MASK) ? true : false;\n> +}\n> +\n> +static int spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv,\n> +\t\t\tbool enable_state)\n> +{\n> +\tint rc;\n> +\n> +\trc = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_EN_CTL,\n> +\t\t\t\tREG_EN_MASK,\n> +\t\t\t\t(enable_state == true) ? REG_EN_MASK : 0);\n> +\tif (rc)\n> +\t\treturn rc;\n> +\n> +\tif (enable_state == true)\n> +\t\tndelay(ENABLE_DELAY_NS(clkdiv->cxo_period_ns,\n> +\t\t\t\tdiv_factor_to_div(clkdiv->div_factor)));\n> +\telse\n> +\t\tndelay(DISABLE_DELAY_NS(clkdiv->cxo_period_ns,\n> +\t\t\t\tdiv_factor_to_div(clkdiv->div_factor)));\n> +\n> +\treturn rc;\n> +}\n> +\n> +static int spmi_pmic_clkdiv_config_freq_div(struct clkdiv *clkdiv,\n> +\t\t\tunsigned int div)\n> +{\n> +\tunsigned int div_factor;\n> +\tunsigned long flags;\n> +\tbool enabled;\n> +\tint rc;\n> +\n> +\tdiv_factor = div_to_div_factor(div);\n> +\n> +\tspin_lock_irqsave(&clkdiv->lock, flags);\n> +\n> +\tenabled = is_spmi_pmic_clkdiv_enabled(clkdiv);\n> +\tif (enabled) {\n> +\t\trc = spmi_pmic_clkdiv_set_enable_state(clkdiv, false);\n> +\t\tif (rc)\n> +\t\t\tgoto fail;\n> +\t}\n> +\n> +\trc = regmap_update_bits(clkdiv->regmap,\n> +\t\t\t\tclkdiv->base + REG_DIV_CTL1,\n> +\t\t\t\tDIV_CTL1_DIV_FACTOR_MASK, div_factor);\n> +\tif (rc)\n> +\t\tgoto fail;\n> +\n> +\tclkdiv->div_factor = div_factor;\n> +\n> +\tif (enabled)\n> +\t\trc = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);\n> +\n> +fail:\n> +\tspin_unlock_irqrestore(&clkdiv->lock, flags);\n> +\treturn rc;\n> +}\n> +\n> +static int clk_spmi_pmic_div_enable(struct clk_hw *hw)\n> +{\n> +\tstruct clkdiv *clkdiv = to_clkdiv(hw);\n> +\tunsigned long flags;\n> +\tint rc;\n> +\n> +\tspin_lock_irqsave(&clkdiv->lock, flags);\n> +\trc = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);\n> +\tspin_unlock_irqrestore(&clkdiv->lock, flags);\n> +\n> +\treturn rc;\n> +}\n> +\n> +static void clk_spmi_pmic_div_disable(struct clk_hw *hw)\n> +{\n> +\tstruct clkdiv *clkdiv = to_clkdiv(hw);\n> +\tunsigned long flags;\n> +\n> +\tspin_lock_irqsave(&clkdiv->lock, flags);\n> +\tspmi_pmic_clkdiv_set_enable_state(clkdiv, false);\n> +\tspin_unlock_irqrestore(&clkdiv->lock, flags);\n> +}\n> +\n> +static long clk_spmi_pmic_div_round_rate(struct clk_hw *hw, unsigned long rate,\n> +\t\t\tunsigned long *parent_rate)\n> +{\n> +\tunsigned long new_rate;\n> +\tunsigned int div, div_factor;\n> +\n> +\tdiv = DIV_ROUND_UP(*parent_rate, rate);\n> +\tdiv_factor = div_to_div_factor(div);\n> +\tnew_rate = *parent_rate / div_factor_to_div(div_factor);\n> +\n> +\treturn new_rate;\n> +}\n> +\n> +static unsigned long clk_spmi_pmic_div_recalc_rate(struct clk_hw *hw,\n> +\t\t\tunsigned long parent_rate)\n> +{\n> +\tstruct clkdiv *clkdiv = to_clkdiv(hw);\n> +\tunsigned long rate;\n> +\n> +\trate = parent_rate / div_factor_to_div(clkdiv->div_factor);\n> +\n> +\treturn rate;\n> +}\n> +\n> +static int clk_spmi_pmic_div_set_rate(struct clk_hw *hw, unsigned long rate,\n> +\t\t\tunsigned long parent_rate)\n> +{\n> +\tstruct clkdiv *clkdiv = to_clkdiv(hw);\n> +\n> +\treturn spmi_pmic_clkdiv_config_freq_div(clkdiv, parent_rate / rate);\n> +}\n> +\n> +static const struct clk_ops clk_spmi_pmic_div_ops = {\n> +\t.enable = clk_spmi_pmic_div_enable,\n> +\t.disable = clk_spmi_pmic_div_disable,\n> +\t.set_rate = clk_spmi_pmic_div_set_rate,\n> +\t.recalc_rate = clk_spmi_pmic_div_recalc_rate,\n> +\t.round_rate = clk_spmi_pmic_div_round_rate,\n> +};\n> +\n> +struct spmi_pmic_div_clk_cc {\n> +\tstruct clk_hw\t**div_clks;\n> +\tint\t\tnclks;\n> +};\n> +\n> +#define SPMI_PMIC_CLKDIV_MIN_INDEX\t1\n> +\n> +static struct clk_hw *spmi_pmic_div_clk_hw_get(struct of_phandle_args *clkspec,\n> +\t\t\t\t      void *data)\n> +{\n> +\tstruct spmi_pmic_div_clk_cc *clk_cc = data;\n> +\tunsigned int idx = (clkspec->args[0] - SPMI_PMIC_CLKDIV_MIN_INDEX);\n> +\n> +\tif (idx < 0 || idx >= clk_cc->nclks) {\n> +\t\tpr_err(\"%s: index value %u is invalid; allowed range: [%d, %d]\\n\",\n> +\t\t       __func__, clkspec->args[0], SPMI_PMIC_CLKDIV_MIN_INDEX,\n> +\t\t       clk_cc->nclks);\n> +\t\treturn ERR_PTR(-EINVAL);\n> +\t}\n> +\n> +\treturn clk_cc->div_clks[idx];\n> +}\n> +\n> +#define SPMI_PMIC_DIV_CLK_SIZE\t\t0x100\n> +\n> +static const struct of_device_id spmi_pmic_clkdiv_match_table[] = {\n> +\t{\n> +\t\t.compatible = \"qcom,spmi-clkdiv\",\n> +\t\t.data =  (void *)(uintptr_t)1,\t\t/* Generic */\n> +\t},\n> +\t{\n> +\t\t.compatible = \"qcom,pm8998-clkdiv\",\n> +\t\t.data =  (void *)(uintptr_t)3,\t\t/* 3 div_clks */\n> +\t},\n> +\t{ /* sentinel */ }\n> +};\n> +MODULE_DEVICE_TABLE(of, spmi_pmic_clkdiv_match_table);\n> +\n> +static int spmi_pmic_clkdiv_probe(struct platform_device *pdev)\n> +{\n> +\tstruct spmi_pmic_div_clk_cc *clk_cc;\n> +\tstruct clk_init_data init = {};\n> +\tstruct clkdiv *clkdiv;\n> +\tstruct clk *cxo;\n> +\tstruct regmap *regmap;\n> +\tstruct device *dev = &pdev->dev;\n> +\tconst char *parent_name;\n> +\tint nclks, i, rc, cxo_hz;\n> +\tu32 start;\n> +\n> +\trc = of_property_read_u32(dev->of_node, \"reg\", &start);\n> +\tif (rc < 0) {\n> +\t\tdev_err(dev, \"reg property reading failed\\n\");\n> +\t\treturn rc;\n> +\t}\n> +\n> +\tregmap = dev_get_regmap(dev->parent, NULL);\n> +\tif (!regmap) {\n> +\t\tdev_err(dev, \"Couldn't get parent's regmap\\n\");\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tnclks = (uintptr_t)of_match_node(spmi_pmic_clkdiv_match_table,\n> +\t\t\t\t\t dev->of_node)->data;\n> +\n> +\tclkdiv = devm_kcalloc(dev, nclks, sizeof(*clkdiv), GFP_KERNEL);\n> +\tif (!clkdiv)\n> +\t\treturn -ENOMEM;\n> +\n> +\tclk_cc = devm_kzalloc(&pdev->dev, sizeof(*clk_cc), GFP_KERNEL);\n> +\tif (!clk_cc)\n> +\t\treturn -ENOMEM;\n> +\n> +\tclk_cc->div_clks = devm_kcalloc(&pdev->dev, nclks,\n> +\t\t\t\t\tsizeof(*clk_cc->div_clks), GFP_KERNEL);\n> +\tif (!clk_cc->div_clks)\n> +\t\treturn -ENOMEM;\n> +\n> +\tcxo = clk_get(dev, \"xo\");\n> +\tif (IS_ERR(cxo)) {\n> +\t\trc = PTR_ERR(cxo);\n> +\t\tif (rc != -EPROBE_DEFER)\n> +\t\t\tdev_err(dev, \"failed to get xo clock\");\n> +\t\treturn rc;\n> +\t}\n> +\tcxo_hz = clk_get_rate(cxo);\n> +\tclk_put(cxo);\n> +\n> +\tparent_name = of_clk_get_parent_name(dev->of_node, 0);\n> +\tif (!parent_name) {\n> +\t\tdev_err(dev, \"missing parent clock\\n\");\n> +\t\treturn -ENODEV;\n> +\t}\n> +\n> +\tinit.parent_names = &parent_name;\n> +\tinit.num_parents = parent_name ? 1 : 0;\n> +\tinit.ops = &clk_spmi_pmic_div_ops;\n> +\tinit.flags = 0;\n> +\n> +\tfor (i = 0; i < nclks; i++) {\n> +\t\tspin_lock_init(&clkdiv[i].lock);\n> +\t\tclkdiv[i].base = start + i * SPMI_PMIC_DIV_CLK_SIZE;\n> +\t\tclkdiv[i].regmap = regmap;\n> +\t\tclkdiv[i].cxo_period_ns = NSEC_PER_SEC / cxo_hz;\n> +\t\tinit.name = kasprintf(GFP_KERNEL, \"div_clk%d\", i + 1);\n> +\t\tclkdiv[i].hw.init = &init;\n> +\t\trc = devm_clk_hw_register(dev, &clkdiv[i].hw);\n> +\t\tkfree(init.name); /* clock framework made a copy of the name */\n> +\t\tif (rc)\n> +\t\t\treturn rc;\n> +\n> +\t\tclk_cc->div_clks[i] = &clkdiv[i].hw;\n> +\t}\n> +\n> +\tclk_cc->nclks = nclks;\n> +\trc = of_clk_add_hw_provider(pdev->dev.of_node, spmi_pmic_div_clk_hw_get,\n> +\t\t\t\t    clk_cc);\n> +\treturn rc;\n> +}\n> +\n> +static int spmi_pmic_clkdiv_remove(struct platform_device *pdev)\n> +{\n> +\tof_clk_del_provider(pdev->dev.of_node);\n> +\n> +\treturn 0;\n> +}\n> +\n> +static struct platform_driver spmi_pmic_clkdiv_driver = {\n> +\t.driver\t\t= {\n> +\t\t.name\t= \"qcom,spmi-pmic-clkdiv\",\n> +\t\t.of_match_table = spmi_pmic_clkdiv_match_table,\n> +\t},\n> +\t.probe\t\t= spmi_pmic_clkdiv_probe,\n> +\t.remove\t\t= spmi_pmic_clkdiv_remove,\n> +};\n> +module_platform_driver(spmi_pmic_clkdiv_driver);\n> +\n> +MODULE_DESCRIPTION(\"QCOM SPMI PMIC clkdiv driver\");\n> +MODULE_LICENSE(\"GPL v2\");\n\n--\nTo unsubscribe from this list: send the line \"unsubscribe devicetree\" in\nthe body of a message to majordomo@vger.kernel.org\nMore majordomo info at  http://vger.kernel.org/majordomo-info.html","headers":{"Return-Path":"<devicetree-owner@vger.kernel.org>","X-Original-To":"incoming-dt@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-dt@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=devicetree-owner@vger.kernel.org; receiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=codeaurora.org header.i=@codeaurora.org\n\theader.b=\"Y2V+fOh0\"; \n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n\theader.d=codeaurora.org header.i=@codeaurora.org header.b=\"OdWXOhfw\"; \n\tdkim-atps=neutral","pdx-caf-mail.web.codeaurora.org;\n\tdmarc=none (p=none dis=none) header.from=codeaurora.org","pdx-caf-mail.web.codeaurora.org;\n\tspf=none smtp.mailfrom=tirupath@codeaurora.org"],"Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3yCvYR3R7Zz9sP1\n\tfor <incoming-dt@patchwork.ozlabs.org>;\n\tFri, 13 Oct 2017 15:16:43 +1100 (AEDT)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1753425AbdJMEQ2 (ORCPT\n\t<rfc822;incoming-dt@patchwork.ozlabs.org>);\n\tFri, 13 Oct 2017 00:16:28 -0400","from smtp.codeaurora.org ([198.145.29.96]:41258 \"EHLO\n\tsmtp.codeaurora.org\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1750785AbdJMEQ0 (ORCPT\n\t<rfc822; devicetree@vger.kernel.org>); Fri, 13 Oct 2017 00:16:26 -0400","by smtp.codeaurora.org (Postfix, from userid 1000)\n\tid 18CE26071B; Fri, 13 Oct 2017 04:16:25 +0000 (UTC)","from [10.206.28.43]\n\t(blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com\n\t[103.229.19.19])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128\n\tbits)) (No client certificate requested)\n\t(Authenticated sender: tirupath@smtp.codeaurora.org)\n\tby smtp.codeaurora.org (Postfix) with ESMTPSA id 98B0F6014C;\n\tFri, 13 Oct 2017 04:16:20 +0000 (UTC)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org;\n\ts=default; t=1507868186;\n\tbh=+13FEaxMWjWjcpXkHPxqYWpEyWX/y5J1Rf7NczYWxmY=;\n\th=Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=Y2V+fOh0CXYw5lO1j28ai6kckvsQElRkDIKbVEOV8FE4wpfo2+ROo3EPAvpPI7u4/\n\tK9BFlsHmkGY1DpohfATACnUv1HuLZ5vu4h+rDUy1XZXPVPmrZELGxdUCc6kMm054xi\n\tIzyUJ0sf2Qxg8WmEAhNPQtFK45f9OVQC18fvayZM=","v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org;\n\ts=default; t=1507868184;\n\tbh=+13FEaxMWjWjcpXkHPxqYWpEyWX/y5J1Rf7NczYWxmY=;\n\th=Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=OdWXOhfwvdcgB+rMd3pRtwHjsLiB52bpH5bE6pawyuxH6SEHK26uZFtpSI6IiJo7h\n\t3Ndo2maCyNh3sPsKftsquGP6GUQEQ3jGTC2QlRAkoWlfTVrRj6X6RYQVSU7849uInS\n\tIGWwB3qQpzO3UIkI/cSL9MgWJFT/+dUFPFzETqSs="],"X-Spam-Checker-Version":"SpamAssassin 3.4.0 (2014-02-07) on\n\tpdx-caf-mail.web.codeaurora.org","X-Spam-Level":"","X-Spam-Status":"No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00,\n\tDKIM_SIGNED,\n\tT_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0","DMARC-Filter":"OpenDMARC Filter v1.3.2 smtp.codeaurora.org 98B0F6014C","Subject":"Re: [PATCH V5] clk: qcom: Add spmi_pmic clock divider support","To":"sboyd@codeaurora.org","Cc":"mturquette@baylibre.com, robh+dt@kernel.org, mark.rutland@arm.com,\n\tandy.gross@linaro.org, david.brown@linaro.org,\n\tlinux-clk@vger.kernel.org, devicetree@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,\n\tlinux-soc@vger.kernel.org","References":"<1505817286-12445-1-git-send-email-tirupath@codeaurora.org>","From":"Tirupathi Reddy T <tirupath@codeaurora.org>","Message-ID":"<9d5af4da-4c6e-74c8-cf0e-4a480e817707@codeaurora.org>","Date":"Fri, 13 Oct 2017 09:46:17 +0530","User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101\n\tThunderbird/52.3.0","MIME-Version":"1.0","In-Reply-To":"<1505817286-12445-1-git-send-email-tirupath@codeaurora.org>","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Transfer-Encoding":"8bit","Content-Language":"en-US","Sender":"devicetree-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<devicetree.vger.kernel.org>","X-Mailing-List":"devicetree@vger.kernel.org"}},{"id":1806217,"web_url":"http://patchwork.ozlabs.org/comment/1806217/","msgid":"<86711b65-52a8-d96a-1039-3e5fc52a027f@codeaurora.org>","list_archive_url":null,"date":"2017-11-17T10:01:13","subject":"Re: [PATCH V5] clk: qcom: Add spmi_pmic clock divider support","submitter":{"id":71968,"url":"http://patchwork.ozlabs.org/api/people/71968/","name":"Tirupathi Reddy","email":"tirupath@codeaurora.org"},"content":"On 11/15/2017 10:36 PM, Stephen Boyd wrote:\n> On 09/19, Tirupathi Reddy wrote:\n>> diff --git a/Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt b/Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt\n>> new file mode 100644\n>> index 0000000..e37a136\n>> --- /dev/null\n>> +++ b/Documentation/devicetree/bindings/clock/clk-spmi-pmic-div.txt\n>> @@ -0,0 +1,56 @@\n>> +Qualcomm Technologies, Inc. SPMI PMIC clock divider (clkdiv)\n>> +\n>> +clkdiv configures the clock frequency of a set of outputs on the PMIC.\n>> +These clocks are typically wired through alternate functions on\n>> +gpio pins.\n>> +\n>> +=======================\n>> +Properties\n>> +=======================\n>> +\n>> +- compatible\n>> +\tUsage:      required\n>> +\tValue type: <string>\n>> +\tDefinition: must be one of:\n>> +\t\t    \"qcom,spmi-clkdiv\"\n>> +\t\t    \"qcom,pm8998-clkdiv\"\n>> +\n>> +- reg\n>> +\tUsage:      required\n>> +\tValue type: <prop-encoded-array>\n>> +\tDefinition: Addresses and sizes for the memory of this CLKDIV\n> There's no size though.\nFixed in Patch version 6.\n>\n>> +\t\t    peripheral.\n>> +\n>> +- clocks:\n>> +\tUsage: required\n>> +\tValue type: <prop-encoded-array>\n>> +\tDefinition: reference to the xo clock.\n>> +\n>> +- clock-names:\n>> +\tUsage: required\n>> +\tValue type: <stringlist>\n>> +\tDefinition: must be \"xo\".\n>> +\n>> +- clock-cells:\n>> +\tUsage: required\n>> +\tValue type: <u32>\n>> +\tDefinition: shall contain 1.\n> Can we get a property to indicate the number of clks? Something\n> like \"qcom,num-clkdivs\" or something like that. That would make\n> things easier to handle in the driver because we could match the\n> generic compatible and look for the property and then populate\n> that many clks. Otherwise, we're going to need a \"small\" driver\n> update for each PMIC just because the number of clks changes.\n>\n> Of course we're going to need to update the binding to add the\n> new PMIC compatibles as new things are created, but I'd like to\n> avoid driver updates for the compatible. If someone messes up the\n> number we can always fallback to matching the more specific\n> compatible and fix it up in the driver, but let's hope that\n> doesn't happen.\nFixed in Patch version 6.\n>\n>> +\n>> +=======\n>> +Example\n>> +=======\n>> +\n>> +pm8998_clk_divs: qcom,clock@5b00 {\n> clock-controller@5b00?\nFixed in Patch version 6.\n>\n>> +\tcompatible = \"qcom,pm8998-clkdiv\";\n>> +\treg = <0x5b00>;\n>> +\t#clock-cells = <1>;\n>> +\tclocks = <&xo_board>;\n>> +\tclock-names = \"xo\";\n>> +\n>> +\tassigned-clocks = <&pm8998_clk_divs 1>,\n>> +\t\t\t  <&pm8998_clk_divs 2>,\n>> +\t\t\t  <&pm8998_clk_divs 3>;\n>> +\tassigned-clock-rates = <9600000>,\n>> +\t\t\t       <9600000>,\n>> +\t\t\t       <9600000>;\n>> +};\n>> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig\n>> index 9f6c278..dd5b18e 100644\n>> --- a/drivers/clk/qcom/Kconfig\n>> +++ b/drivers/clk/qcom/Kconfig\n>> @@ -196,3 +196,12 @@ config MSM_MMCC_8996\n>>   \t  Support for the multimedia clock controller on msm8996 devices.\n>>   \t  Say Y if you want to support multimedia devices such as display,\n>>   \t  graphics, video encode/decode, camera, etc.\n>> +\n>> +config SPMI_PMIC_CLKDIV\n>> +\ttristate \"spmi pmic clkdiv driver\"\n> Capitalize SPMI and PMIC and replace driver with something else.\nFixed in Patch version 6.\n>\n>> +\tdepends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST\n>> +\thelp\n>> +\t  This driver supports the clkdiv functionality on the Qualcomm\n>> +\t  Technologies, Inc. SPMI PMIC. It configures the frequency of\n>> +\t  clkdiv outputs on the PMIC. These clocks are typically wired\n>> +\t  through alternate functions on gpio pins.\n> I rewrote a bunch of stuff in the driver. Let me know if anything\n> doesn't work.\nVerified. The changes look good.\n>\n> ----8<----\n> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig\n> index dd5b18ecd9d1..20b5d6fd501d 100644\n> --- a/drivers/clk/qcom/Kconfig\n> +++ b/drivers/clk/qcom/Kconfig\n> @@ -198,10 +198,10 @@ config MSM_MMCC_8996\n>   \t  graphics, video encode/decode, camera, etc.\n>   \n>   config SPMI_PMIC_CLKDIV\n> -\ttristate \"spmi pmic clkdiv driver\"\n> +\ttristate \"SPMI PMIC clkdiv Support\"\n>   \tdepends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST\n>   \thelp\n>   \t  This driver supports the clkdiv functionality on the Qualcomm\n>   \t  Technologies, Inc. SPMI PMIC. It configures the frequency of\n> -\t  clkdiv outputs on the PMIC. These clocks are typically wired\n> -\t  through alternate functions on gpio pins.\n> +\t  clkdiv outputs of the PMIC. These clocks are typically wired\n> +\t  through alternate functions on GPIO pins.\n> diff --git a/drivers/clk/qcom/clk-spmi-pmic-div.c b/drivers/clk/qcom/clk-spmi-pmic-div.c\n> index af343ad2ee0b..a7217ee9f741 100644\n> --- a/drivers/clk/qcom/clk-spmi-pmic-div.c\n> +++ b/drivers/clk/qcom/clk-spmi-pmic-div.c\n> @@ -18,6 +18,7 @@\n>   #include <linux/log2.h>\n>   #include <linux/module.h>\n>   #include <linux/of.h>\n> +#include <linux/of_device.h>\n>   #include <linux/platform_device.h>\n>   #include <linux/regmap.h>\n>   #include <linux/slab.h>\n> @@ -29,29 +30,12 @@\n>   #define REG_EN_CTL\t\t\t0x46\n>   #define REG_EN_MASK\t\t\tBIT(7)\n>   \n> -#define ENABLE_DELAY_NS(cxo_ns, div)\t((2 + 3 * div) * cxo_ns)\n> -#define DISABLE_DELAY_NS(cxo_ns, div)\t((3 * div) * cxo_ns)\n> -\n> -#define CLK_SPMI_PMIC_DIV_OFFSET\t1\n> -\n> -#define CLKDIV_XO_DIV_1_0\t\t0\n> -#define CLKDIV_XO_DIV_1\t\t\t1\n> -#define CLKDIV_XO_DIV_2\t\t\t2\n> -#define CLKDIV_XO_DIV_4\t\t\t3\n> -#define CLKDIV_XO_DIV_8\t\t\t4\n> -#define CLKDIV_XO_DIV_16\t\t5\n> -#define CLKDIV_XO_DIV_32\t\t6\n> -#define CLKDIV_XO_DIV_64\t\t7\n> -#define CLKDIV_MAX_ALLOWED\t\t8\n> -\n>   struct clkdiv {\n>   \tstruct regmap\t\t*regmap;\n>   \tu16\t\t\tbase;\n>   \tspinlock_t\t\tlock;\n>   \n> -\t/* clock properties */\n>   \tstruct clk_hw\t\thw;\n> -\tunsigned int\t\tdiv_factor;\n>   \tunsigned int\t\tcxo_period_ns;\n>   };\n>   \n> @@ -62,94 +46,68 @@ static inline struct clkdiv *to_clkdiv(struct clk_hw *hw)\n>   \n>   static inline unsigned int div_factor_to_div(unsigned int div_factor)\n>   {\n> -\tif (div_factor == CLKDIV_XO_DIV_1_0)\n> -\t\treturn 1;\n> +\tif (!div_factor)\n> +\t\tdiv_factor = 1;\n>   \n> -\treturn 1 << (div_factor - CLK_SPMI_PMIC_DIV_OFFSET);\n> +\treturn 1 << (div_factor - 1);\n>   }\n>   \n>   static inline unsigned int div_to_div_factor(unsigned int div)\n>   {\n> -\treturn min(ilog2(div) + CLK_SPMI_PMIC_DIV_OFFSET,\n> -\t\t   CLKDIV_MAX_ALLOWED - 1);\n> +\treturn min(ilog2(div) + 1, 7);\n>   }\n>   \n>   static bool is_spmi_pmic_clkdiv_enabled(struct clkdiv *clkdiv)\n>   {\n>   \tunsigned int val = 0;\n>   \n> -\tregmap_read(clkdiv->regmap, clkdiv->base + REG_EN_CTL,\n> -\t\t\t &val);\n> -\treturn (val & REG_EN_MASK) ? true : false;\n> +\tregmap_read(clkdiv->regmap, clkdiv->base + REG_EN_CTL, &val);\n> +\n> +\treturn val & REG_EN_MASK;\n>   }\n>   \n> -static int spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv,\n> -\t\t\tbool enable_state)\n> +static int\n> +__spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool enable,\n> +\t\t\t\t    unsigned int div_factor)\n>   {\n> -\tint rc;\n> +\tint ret;\n> +\tunsigned int ns = clkdiv->cxo_period_ns;\n> +\tunsigned int div = div_factor_to_div(div_factor);\n>   \n> -\trc = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_EN_CTL,\n> -\t\t\t\tREG_EN_MASK,\n> -\t\t\t\t(enable_state == true) ? REG_EN_MASK : 0);\n> -\tif (rc)\n> -\t\treturn rc;\n> +\tret = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_EN_CTL,\n> +\t\t\t\t REG_EN_MASK, enable ? REG_EN_MASK : 0);\n> +\tif (ret)\n> +\t\treturn ret;\n>   \n> -\tif (enable_state == true)\n> -\t\tndelay(ENABLE_DELAY_NS(clkdiv->cxo_period_ns,\n> -\t\t\t\tdiv_factor_to_div(clkdiv->div_factor)));\n> +\tif (enable)\n> +\t\tndelay((2 + 3 * div) * ns);\n>   \telse\n> -\t\tndelay(DISABLE_DELAY_NS(clkdiv->cxo_period_ns,\n> -\t\t\t\tdiv_factor_to_div(clkdiv->div_factor)));\n> +\t\tndelay(3 * div * ns);\n>   \n> -\treturn rc;\n> +\treturn 0;\n>   }\n>   \n> -static int spmi_pmic_clkdiv_config_freq_div(struct clkdiv *clkdiv,\n> -\t\t\tunsigned int div)\n> +static int spmi_pmic_clkdiv_set_enable_state(struct clkdiv *clkdiv, bool enable)\n>   {\n>   \tunsigned int div_factor;\n> -\tunsigned long flags;\n> -\tbool enabled;\n> -\tint rc;\n> -\n> -\tdiv_factor = div_to_div_factor(div);\n> -\n> -\tspin_lock_irqsave(&clkdiv->lock, flags);\n> -\n> -\tenabled = is_spmi_pmic_clkdiv_enabled(clkdiv);\n> -\tif (enabled) {\n> -\t\trc = spmi_pmic_clkdiv_set_enable_state(clkdiv, false);\n> -\t\tif (rc)\n> -\t\t\tgoto fail;\n> -\t}\n>   \n> -\trc = regmap_update_bits(clkdiv->regmap,\n> -\t\t\t\tclkdiv->base + REG_DIV_CTL1,\n> -\t\t\t\tDIV_CTL1_DIV_FACTOR_MASK, div_factor);\n> -\tif (rc)\n> -\t\tgoto fail;\n> +\tregmap_read(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1, &div_factor);\n> +\tdiv_factor &= DIV_CTL1_DIV_FACTOR_MASK;\n>   \n> -\tclkdiv->div_factor = div_factor;\n> -\n> -\tif (enabled)\n> -\t\trc = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);\n> -\n> -fail:\n> -\tspin_unlock_irqrestore(&clkdiv->lock, flags);\n> -\treturn rc;\n> +\treturn __spmi_pmic_clkdiv_set_enable_state(clkdiv, enable, div_factor);\n>   }\n>   \n>   static int clk_spmi_pmic_div_enable(struct clk_hw *hw)\n>   {\n>   \tstruct clkdiv *clkdiv = to_clkdiv(hw);\n>   \tunsigned long flags;\n> -\tint rc;\n> +\tint ret;\n>   \n>   \tspin_lock_irqsave(&clkdiv->lock, flags);\n> -\trc = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);\n> +\tret = spmi_pmic_clkdiv_set_enable_state(clkdiv, true);\n>   \tspin_unlock_irqrestore(&clkdiv->lock, flags);\n>   \n> -\treturn rc;\n> +\treturn ret;\n>   }\n>   \n>   static void clk_spmi_pmic_div_disable(struct clk_hw *hw)\n> @@ -163,35 +121,59 @@ static void clk_spmi_pmic_div_disable(struct clk_hw *hw)\n>   }\n>   \n>   static long clk_spmi_pmic_div_round_rate(struct clk_hw *hw, unsigned long rate,\n> -\t\t\tunsigned long *parent_rate)\n> +\t\t\t\t\t unsigned long *parent_rate)\n>   {\n> -\tunsigned long new_rate;\n>   \tunsigned int div, div_factor;\n>   \n>   \tdiv = DIV_ROUND_UP(*parent_rate, rate);\n>   \tdiv_factor = div_to_div_factor(div);\n> -\tnew_rate = *parent_rate / div_factor_to_div(div_factor);\n> +\tdiv = div_factor_to_div(div_factor);\n>   \n> -\treturn new_rate;\n> +\treturn *parent_rate / div;\n>   }\n>   \n> -static unsigned long clk_spmi_pmic_div_recalc_rate(struct clk_hw *hw,\n> -\t\t\tunsigned long parent_rate)\n> +static unsigned long\n> +clk_spmi_pmic_div_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)\n>   {\n>   \tstruct clkdiv *clkdiv = to_clkdiv(hw);\n> -\tunsigned long rate;\n> +\tunsigned int div_factor;\n>   \n> -\trate = parent_rate / div_factor_to_div(clkdiv->div_factor);\n> +\tregmap_read(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1, &div_factor);\n> +\tdiv_factor &= DIV_CTL1_DIV_FACTOR_MASK;\n>   \n> -\treturn rate;\n> +\treturn parent_rate / div_factor_to_div(div_factor);\n>   }\n>   \n>   static int clk_spmi_pmic_div_set_rate(struct clk_hw *hw, unsigned long rate,\n> -\t\t\tunsigned long parent_rate)\n> +\t\t\t\t      unsigned long parent_rate)\n>   {\n>   \tstruct clkdiv *clkdiv = to_clkdiv(hw);\n> +\tunsigned int div_factor = div_to_div_factor(parent_rate / rate);\n> +\tunsigned long flags;\n> +\tbool enabled;\n> +\tint ret;\n> +\n> +\tspin_lock_irqsave(&clkdiv->lock, flags);\n> +\tenabled = is_spmi_pmic_clkdiv_enabled(clkdiv);\n> +\tif (enabled) {\n> +\t\tret = spmi_pmic_clkdiv_set_enable_state(clkdiv, false);\n> +\t\tif (ret)\n> +\t\t\tgoto unlock;\n> +\t}\n> +\n> +\tret = regmap_update_bits(clkdiv->regmap, clkdiv->base + REG_DIV_CTL1,\n> +\t\t\t\t DIV_CTL1_DIV_FACTOR_MASK, div_factor);\n> +\tif (ret)\n> +\t\tgoto unlock;\n> +\n> +\tif (enabled)\n> +\t\tret = __spmi_pmic_clkdiv_set_enable_state(clkdiv, true,\n> +\t\t\t\t\t\t\t  div_factor);\n>   \n> -\treturn spmi_pmic_clkdiv_config_freq_div(clkdiv, parent_rate / rate);\n> +unlock:\n> +\tspin_unlock_irqrestore(&clkdiv->lock, flags);\n> +\n> +\treturn ret;\n>   }\n>   \n>   static const struct clk_ops clk_spmi_pmic_div_ops = {\n> @@ -203,30 +185,25 @@ static const struct clk_ops clk_spmi_pmic_div_ops = {\n>   };\n>   \n>   struct spmi_pmic_div_clk_cc {\n> -\tstruct clk_hw\t**div_clks;\n>   \tint\t\tnclks;\n> +\tstruct clkdiv\tclks[];\n>   };\n>   \n> -#define SPMI_PMIC_CLKDIV_MIN_INDEX\t1\n> -\n> -static struct clk_hw *spmi_pmic_div_clk_hw_get(struct of_phandle_args *clkspec,\n> -\t\t\t\t      void *data)\n> +static struct clk_hw *\n> +spmi_pmic_div_clk_hw_get(struct of_phandle_args *clkspec, void *data)\n>   {\n> -\tstruct spmi_pmic_div_clk_cc *clk_cc = data;\n> -\tunsigned int idx = (clkspec->args[0] - SPMI_PMIC_CLKDIV_MIN_INDEX);\n> +\tstruct spmi_pmic_div_clk_cc *cc = data;\n> +\tint idx = clkspec->args[0] - 1; /* Start at 1 instead of 0 */\n>   \n> -\tif (idx < 0 || idx >= clk_cc->nclks) {\n> -\t\tpr_err(\"%s: index value %u is invalid; allowed range: [%d, %d]\\n\",\n> -\t\t       __func__, clkspec->args[0], SPMI_PMIC_CLKDIV_MIN_INDEX,\n> -\t\t       clk_cc->nclks);\n> +\tif (idx < 0 || idx >= cc->nclks) {\n> +\t\tpr_err(\"%s: index value %u is invalid; allowed range [1, %d]\\n\",\n> +\t\t       __func__, clkspec->args[0], cc->nclks);\n>   \t\treturn ERR_PTR(-EINVAL);\n>   \t}\n>   \n> -\treturn clk_cc->div_clks[idx];\n> +\treturn &cc->clks[idx].hw;\n>   }\n>   \n> -#define SPMI_PMIC_DIV_CLK_SIZE\t\t0x100\n> -\n>   static const struct of_device_id spmi_pmic_clkdiv_match_table[] = {\n>   \t{\n>   \t\t.compatible = \"qcom,spmi-clkdiv\",\n> @@ -242,20 +219,21 @@ MODULE_DEVICE_TABLE(of, spmi_pmic_clkdiv_match_table);\n>   \n>   static int spmi_pmic_clkdiv_probe(struct platform_device *pdev)\n>   {\n> -\tstruct spmi_pmic_div_clk_cc *clk_cc;\n> +\tstruct spmi_pmic_div_clk_cc *cc;\n>   \tstruct clk_init_data init = {};\n>   \tstruct clkdiv *clkdiv;\n>   \tstruct clk *cxo;\n>   \tstruct regmap *regmap;\n>   \tstruct device *dev = &pdev->dev;\n> +\tstruct device_node *of_node = dev->of_node;\n>   \tconst char *parent_name;\n> -\tint nclks, i, rc, cxo_hz;\n> +\tint nclks, i, ret, cxo_hz;\n>   \tu32 start;\n>   \n> -\trc = of_property_read_u32(dev->of_node, \"reg\", &start);\n> -\tif (rc < 0) {\n> +\tret = of_property_read_u32(of_node, \"reg\", &start);\n> +\tif (ret < 0) {\n>   \t\tdev_err(dev, \"reg property reading failed\\n\");\n> -\t\treturn rc;\n> +\t\treturn ret;\n>   \t}\n>   \n>   \tregmap = dev_get_regmap(dev->parent, NULL);\n> @@ -264,62 +242,51 @@ static int spmi_pmic_clkdiv_probe(struct platform_device *pdev)\n>   \t\treturn -EINVAL;\n>   \t}\n>   \n> -\tnclks = (uintptr_t)of_match_node(spmi_pmic_clkdiv_match_table,\n> -\t\t\t\t\t dev->of_node)->data;\n> -\n> -\tclkdiv = devm_kcalloc(dev, nclks, sizeof(*clkdiv), GFP_KERNEL);\n> -\tif (!clkdiv)\n> -\t\treturn -ENOMEM;\n> -\n> -\tclk_cc = devm_kzalloc(&pdev->dev, sizeof(*clk_cc), GFP_KERNEL);\n> -\tif (!clk_cc)\n> -\t\treturn -ENOMEM;\n> +\tnclks = (uintptr_t)of_device_get_match_data(dev);\n> +\tif (!nclks)\n> +\t\treturn -EINVAL;\n>   \n> -\tclk_cc->div_clks = devm_kcalloc(&pdev->dev, nclks,\n> -\t\t\t\t\tsizeof(*clk_cc->div_clks), GFP_KERNEL);\n> -\tif (!clk_cc->div_clks)\n> +\tcc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*cc->clks) * nclks,\n> +\t\t\t  GFP_KERNEL);\n> +\tif (!cc)\n>   \t\treturn -ENOMEM;\n> +\tcc->nclks = nclks;\n>   \n>   \tcxo = clk_get(dev, \"xo\");\n>   \tif (IS_ERR(cxo)) {\n> -\t\trc = PTR_ERR(cxo);\n> -\t\tif (rc != -EPROBE_DEFER)\n> -\t\t\tdev_err(dev, \"failed to get xo clock\");\n> -\t\treturn rc;\n> +\t\tret = PTR_ERR(cxo);\n> +\t\tif (ret != -EPROBE_DEFER)\n> +\t\t\tdev_err(dev, \"failed to get xo clock\\n\");\n> +\t\treturn ret;\n>   \t}\n>   \tcxo_hz = clk_get_rate(cxo);\n>   \tclk_put(cxo);\n>   \n> -\tparent_name = of_clk_get_parent_name(dev->of_node, 0);\n> +\tparent_name = of_clk_get_parent_name(of_node, 0);\n>   \tif (!parent_name) {\n>   \t\tdev_err(dev, \"missing parent clock\\n\");\n>   \t\treturn -ENODEV;\n>   \t}\n>   \n>   \tinit.parent_names = &parent_name;\n> -\tinit.num_parents = parent_name ? 1 : 0;\n> +\tinit.num_parents = 1;\n>   \tinit.ops = &clk_spmi_pmic_div_ops;\n> -\tinit.flags = 0;\n>   \n> -\tfor (i = 0; i < nclks; i++) {\n> +\tfor (i = 0, clkdiv = cc->clks; i < nclks; i++) {\n>   \t\tspin_lock_init(&clkdiv[i].lock);\n> -\t\tclkdiv[i].base = start + i * SPMI_PMIC_DIV_CLK_SIZE;\n> +\t\tclkdiv[i].base = start + i * 0x100;\n>   \t\tclkdiv[i].regmap = regmap;\n>   \t\tclkdiv[i].cxo_period_ns = NSEC_PER_SEC / cxo_hz;\n>   \t\tinit.name = kasprintf(GFP_KERNEL, \"div_clk%d\", i + 1);\n>   \t\tclkdiv[i].hw.init = &init;\n> -\t\trc = devm_clk_hw_register(dev, &clkdiv[i].hw);\n> -\t\tkfree(init.name); /* clock framework made a copy of the name */\n> -\t\tif (rc)\n> -\t\t\treturn rc;\n>   \n> -\t\tclk_cc->div_clks[i] = &clkdiv[i].hw;\n> +\t\tret = devm_clk_hw_register(dev, &clkdiv[i].hw);\n> +\t\tkfree(init.name); /* clk framework made a copy */\n> +\t\tif (ret)\n> +\t\t\treturn ret;\n>   \t}\n>   \n> -\tclk_cc->nclks = nclks;\n> -\trc = of_clk_add_hw_provider(pdev->dev.of_node, spmi_pmic_div_clk_hw_get,\n> -\t\t\t\t    clk_cc);\n> -\treturn rc;\n> +\treturn of_clk_add_hw_provider(of_node, spmi_pmic_div_clk_hw_get, cc);\n>   }\n>   \n>   static int spmi_pmic_clkdiv_remove(struct platform_device *pdev)\n>\n>\n\n--\nTo unsubscribe from this list: send the line \"unsubscribe devicetree\" in\nthe body of a message to majordomo@vger.kernel.org\nMore majordomo info at  http://vger.kernel.org/majordomo-info.html","headers":{"Return-Path":"<devicetree-owner@vger.kernel.org>","X-Original-To":"incoming-dt@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-dt@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=devicetree-owner@vger.kernel.org; receiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=codeaurora.org header.i=@codeaurora.org\n\theader.b=\"C+BLV22x\"; \n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n\theader.d=codeaurora.org header.i=@codeaurora.org header.b=\"kSy6cGIe\"; \n\tdkim-atps=neutral","pdx-caf-mail.web.codeaurora.org;\n\tdmarc=none (p=none dis=none) header.from=codeaurora.org","pdx-caf-mail.web.codeaurora.org;\n\tspf=none smtp.mailfrom=tirupath@codeaurora.org"],"Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3ydYYK25cWz9s71\n\tfor <incoming-dt@patchwork.ozlabs.org>;\n\tFri, 17 Nov 2017 21:01:41 +1100 (AEDT)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1752509AbdKQKBj (ORCPT\n\t<rfc822;incoming-dt@patchwork.ozlabs.org>);\n\tFri, 17 Nov 2017 05:01:39 -0500","from smtp.codeaurora.org ([198.145.29.96]:35706 \"EHLO\n\tsmtp.codeaurora.org\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751617AbdKQKBW (ORCPT\n\t<rfc822; devicetree@vger.kernel.org>); Fri, 17 Nov 2017 05:01:22 -0500","by smtp.codeaurora.org (Postfix, from userid 1000)\n\tid 3D7D4607DC; Fri, 17 Nov 2017 10:01:22 +0000 (UTC)","from [10.206.28.43]\n\t(blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com\n\t[103.229.19.19])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128\n\tbits)) (No client certificate requested)\n\t(Authenticated sender: tirupath@smtp.codeaurora.org)\n\tby smtp.codeaurora.org (Postfix) with ESMTPSA id 9D51160584;\n\tFri, 17 Nov 2017 10:01:16 +0000 (UTC)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org;\n\ts=default; t=1510912882;\n\tbh=CZweoKzx2P8LiKBGrSO9OjlkujSc83WHpIOoeCqNFS4=;\n\th=Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=C+BLV22x3du85irVRn2XQLa18sHFidxRLlDiP5f2gkuXxfdXtJxbt8ypdDYAN2t9v\n\tQUVNZYNc2PjaWCtOFVZHP9dCLSFnY4Bfm6TY1tdDshD/IhGVquck2Yf/mrSWjVDajV\n\tFuJh2xkRFge50utgBmcl/CrIs8DsKEFCFG9c7H8c=","v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org;\n\ts=default; t=1510912880;\n\tbh=CZweoKzx2P8LiKBGrSO9OjlkujSc83WHpIOoeCqNFS4=;\n\th=Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=kSy6cGIey3WDoMJraMj7g0sjuQLZ79kfqE2CfRiArDVOxmDJRahvKk7eBOJiCGxZr\n\tyLI214+MPMa4YUMQZ5WWIJkCdhrtl23NHqvtbtzEMC3nhNi5OMz5qYGo56EztsS+ES\n\te9CU7GraJjY5nnNK5YeMy0DqAzfivckRwFCx811s="],"X-Spam-Checker-Version":"SpamAssassin 3.4.0 (2014-02-07) on\n\tpdx-caf-mail.web.codeaurora.org","X-Spam-Level":"","X-Spam-Status":"No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00,\n\tDKIM_SIGNED,\n\tT_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0","DMARC-Filter":"OpenDMARC Filter v1.3.2 smtp.codeaurora.org 9D51160584","Subject":"Re: [PATCH V5] clk: qcom: Add spmi_pmic clock divider support","To":"Stephen Boyd <sboyd@codeaurora.org>","Cc":"mturquette@baylibre.com, robh+dt@kernel.org, mark.rutland@arm.com,\n\tandy.gross@linaro.org, david.brown@linaro.org,\n\tlinux-clk@vger.kernel.org, devicetree@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,\n\tlinux-soc@vger.kernel.org","References":"<1505817286-12445-1-git-send-email-tirupath@codeaurora.org>\n\t<20171115170647.GR11955@codeaurora.org>","From":"Tirupathi Reddy T <tirupath@codeaurora.org>","Message-ID":"<86711b65-52a8-d96a-1039-3e5fc52a027f@codeaurora.org>","Date":"Fri, 17 Nov 2017 15:31:13 +0530","User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101\n\tThunderbird/52.4.0","MIME-Version":"1.0","In-Reply-To":"<20171115170647.GR11955@codeaurora.org>","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Transfer-Encoding":"7bit","Content-Language":"en-US","Sender":"devicetree-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<devicetree.vger.kernel.org>","X-Mailing-List":"devicetree@vger.kernel.org"}}]