From: Stephen Boyd <sboyd@codeaurora.org>
To: gabriel.fernandez@st.com
Cc: Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Russell King <linux@armlinux.org.uk>,
Maxime Coquelin <mcoquelin.stm32@gmail.com>,
Alexandre Torgue <alexandre.torgue@st.com>,
Michael Turquette <mturquette@baylibre.com>,
Nicolas Pitre <nico@linaro.org>, Arnd Bergmann <arnd@arndb.de>,
daniel.thompson@linaro.org, andrea.merello@gmail.com,
radoslaw.pietrzyk@gmail.com, Lee Jones <lee.jones@linaro.org>,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org,
ludovic.barre@st.com, olivier.bideau@st.com,
amelie.delaunay@st.com
Subject: Re: [PATCH] clk: stm32h7: Add stm32h743 clock driver
Date: Wed, 5 Apr 2017 15:32:33 -0700 [thread overview]
Message-ID: <20170405223233.GJ7065@codeaurora.org> (raw)
In-Reply-To: <1489569810-24350-1-git-send-email-gabriel.fernandez@st.com>
On 03/15, gabriel.fernandez@st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>
> This patch enables clocks for STM32H743 boards.
Like what clocks exactly? All of them?
> diff --git a/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
> new file mode 100644
> index 0000000..9d4b587
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
> @@ -0,0 +1,152 @@
> +STMicroelectronics STM32H7 Reset and Clock Controller
> +=====================================================
> +
> +The RCC IP is both a reset and a clock controller.
> +
> +Please refer to clock-bindings.txt for common clock controller binding usage.
> +Please also refer to reset.txt for common reset controller binding usage.
> +
> +Required properties:
> +- compatible: Should be:
> + "st,stm32h743-rcc"
> +
> +- reg: should be register base and length as documented in the
> + datasheet
> +
> +- #reset-cells: 1, see below
> +
> +- #clock-cells : from common clock binding; shall be set to 1
> +
> +- clocks: External oscillator clock phandle
> + - high speed external clock signal (HSE)
> + - low speed external clock signal (LSE)
> + - external I2S clock (I2S_CKIN)
> +
> +- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
> + write protection (RTC clock).
> +
> +- pll x node: Allow to register a pll with specific parameters.
> + Please see PLL section below.
> +
> +Example:
> +
> + rcc: rcc@58024400 {
> + #reset-cells = <1>;
> + #clock-cells = <2>
> + compatible = "st,stm32h743-rcc", "st,stm32-rcc";
> + reg = <0x58024400 0x400>;
> + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>;
> +
> + st,syscfg = <&pwrcfg>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + vco1@58024430 {
> + #clock-cells = <0>;
> + compatible = "stm32,pll";
> + reg = <0>;
reg is super confusing and doesn't match unit address.
> + };
Why? Shouldn't we know this from the compatible string how many
PLLs there are and where they're located? Export the PLLs through
rcc node's clock-cells?
> +
> + vco2@58024438 {
> + #clock-cells = <0>;
> + compatible = "stm32,pll";
> + reg = <1>;
reg is super confusing and doesn't match unit address.
> + st,clock-div = <2>;
> + st,clock-mult = <40>;
> + st,frac-status = <0>;
> + st,frac = <0>;
> + st,vcosel = <1>;
> + st,pllrge = <2>;
Does this stuff change on a per-board basis? I hope none of these
properties need to be in DT.
> + };
> + };
> +
> +
> +STM32H7 PLL
> +-----------
> +
[...]
> +
> +Specifying softreset control of devices
> +=======================================
> +
> +Device nodes should specify the reset channel required in their "resets"
> +property, containing a phandle to the reset device node and an index specifying
> +which channel to use.
> +The index is the bit number within the RCC registers bank, starting from RCC
> +base address.
> +It is calculated as: index = register_offset / 4 * 32 + bit_offset.
> +Where bit_offset is the bit offset within the register.
> +
> +For example, for CRC reset:
> + crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107
> +
> +All available preprocessor macros for reset are defined dt-bindings//mfd/stm32h7-rcc.h
One too many slashes?
> +header and can be used in device tree sources.
> +
> +example:
> +
> + timer2 {
> + resets = <&rcc STM32H7_APB1L_RESET(TIM2)>;
> + };
> diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c
> new file mode 100644
> index 0000000..c8eb729
> --- /dev/null
> +++ b/drivers/clk/clk-stm32h7.c
> @@ -0,0 +1,1586 @@
> +/*
> + * Copyright (C) Gabriel Fernandez 2017
> + * Author: Gabriel Fernandez <gabriel.fernandez@st.com>
> + *
> + * License terms: GPL V2.0.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
Is this used?
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/clock/stm32h7-clks.h>
> +
> +/* Reset Clock Control Registers */
> +#define RCC_CR 0x00
> +#define RCC_CFGR 0x10
> +#define RCC_D1CFGR 0x18
> +#define RCC_D2CFGR 0x1C
> +#define RCC_D3CFGR 0x20
> +#define RCC_PLLCKSELR 0x28
> +#define RCC_PLLCFGR 0x2C
> +#define RCC_PLL1DIVR 0x30
> +#define RCC_PLL1FRACR 0x34
> +#define RCC_PLL2DIVR 0x38
> +#define RCC_PLL2FRACR 0x3C
> +#define RCC_PLL3DIVR 0x40
> +#define RCC_PLL3FRACR 0x44
> +#define RCC_D1CCIPR 0x4C
> +#define RCC_D2CCIP1R 0x50
> +#define RCC_D2CCIP2R 0x54
> +#define RCC_D3CCIPR 0x58
> +#define RCC_BDCR 0x70
> +#define RCC_CSR 0x74
> +#define RCC_AHB3ENR 0xD4
> +#define RCC_AHB1ENR 0xD8
> +#define RCC_AHB2ENR 0xDC
> +#define RCC_AHB4ENR 0xE0
> +#define RCC_APB3ENR 0xE4
> +#define RCC_APB1LENR 0xE8
> +#define RCC_APB1HENR 0xEC
> +#define RCC_APB2ENR 0xF0
> +#define RCC_APB4ENR 0xF4
> +
> +static DEFINE_SPINLOCK(rlock);
This is super generic and will make lockdep debugging sad.
Perhaps stm32rcc_lock?
> +
> +static void __iomem *base;
> +static struct regmap *pdrm;
> +static struct clk_hw **hws;
> +
> +/* System clock parent */
> +static const char * const sys_src[] = {
> + "hsi_ck", "csi_ck", "hse_ck", "pll1_p" };
> +
> +static const char * const tracein_src[] = {
> + "hsi_ck", "csi_ck", "hse_ck", "pll1_r" };
[...]
> +
> +static unsigned long pll_fd_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct stm32_pll_obj *clk_elem = to_pll(hw);
> + struct stm32_fractional_divider *fd = &clk_elem->div;
> + unsigned long m, n;
> + u32 val, mask;
> + u64 rate, rate1 = 0;
> +
> + val = clk_readl(fd->mreg);
Please don't use clk_readl() unless you need it for some reason.
> + mask = (GENMASK(fd->mwidth - 1, 0) << fd->mshift);
> + m = (val & mask) >> fd->mshift;
> +
> + val = clk_readl(fd->nreg);
> + mask = (GENMASK(fd->nwidth - 1, 0) << fd->nshift);
Useless parentheses. And isn't GENMASK supposed to take the
actual bit positions? Then we avoid overflow issues?
> + n = ((val & mask) >> fd->nshift) + 1;
> +
> + if (!n || !m)
> + return parent_rate;
> +
> + rate = (u64)parent_rate * n;
> + do_div(rate, m);
> +
> + if (pll_frac_is_enabled(hw)) {
> + val = pll_read_frac(hw);
> + rate1 = (u64) parent_rate * (u64) val;
> + do_div(rate1, (m * 8191));
> + }
> +
> + return rate + rate1;
> +}
> +
[...]
> +
> + /* Micro-controller clocks */
> + for (n = 0; n < ARRAY_SIZE(mco_clk); n++) {
> + get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg,
> + &rlock);
> +
> + hws[MCO_BANK + n] = clk_hw_register_composite(NULL,
> + mco_clk[n].name,
> + mco_clk[n].parent_name,
> + mco_clk[n].num_parents,
> + c_cfg.mux_hw, c_cfg.mux_ops,
> + c_cfg.div_hw, c_cfg.div_ops,
> + c_cfg.gate_hw, c_cfg.gate_ops,
> + mco_clk[n].flags);
> + }
> +
> + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
> +
> + return;
> +
> +err_free_clks:
> + kfree(clk_data);
> +}
> +CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init);
Is there another driver that uses the same register space?
Nothing showing up in -next right now. Perhaps a comment should
be added to indicate the other driver.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
WARNING: multiple messages have this Message-ID (diff)
From: sboyd@codeaurora.org (Stephen Boyd)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] clk: stm32h7: Add stm32h743 clock driver
Date: Wed, 5 Apr 2017 15:32:33 -0700 [thread overview]
Message-ID: <20170405223233.GJ7065@codeaurora.org> (raw)
In-Reply-To: <1489569810-24350-1-git-send-email-gabriel.fernandez@st.com>
On 03/15, gabriel.fernandez at st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>
> This patch enables clocks for STM32H743 boards.
Like what clocks exactly? All of them?
> diff --git a/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
> new file mode 100644
> index 0000000..9d4b587
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
> @@ -0,0 +1,152 @@
> +STMicroelectronics STM32H7 Reset and Clock Controller
> +=====================================================
> +
> +The RCC IP is both a reset and a clock controller.
> +
> +Please refer to clock-bindings.txt for common clock controller binding usage.
> +Please also refer to reset.txt for common reset controller binding usage.
> +
> +Required properties:
> +- compatible: Should be:
> + "st,stm32h743-rcc"
> +
> +- reg: should be register base and length as documented in the
> + datasheet
> +
> +- #reset-cells: 1, see below
> +
> +- #clock-cells : from common clock binding; shall be set to 1
> +
> +- clocks: External oscillator clock phandle
> + - high speed external clock signal (HSE)
> + - low speed external clock signal (LSE)
> + - external I2S clock (I2S_CKIN)
> +
> +- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
> + write protection (RTC clock).
> +
> +- pll x node: Allow to register a pll with specific parameters.
> + Please see PLL section below.
> +
> +Example:
> +
> + rcc: rcc at 58024400 {
> + #reset-cells = <1>;
> + #clock-cells = <2>
> + compatible = "st,stm32h743-rcc", "st,stm32-rcc";
> + reg = <0x58024400 0x400>;
> + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>;
> +
> + st,syscfg = <&pwrcfg>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + vco1 at 58024430 {
> + #clock-cells = <0>;
> + compatible = "stm32,pll";
> + reg = <0>;
reg is super confusing and doesn't match unit address.
> + };
Why? Shouldn't we know this from the compatible string how many
PLLs there are and where they're located? Export the PLLs through
rcc node's clock-cells?
> +
> + vco2 at 58024438 {
> + #clock-cells = <0>;
> + compatible = "stm32,pll";
> + reg = <1>;
reg is super confusing and doesn't match unit address.
> + st,clock-div = <2>;
> + st,clock-mult = <40>;
> + st,frac-status = <0>;
> + st,frac = <0>;
> + st,vcosel = <1>;
> + st,pllrge = <2>;
Does this stuff change on a per-board basis? I hope none of these
properties need to be in DT.
> + };
> + };
> +
> +
> +STM32H7 PLL
> +-----------
> +
[...]
> +
> +Specifying softreset control of devices
> +=======================================
> +
> +Device nodes should specify the reset channel required in their "resets"
> +property, containing a phandle to the reset device node and an index specifying
> +which channel to use.
> +The index is the bit number within the RCC registers bank, starting from RCC
> +base address.
> +It is calculated as: index = register_offset / 4 * 32 + bit_offset.
> +Where bit_offset is the bit offset within the register.
> +
> +For example, for CRC reset:
> + crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107
> +
> +All available preprocessor macros for reset are defined dt-bindings//mfd/stm32h7-rcc.h
One too many slashes?
> +header and can be used in device tree sources.
> +
> +example:
> +
> + timer2 {
> + resets = <&rcc STM32H7_APB1L_RESET(TIM2)>;
> + };
> diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c
> new file mode 100644
> index 0000000..c8eb729
> --- /dev/null
> +++ b/drivers/clk/clk-stm32h7.c
> @@ -0,0 +1,1586 @@
> +/*
> + * Copyright (C) Gabriel Fernandez 2017
> + * Author: Gabriel Fernandez <gabriel.fernandez@st.com>
> + *
> + * License terms: GPL V2.0.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
Is this used?
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/clock/stm32h7-clks.h>
> +
> +/* Reset Clock Control Registers */
> +#define RCC_CR 0x00
> +#define RCC_CFGR 0x10
> +#define RCC_D1CFGR 0x18
> +#define RCC_D2CFGR 0x1C
> +#define RCC_D3CFGR 0x20
> +#define RCC_PLLCKSELR 0x28
> +#define RCC_PLLCFGR 0x2C
> +#define RCC_PLL1DIVR 0x30
> +#define RCC_PLL1FRACR 0x34
> +#define RCC_PLL2DIVR 0x38
> +#define RCC_PLL2FRACR 0x3C
> +#define RCC_PLL3DIVR 0x40
> +#define RCC_PLL3FRACR 0x44
> +#define RCC_D1CCIPR 0x4C
> +#define RCC_D2CCIP1R 0x50
> +#define RCC_D2CCIP2R 0x54
> +#define RCC_D3CCIPR 0x58
> +#define RCC_BDCR 0x70
> +#define RCC_CSR 0x74
> +#define RCC_AHB3ENR 0xD4
> +#define RCC_AHB1ENR 0xD8
> +#define RCC_AHB2ENR 0xDC
> +#define RCC_AHB4ENR 0xE0
> +#define RCC_APB3ENR 0xE4
> +#define RCC_APB1LENR 0xE8
> +#define RCC_APB1HENR 0xEC
> +#define RCC_APB2ENR 0xF0
> +#define RCC_APB4ENR 0xF4
> +
> +static DEFINE_SPINLOCK(rlock);
This is super generic and will make lockdep debugging sad.
Perhaps stm32rcc_lock?
> +
> +static void __iomem *base;
> +static struct regmap *pdrm;
> +static struct clk_hw **hws;
> +
> +/* System clock parent */
> +static const char * const sys_src[] = {
> + "hsi_ck", "csi_ck", "hse_ck", "pll1_p" };
> +
> +static const char * const tracein_src[] = {
> + "hsi_ck", "csi_ck", "hse_ck", "pll1_r" };
[...]
> +
> +static unsigned long pll_fd_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct stm32_pll_obj *clk_elem = to_pll(hw);
> + struct stm32_fractional_divider *fd = &clk_elem->div;
> + unsigned long m, n;
> + u32 val, mask;
> + u64 rate, rate1 = 0;
> +
> + val = clk_readl(fd->mreg);
Please don't use clk_readl() unless you need it for some reason.
> + mask = (GENMASK(fd->mwidth - 1, 0) << fd->mshift);
> + m = (val & mask) >> fd->mshift;
> +
> + val = clk_readl(fd->nreg);
> + mask = (GENMASK(fd->nwidth - 1, 0) << fd->nshift);
Useless parentheses. And isn't GENMASK supposed to take the
actual bit positions? Then we avoid overflow issues?
> + n = ((val & mask) >> fd->nshift) + 1;
> +
> + if (!n || !m)
> + return parent_rate;
> +
> + rate = (u64)parent_rate * n;
> + do_div(rate, m);
> +
> + if (pll_frac_is_enabled(hw)) {
> + val = pll_read_frac(hw);
> + rate1 = (u64) parent_rate * (u64) val;
> + do_div(rate1, (m * 8191));
> + }
> +
> + return rate + rate1;
> +}
> +
[...]
> +
> + /* Micro-controller clocks */
> + for (n = 0; n < ARRAY_SIZE(mco_clk); n++) {
> + get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg,
> + &rlock);
> +
> + hws[MCO_BANK + n] = clk_hw_register_composite(NULL,
> + mco_clk[n].name,
> + mco_clk[n].parent_name,
> + mco_clk[n].num_parents,
> + c_cfg.mux_hw, c_cfg.mux_ops,
> + c_cfg.div_hw, c_cfg.div_ops,
> + c_cfg.gate_hw, c_cfg.gate_ops,
> + mco_clk[n].flags);
> + }
> +
> + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
> +
> + return;
> +
> +err_free_clks:
> + kfree(clk_data);
> +}
> +CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init);
Is there another driver that uses the same register space?
Nothing showing up in -next right now. Perhaps a comment should
be added to indicate the other driver.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
WARNING: multiple messages have this Message-ID (diff)
From: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
To: gabriel.fernandez-qxv4g6HH51o@public.gmane.org
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>,
Maxime Coquelin
<mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Alexandre Torgue <alexandre.torgue-qxv4g6HH51o@public.gmane.org>,
Michael Turquette
<mturquette-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>,
Nicolas Pitre <nico-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
daniel.thompson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
andrea.merello-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
radoslaw.pietrzyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
ludovic.barre-qxv4g6HH51o@public.gmane.org,
olivier.bideau-qxv4g6HH51o@public.gmane.org,
amelie.delaunay-qxv4g6HH51o@public.gmane.org
Subject: Re: [PATCH] clk: stm32h7: Add stm32h743 clock driver
Date: Wed, 5 Apr 2017 15:32:33 -0700 [thread overview]
Message-ID: <20170405223233.GJ7065@codeaurora.org> (raw)
In-Reply-To: <1489569810-24350-1-git-send-email-gabriel.fernandez-qxv4g6HH51o@public.gmane.org>
On 03/15, gabriel.fernandez-qxv4g6HH51o@public.gmane.org wrote:
> From: Gabriel Fernandez <gabriel.fernandez-qxv4g6HH51o@public.gmane.org>
>
> This patch enables clocks for STM32H743 boards.
Like what clocks exactly? All of them?
> diff --git a/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
> new file mode 100644
> index 0000000..9d4b587
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
> @@ -0,0 +1,152 @@
> +STMicroelectronics STM32H7 Reset and Clock Controller
> +=====================================================
> +
> +The RCC IP is both a reset and a clock controller.
> +
> +Please refer to clock-bindings.txt for common clock controller binding usage.
> +Please also refer to reset.txt for common reset controller binding usage.
> +
> +Required properties:
> +- compatible: Should be:
> + "st,stm32h743-rcc"
> +
> +- reg: should be register base and length as documented in the
> + datasheet
> +
> +- #reset-cells: 1, see below
> +
> +- #clock-cells : from common clock binding; shall be set to 1
> +
> +- clocks: External oscillator clock phandle
> + - high speed external clock signal (HSE)
> + - low speed external clock signal (LSE)
> + - external I2S clock (I2S_CKIN)
> +
> +- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
> + write protection (RTC clock).
> +
> +- pll x node: Allow to register a pll with specific parameters.
> + Please see PLL section below.
> +
> +Example:
> +
> + rcc: rcc@58024400 {
> + #reset-cells = <1>;
> + #clock-cells = <2>
> + compatible = "st,stm32h743-rcc", "st,stm32-rcc";
> + reg = <0x58024400 0x400>;
> + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>;
> +
> + st,syscfg = <&pwrcfg>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + vco1@58024430 {
> + #clock-cells = <0>;
> + compatible = "stm32,pll";
> + reg = <0>;
reg is super confusing and doesn't match unit address.
> + };
Why? Shouldn't we know this from the compatible string how many
PLLs there are and where they're located? Export the PLLs through
rcc node's clock-cells?
> +
> + vco2@58024438 {
> + #clock-cells = <0>;
> + compatible = "stm32,pll";
> + reg = <1>;
reg is super confusing and doesn't match unit address.
> + st,clock-div = <2>;
> + st,clock-mult = <40>;
> + st,frac-status = <0>;
> + st,frac = <0>;
> + st,vcosel = <1>;
> + st,pllrge = <2>;
Does this stuff change on a per-board basis? I hope none of these
properties need to be in DT.
> + };
> + };
> +
> +
> +STM32H7 PLL
> +-----------
> +
[...]
> +
> +Specifying softreset control of devices
> +=======================================
> +
> +Device nodes should specify the reset channel required in their "resets"
> +property, containing a phandle to the reset device node and an index specifying
> +which channel to use.
> +The index is the bit number within the RCC registers bank, starting from RCC
> +base address.
> +It is calculated as: index = register_offset / 4 * 32 + bit_offset.
> +Where bit_offset is the bit offset within the register.
> +
> +For example, for CRC reset:
> + crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107
> +
> +All available preprocessor macros for reset are defined dt-bindings//mfd/stm32h7-rcc.h
One too many slashes?
> +header and can be used in device tree sources.
> +
> +example:
> +
> + timer2 {
> + resets = <&rcc STM32H7_APB1L_RESET(TIM2)>;
> + };
> diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c
> new file mode 100644
> index 0000000..c8eb729
> --- /dev/null
> +++ b/drivers/clk/clk-stm32h7.c
> @@ -0,0 +1,1586 @@
> +/*
> + * Copyright (C) Gabriel Fernandez 2017
> + * Author: Gabriel Fernandez <gabriel.fernandez-qxv4g6HH51o@public.gmane.org>
> + *
> + * License terms: GPL V2.0.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
Is this used?
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/clock/stm32h7-clks.h>
> +
> +/* Reset Clock Control Registers */
> +#define RCC_CR 0x00
> +#define RCC_CFGR 0x10
> +#define RCC_D1CFGR 0x18
> +#define RCC_D2CFGR 0x1C
> +#define RCC_D3CFGR 0x20
> +#define RCC_PLLCKSELR 0x28
> +#define RCC_PLLCFGR 0x2C
> +#define RCC_PLL1DIVR 0x30
> +#define RCC_PLL1FRACR 0x34
> +#define RCC_PLL2DIVR 0x38
> +#define RCC_PLL2FRACR 0x3C
> +#define RCC_PLL3DIVR 0x40
> +#define RCC_PLL3FRACR 0x44
> +#define RCC_D1CCIPR 0x4C
> +#define RCC_D2CCIP1R 0x50
> +#define RCC_D2CCIP2R 0x54
> +#define RCC_D3CCIPR 0x58
> +#define RCC_BDCR 0x70
> +#define RCC_CSR 0x74
> +#define RCC_AHB3ENR 0xD4
> +#define RCC_AHB1ENR 0xD8
> +#define RCC_AHB2ENR 0xDC
> +#define RCC_AHB4ENR 0xE0
> +#define RCC_APB3ENR 0xE4
> +#define RCC_APB1LENR 0xE8
> +#define RCC_APB1HENR 0xEC
> +#define RCC_APB2ENR 0xF0
> +#define RCC_APB4ENR 0xF4
> +
> +static DEFINE_SPINLOCK(rlock);
This is super generic and will make lockdep debugging sad.
Perhaps stm32rcc_lock?
> +
> +static void __iomem *base;
> +static struct regmap *pdrm;
> +static struct clk_hw **hws;
> +
> +/* System clock parent */
> +static const char * const sys_src[] = {
> + "hsi_ck", "csi_ck", "hse_ck", "pll1_p" };
> +
> +static const char * const tracein_src[] = {
> + "hsi_ck", "csi_ck", "hse_ck", "pll1_r" };
[...]
> +
> +static unsigned long pll_fd_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct stm32_pll_obj *clk_elem = to_pll(hw);
> + struct stm32_fractional_divider *fd = &clk_elem->div;
> + unsigned long m, n;
> + u32 val, mask;
> + u64 rate, rate1 = 0;
> +
> + val = clk_readl(fd->mreg);
Please don't use clk_readl() unless you need it for some reason.
> + mask = (GENMASK(fd->mwidth - 1, 0) << fd->mshift);
> + m = (val & mask) >> fd->mshift;
> +
> + val = clk_readl(fd->nreg);
> + mask = (GENMASK(fd->nwidth - 1, 0) << fd->nshift);
Useless parentheses. And isn't GENMASK supposed to take the
actual bit positions? Then we avoid overflow issues?
> + n = ((val & mask) >> fd->nshift) + 1;
> +
> + if (!n || !m)
> + return parent_rate;
> +
> + rate = (u64)parent_rate * n;
> + do_div(rate, m);
> +
> + if (pll_frac_is_enabled(hw)) {
> + val = pll_read_frac(hw);
> + rate1 = (u64) parent_rate * (u64) val;
> + do_div(rate1, (m * 8191));
> + }
> +
> + return rate + rate1;
> +}
> +
[...]
> +
> + /* Micro-controller clocks */
> + for (n = 0; n < ARRAY_SIZE(mco_clk); n++) {
> + get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg,
> + &rlock);
> +
> + hws[MCO_BANK + n] = clk_hw_register_composite(NULL,
> + mco_clk[n].name,
> + mco_clk[n].parent_name,
> + mco_clk[n].num_parents,
> + c_cfg.mux_hw, c_cfg.mux_ops,
> + c_cfg.div_hw, c_cfg.div_ops,
> + c_cfg.gate_hw, c_cfg.gate_ops,
> + mco_clk[n].flags);
> + }
> +
> + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
> +
> + return;
> +
> +err_free_clks:
> + kfree(clk_data);
> +}
> +CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init);
Is there another driver that uses the same register space?
Nothing showing up in -next right now. Perhaps a comment should
be added to indicate the other driver.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2017-04-05 22:32 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-15 9:23 [PATCH] clk: stm32h7: Add stm32h743 clock driver gabriel.fernandez
2017-03-15 9:23 ` gabriel.fernandez
2017-03-15 9:23 ` gabriel.fernandez at st.com
2017-03-15 12:15 ` Lee Jones
2017-03-15 12:15 ` Lee Jones
2017-03-15 12:15 ` Lee Jones
2017-03-24 2:06 ` Rob Herring
2017-03-24 2:06 ` Rob Herring
2017-03-24 2:06 ` Rob Herring
2017-03-24 9:41 ` Gabriel Fernandez
2017-03-24 9:41 ` Gabriel Fernandez
2017-03-24 9:41 ` Gabriel Fernandez
2017-03-27 19:04 ` Rob Herring
2017-03-27 19:04 ` Rob Herring
2017-03-27 19:04 ` Rob Herring
2017-03-28 6:20 ` Gabriel Fernandez
2017-03-28 6:20 ` Gabriel Fernandez
2017-03-28 6:20 ` Gabriel Fernandez
2017-03-28 15:19 ` Rob Herring
2017-03-28 15:19 ` Rob Herring
2017-03-28 15:19 ` Rob Herring
2017-04-05 22:32 ` Stephen Boyd [this message]
2017-04-05 22:32 ` Stephen Boyd
2017-04-05 22:32 ` Stephen Boyd
2017-04-06 9:35 ` Gabriel Fernandez
2017-04-06 9:35 ` Gabriel Fernandez
2017-04-06 9:35 ` Gabriel Fernandez
2017-04-07 19:51 ` Stephen Boyd
2017-04-07 19:51 ` Stephen Boyd
2017-04-07 19:51 ` Stephen Boyd
2017-04-28 14:56 ` Gabriel Fernandez
2017-04-28 14:56 ` Gabriel Fernandez
2017-04-28 14:56 ` Gabriel Fernandez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170405223233.GJ7065@codeaurora.org \
--to=sboyd@codeaurora.org \
--cc=alexandre.torgue@st.com \
--cc=amelie.delaunay@st.com \
--cc=andrea.merello@gmail.com \
--cc=arnd@arndb.de \
--cc=daniel.thompson@linaro.org \
--cc=devicetree@vger.kernel.org \
--cc=gabriel.fernandez@st.com \
--cc=lee.jones@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=ludovic.barre@st.com \
--cc=mark.rutland@arm.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=mturquette@baylibre.com \
--cc=nico@linaro.org \
--cc=olivier.bideau@st.com \
--cc=radoslaw.pietrzyk@gmail.com \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.