All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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.