mbox series

[v5,00/44] ARM: davinci: convert to common clock framework​

Message ID 1515377863-20358-1-git-send-email-david@lechnology.com
Headers show
Series ARM: davinci: convert to common clock framework​ | expand

Message

David Lechner Jan. 8, 2018, 2:16 a.m. UTC
This series converts mach-davinci to use the common clock framework.

The series works like this, the first 21 patches create new clock drivers
using the common clock framework. There are basically 3 groups of clocks -
PLL, PSC and CFGCHIP (syscon). There are six different SoCs that each have
unique init data, which is the reason for so many patches.

Then, starting with "ARM: davinci: move davinci_clk_init() to init_time",
we get the mach code ready for the switch by adding the code needed for
the new clock drivers and adding #ifndef CONFIG_COMMON_CLK around the
legacy clocks so that we can switch easily between the old and the new.

"ARM: davinci: switch to common clock framework" actually flips the switch
to start using the new clock drivers. Then the next 8 patches remove all
of the old clock code.

The final three patches add device tree support to the one SoC that
supports it.

v5 changes:
- Basically, this is an entirely new series
- Patches are broken up into bite-sized pieces
- Converted PSC clock driver to use regmap
- Restored "force" flag for certain DA850 clocks
- Added device tree bindings
- Moved more of the clock init to drivers/clk
- Fixed frequency scaling (maybe*)

* I have frequency scaling using cpufreq-dt, so I know the clocks are doing
  what they need to do to make this work, but I haven't figured out how to
  test davinci-cpufreq driver yet. (Patches to make cpufreq-dt work will be
  sent separately after this series has landed.)

Dependencies:

This series applies on top of linux-davinci/master plus the following patches:
- [1] clk: fix reentrancy of clk_enable() on UP systems
- [2] clk: add helper functions for managing clk_onecell_data
- [3] clk: divider: fix clk_round_rate() when CLK_DIVIDER_READ_ONLY &&
	CLK_RATE_SET_PARENT
- [4] watchdog: davinci_wdt: add restart function
- [5] ARM: davinci: remove watchdog reset
- [6] USB: musb: da8xx: remove clock con_id
- [7] USB: ohci: da8xx: remove clk con_id
- [8] ARM: da8xx: remove con_id from USB clocks

You can find a working branch with everything included in the "common-clk-v5"
branch of https://github.com/dlech/ev3dev-kernel.git.

[1]: https://patchwork.kernel.org/patch/10145933/
[2]: https://patchwork.kernel.org/patch/10145873/
[3]: https://patchwork.kernel.org/patch/10147983/
[4]: https://patchwork.kernel.org/patch/10148097/
[5]: https://patchwork.kernel.org/patch/10148099/
[6]: https://patchwork.kernel.org/patch/10148111/
[7]: https://patchwork.kernel.org/patch/10148107/
[8]: https://patchwork.kernel.org/patch/10148109/


Testing/debugging for the uninitiated:

I only have one device to test with, which is based on da850, so I will
have to rely on others to do some testing here. Since we are dealing with
clocks, if something isn't working, you most likely won't see output on
the serial port. To figure out what is going on, you need to enable...

	CONFIG_DEBUG_LL=y
	CONFIG_EARLY_PRINTK=y

and add "earlyprintk clk_ignore_unused" to the kernel command line options.
You may need to select a different UART for this depending on your board. I
think UART1 is the default in the kernel configuration.

On da850 devices comment out the lines:

	else
		clk_set_parent(clk, parent->clk);

in da850.c or, if using device tree, comment out the lines:

	assigned-clocks = <&async3_clk>;
	assigned-clock-parents = <&pll1_sysclk 2>;

in da850.dtsi when doing earlyprintk, otherwise the UART1 and UART2 clock
source will change during boot and cause garbled output after a point. 


David Lechner (44):
  dt-bindings: clock: Add new bindings for TI Davinci PLL clocks
  clk: davinci: New driver for davinci PLL clocks
  clk: davinci: Add platform information for TI DA830 PLL
  clk: davinci: Add platform information for TI DA850 PLL
  clk: davinci: Add platform information for TI DM355 PLL
  clk: davinci: Add platform information for TI DM365 PLL
  clk: davinci: Add platform information for TI DM644x PLL
  clk: davinci: Add platform information for TI DM646x PLL
  dt-bindings: clock: New bindings for TI Davinci PSC
  clk: davinci: New driver for davinci PSC clocks
  clk: davinci: Add platform information for TI DA830 PSC
  clk: davinci: Add platform information for TI DA850 PSC
  clk: davinci: Add platform information for TI DM355 PSC
  clk: davinci: Add platform information for TI DM365 PSC
  clk: davinci: Add platform information for TI DM644x PSC
  clk: davinci: Add platform information for TI DM646x PSC
  dt-bindings: clock: Add bindings for DA8XX CFGCHIP gate clocks
  dt-bindings: clock: Add binding for TI DA8XX CFGCHIP mux clocks
  clk: davinci: New driver for TI DA8XX CFGCHIP clocks
  dt-bindings: clock: Add bindings for TI DA8XX USB PHY clocks
  clk: davinci: New driver for TI DA8XX USB PHY clocks
  ARM: davinci: move davinci_clk_init() to init_time
  ARM: da830: add new clock init using common clock framework
  ARM: da850: add new clock init using common clock framework
  ARM: dm355: add new clock init using common clock framework
  ARM: dm365: add new clock init using common clock framework
  ARM: dm644x: add new clock init using common clock framework
  ARM: dm646x: add new clock init using common clock framework
  ARM: da8xx: add new USB PHY clock init using common clock framework
  ARM: da8xx: add new sata_refclk init using common clock frmework
  ARM: davinci: remove CONFIG_DAVINCI_RESET_CLOCKS
  ARM: davinci_all_defconfig: remove CONFIG_DAVINCI_RESET_CLOCKS
  ARM: davinci: switch to common clock framework
  ARM: da830: Remove legacy clock init
  ARM: da850: Remove legacy clock init
  ARM: dm355: Remove legacy clock init
  ARM: dm365: Remove legacy clock init
  ARM: dm644x: Remove legacy clock init
  ARM: dm646x: Remove legacy clock init
  ARM: da8xx: Remove legacy clock init
  ARM: davinci: remove legacy clocks
  ARM: davinci: add device tree support to timer
  ARM: da8xx-dt: switch to device tree clocks
  ARM: dts: da850: Add clocks

 .../clock/ti/davinci/da8xx-cfgchip-gate.txt        |  38 ++
 .../clock/ti/davinci/da8xx-cfgchip-mux.txt         |  42 ++
 .../clock/ti/davinci/da8xx-cfgchip-usb-phy.txt     |  55 ++
 .../devicetree/bindings/clock/ti/davinci/pll.txt   |  47 ++
 .../devicetree/bindings/clock/ti/davinci/psc.txt   |  47 ++
 MAINTAINERS                                        |   6 +
 arch/arm/Kconfig                                   |   2 +-
 arch/arm/boot/dts/da850.dtsi                       | 167 +++++
 arch/arm/configs/davinci_all_defconfig             |   1 -
 arch/arm/mach-davinci/Kconfig                      |  13 +-
 arch/arm/mach-davinci/Makefile                     |   2 +-
 arch/arm/mach-davinci/board-da830-evm.c            |   2 +-
 arch/arm/mach-davinci/board-da850-evm.c            |   2 +-
 arch/arm/mach-davinci/board-dm355-evm.c            |   2 +-
 arch/arm/mach-davinci/board-dm355-leopard.c        |   2 +-
 arch/arm/mach-davinci/board-dm365-evm.c            |   2 +-
 arch/arm/mach-davinci/board-dm644x-evm.c           |   2 +-
 arch/arm/mach-davinci/board-dm646x-evm.c           |  19 +-
 arch/arm/mach-davinci/board-mityomapl138.c         |   2 +-
 arch/arm/mach-davinci/board-neuros-osd2.c          |   2 +-
 arch/arm/mach-davinci/board-omapl138-hawk.c        |   2 +-
 arch/arm/mach-davinci/board-sffsdr.c               |   2 +-
 arch/arm/mach-davinci/clock.c                      | 745 ---------------------
 arch/arm/mach-davinci/clock.h                      |  76 ---
 arch/arm/mach-davinci/common.c                     |   3 -
 arch/arm/mach-davinci/da830.c                      | 438 +-----------
 arch/arm/mach-davinci/da850.c                      | 689 ++-----------------
 arch/arm/mach-davinci/da8xx-dt.c                   |  61 +-
 arch/arm/mach-davinci/davinci.h                    |   8 +
 arch/arm/mach-davinci/devices-da8xx.c              |  43 +-
 arch/arm/mach-davinci/devices.c                    |   1 -
 arch/arm/mach-davinci/dm355.c                      | 390 +----------
 arch/arm/mach-davinci/dm365.c                      | 476 +------------
 arch/arm/mach-davinci/dm644x.c                     | 322 +--------
 arch/arm/mach-davinci/dm646x.c                     | 362 +---------
 arch/arm/mach-davinci/include/mach/clock.h         |   3 -
 arch/arm/mach-davinci/include/mach/common.h        |   9 -
 arch/arm/mach-davinci/include/mach/da8xx.h         |   3 +
 arch/arm/mach-davinci/psc.c                        | 137 ----
 arch/arm/mach-davinci/psc.h                        |  12 -
 arch/arm/mach-davinci/time.c                       |  19 +-
 arch/arm/mach-davinci/usb-da8xx.c                  | 262 ++------
 drivers/clk/Makefile                               |   1 +
 drivers/clk/davinci/Makefile                       |  22 +
 drivers/clk/davinci/da8xx-cfgchip.c                | 203 ++++++
 drivers/clk/davinci/da8xx-usb-phy-clk.c            | 425 ++++++++++++
 drivers/clk/davinci/pll-da830.c                    |  38 ++
 drivers/clk/davinci/pll-da850.c                    |  67 ++
 drivers/clk/davinci/pll-dm355.c                    |  40 ++
 drivers/clk/davinci/pll-dm365.c                    |  64 ++
 drivers/clk/davinci/pll-dm644x.c                   |  41 ++
 drivers/clk/davinci/pll-dm646x.c                   |  44 ++
 drivers/clk/davinci/pll.c                          | 564 ++++++++++++++++
 drivers/clk/davinci/pll.h                          |  61 ++
 drivers/clk/davinci/psc-da830.c                    |  96 +++
 drivers/clk/davinci/psc-da850.c                    | 117 ++++
 drivers/clk/davinci/psc-dm355.c                    |  78 +++
 drivers/clk/davinci/psc-dm365.c                    |  83 +++
 drivers/clk/davinci/psc-dm644x.c                   |  73 ++
 drivers/clk/davinci/psc-dm646x.c                   |  68 ++
 drivers/clk/davinci/psc.c                          | 282 ++++++++
 drivers/clk/davinci/psc.h                          |  49 ++
 include/linux/clk/davinci.h                        |  39 ++
 63 files changed, 3172 insertions(+), 3801 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt
 create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-mux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-usb-phy.txt
 create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/psc.txt
 delete mode 100644 arch/arm/mach-davinci/clock.c
 delete mode 100644 arch/arm/mach-davinci/psc.c
 create mode 100644 drivers/clk/davinci/Makefile
 create mode 100644 drivers/clk/davinci/da8xx-cfgchip.c
 create mode 100644 drivers/clk/davinci/da8xx-usb-phy-clk.c
 create mode 100644 drivers/clk/davinci/pll-da830.c
 create mode 100644 drivers/clk/davinci/pll-da850.c
 create mode 100644 drivers/clk/davinci/pll-dm355.c
 create mode 100644 drivers/clk/davinci/pll-dm365.c
 create mode 100644 drivers/clk/davinci/pll-dm644x.c
 create mode 100644 drivers/clk/davinci/pll-dm646x.c
 create mode 100644 drivers/clk/davinci/pll.c
 create mode 100644 drivers/clk/davinci/pll.h
 create mode 100644 drivers/clk/davinci/psc-da830.c
 create mode 100644 drivers/clk/davinci/psc-da850.c
 create mode 100644 drivers/clk/davinci/psc-dm355.c
 create mode 100644 drivers/clk/davinci/psc-dm365.c
 create mode 100644 drivers/clk/davinci/psc-dm644x.c
 create mode 100644 drivers/clk/davinci/psc-dm646x.c
 create mode 100644 drivers/clk/davinci/psc.c
 create mode 100644 drivers/clk/davinci/psc.h
 create mode 100644 include/linux/clk/davinci.h

Comments

Sekhar Nori Jan. 12, 2018, 9:21 a.m. UTC | #1
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new driver for mach-davinci PLL clocks. This is porting the
> code from arch/arm/mach-davinci/clock.c to the common clock framework.
> Additionally, it adds device tree support for these clocks.
> 
> The ifeq ($(CONFIG_COMMON_CLK), y) in the Makefile is needed to prevent
> compile errors until the clock code in arch/arm/mach-davinci is removed.
> 
> Note: although there are similar clocks for TI Keystone we are not able
> to share the code for a few reasons. The keystone clocks are device tree
> only and use legacy one-node-per-clock bindings. Also the register
> layouts are a bit different, which would add even more if/else mess
> to the keystone clocks. And the keystone PLL driver doesn't support
> setting clock rates.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  MAINTAINERS                  |   6 +
>  drivers/clk/Makefile         |   1 +
>  drivers/clk/davinci/Makefile |   5 +
>  drivers/clk/davinci/pll.c    | 564 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/davinci/pll.h    |  61 +++++
>  5 files changed, 637 insertions(+)
>  create mode 100644 drivers/clk/davinci/Makefile
>  create mode 100644 drivers/clk/davinci/pll.c
>  create mode 100644 drivers/clk/davinci/pll.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a6e86e2..1db0cf0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13554,6 +13554,12 @@ F:	arch/arm/mach-davinci/
>  F:	drivers/i2c/busses/i2c-davinci.c
>  F:	arch/arm/boot/dts/da850*
>  
> +TI DAVINCI SERIES CLOCK DRIVER
> +M:	David Lechner <david@lechnology.com>

Please also add:

R: Sekhar Nori <nsekhar@ti.com>

> +S:	Maintained
> +F:	Documentation/devicetree/bindings/clock/ti/davinci/
> +F:	drivers/clk/davinci/
> +
>  TI DAVINCI SERIES GPIO DRIVER
>  M:	Keerthy <j-keerthy@ti.com>
>  L:	linux-gpio@vger.kernel.org
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index f7f761b..c865fd0 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -60,6 +60,7 @@ obj-$(CONFIG_ARCH_ARTPEC)		+= axis/
>  obj-$(CONFIG_ARC_PLAT_AXS10X)		+= axs10x/
>  obj-y					+= bcm/
>  obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
> +obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
>  obj-$(CONFIG_H8300)			+= h8300/
>  obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
>  obj-y					+= imgtec/
> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
> new file mode 100644
> index 0000000..d9673bd
> --- /dev/null
> +++ b/drivers/clk/davinci/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +ifeq ($(CONFIG_COMMON_CLK), y)
> +obj-y += pll.o
> +endif
> diff --git a/drivers/clk/davinci/pll.c b/drivers/clk/davinci/pll.c
> new file mode 100644
> index 0000000..46f9c18
> --- /dev/null
> +++ b/drivers/clk/davinci/pll.c
> @@ -0,0 +1,564 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PLL clock driver for TI Davinci SoCs
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
> + *
> + * Based on drivers/clk/keystone/pll.c
> + * Copyright (C) 2013 Texas Instruments Inc.
> + *	Murali Karicheri <m-karicheri2@ti.com>
> + *	Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * And on arch/arm/mach-davinci/clock.c
> + * Copyright (C) 2006-2007 Texas Instruments.
> + * Copyright (C) 2008-2009 Deep Root Systems, LLC
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/of_address.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include "pll.h"
> +
> +#define REVID		0x000
> +#define PLLCTL		0x100
> +#define OCSEL		0x104
> +#define PLLSECCTL	0x108
> +#define PLLM		0x110
> +#define PREDIV		0x114
> +#define PLLDIV1		0x118
> +#define PLLDIV2		0x11c
> +#define PLLDIV3		0x120
> +#define OSCDIV		0x124
> +#define POSTDIV		0x128
> +#define BPDIV		0x12c
> +#define PLLCMD		0x138
> +#define PLLSTAT		0x13c
> +#define ALNCTL		0x140
> +#define DCHANGE		0x144
> +#define CKEN		0x148
> +#define CKSTAT		0x14c
> +#define SYSTAT		0x150
> +#define PLLDIV4		0x160
> +#define PLLDIV5		0x164
> +#define PLLDIV6		0x168
> +#define PLLDIV7		0x16c
> +#define PLLDIV8		0x170
> +#define PLLDIV9		0x174
> +
> +#define PLLCTL_PLLEN	BIT(0)
> +#define PLLCTL_PLLPWRDN	BIT(1)
> +#define PLLCTL_PLLRST	BIT(3)
> +#define PLLCTL_PLLDIS	BIT(4)
> +#define PLLCTL_PLLENSRC	BIT(5)
> +#define PLLCTL_CLKMODE	BIT(8)
> +
> +#define PLLM_MASK		0x1f
> +#define PREDIV_RATIO_MASK	0x1f

May be use the mode modern GENMASK()?

> +#define PREDIV_PREDEN		BIT(15)
> +#define PLLDIV_RATIO_WIDTH	5
> +#define PLLDIV_ENABLE_SHIFT	15
> +#define OSCDIV_RATIO_WIDTH	5
> +#define POSTDIV_RATIO_MASK	0x1f
> +#define POSTDIV_POSTDEN		BIT(15)
> +#define BPDIV_RATIO_SHIFT	0
> +#define BPDIV_RATIO_WIDTH	5
> +#define CKEN_OBSCLK_SHIFT	1
> +#define CKEN_AUXEN_SHIFT	0
> +
> +/*
> + * OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN
> + * cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us
> + * ensures we are good for all > 4MHz OSCIN/CLKIN inputs. Typically the input
> + * is ~25MHz. Units are micro seconds.
> + */
> +#define PLL_BYPASS_TIME		1
> +/* From OMAP-L138 datasheet table 6-4. Units are micro seconds */

An empty line before the comment make it easier to read.

> +#define PLL_RESET_TIME		1
> +/*
> + * From OMAP-L138 datasheet table 6-4; assuming prediv = 1, sqrt(pllm) = 4
> + * Units are micro seconds.
> + */
> +#define PLL_LOCK_TIME		20
> +
> +/**
> + * struct davinci_pll_clk - Main PLL clock
> + * @hw: clk_hw for the pll
> + * @base: Base memory address
> + * @parent_rate: Saved parent rate used by some child clocks

You don't have parent_rate in the structure below.

> + */
> +struct davinci_pll_clk {
> +	struct clk_hw hw;
> +	void __iomem *base;
> +};
> +
> +#define to_davinci_pll_clk(_hw) container_of((_hw), struct davinci_pll_clk, hw)
> +
> +static unsigned long davinci_pll_clk_recalc(struct clk_hw *hw,
> +					    unsigned long parent_rate)
> +{
> +	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
> +	unsigned long rate = parent_rate;
> +	u32 prediv, mult, postdiv;
> +
> +	prediv = readl(pll->base + PREDIV) & PREDIV_RATIO_MASK;
> +	mult = readl(pll->base + PLLM) & PLLM_MASK;
> +	postdiv = readl(pll->base + POSTDIV) & POSTDIV_RATIO_MASK;

Shouldn't we check if the pre and post dividers are enabled before using
them?

> +
> +	rate /= prediv + 1;
> +	rate *= mult + 1;
> +	rate /= postdiv + 1;
> +
> +	return rate;
> +}
> +
> +/**
> + * davinci_pll_get_best_rate - Calculate PLL output closest to a given rate
> + * @rate: The target rate
> + * @parent_rate: The PLL input clock rate
> + * @mult: Pointer to hold the multiplier value (optional)
> + * @postdiv: Pointer to hold the postdiv value (optional)
> + *
> + * Returns: The closest rate less than or equal to @rate that the PLL can
> + * generate. @mult and @postdiv will contain the values required to generate
> + * that rate.
> + */
> +static long davinci_pll_get_best_rate(u32 rate, u32 parent_rate, u32 *mult,
> +				      u32 *postdiv)
> +{
> +	u32 r, m, d;
> +	u32 best_rate = 0;
> +	u32 best_mult = 0;
> +	u32 best_postdiv = 0;
> +
> +	for (d = 1; d <= 4; d++) {> +		for (m = min(32U, rate * d / parent_rate); m > 0; m--) {
> +			r = parent_rate * m / d;
> +
> +			if (r < best_rate)
> +				break;
> +
> +			if (r > best_rate && r <= rate) {
> +				best_rate = r;
> +				best_mult = m;
> +				best_postdiv = d;
> +			}
> +
> +			if (best_rate == rate)
> +				goto out;
> +		}
> +	}
> +
> +out:
> +	if (mult)
> +		*mult = best_mult;
> +	if (postdiv)
> +		*postdiv = best_postdiv;
> +
> +	return best_rate;
> +}

PLL output on DA850 must never be below 300MHz or above 600MHz (see
datasheet table "Allowed PLL Operating Conditions"). Does this take care
of that? Thats one of the main reasons I recall I went with some
specific values of prediv, pllm and post div in
arch/arm/mach-davinci/da850.c

> +
> +static long davinci_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +				   unsigned long *parent_rate)
> +{
> +	return davinci_pll_get_best_rate(rate, *parent_rate, NULL, NULL);
> +}
> +
> +/**
> + * __davinci_pll_set_rate - set the output rate of a given PLL.
> + *
> + * Note: Currently tested to work with OMAP-L138 only.
> + *
> + * @pll: pll whose rate needs to be changed.
> + * @prediv: The pre divider value. Passing 0 disables the pre-divider.
> + * @pllm: The multiplier value. Passing 0 leads to multiply-by-one.
> + * @postdiv: The post divider value. Passing 0 disables the post-divider.
> + */
> +static void __davinci_pll_set_rate(struct davinci_pll_clk *pll, u32 prediv,
> +				   u32 mult, u32 postdiv)
> +{
> +	u32 ctrl, locktime;
> +
> +	/*
> +	 * PLL lock time required per OMAP-L138 datasheet is
> +	 * (2000 * prediv)/sqrt(pllm) OSCIN cycles. We approximate sqrt(pllm)
> +	 * as 4 and OSCIN cycle as 25 MHz.
> +	 */
> +	if (prediv) {
> +		locktime = ((2000 * prediv) / 100);
> +		prediv = (prediv - 1) | PREDIV_PREDEN;
> +	} else {
> +		locktime = PLL_LOCK_TIME;
> +	}

Empty line here will be nice.

> +	if (postdiv)
> +		postdiv = (postdiv - 1) | POSTDIV_POSTDEN;
> +	if (mult)
> +		mult = mult - 1;
> +
> +	ctrl = readl(pll->base + PLLCTL);
> +
> +	/* Switch the PLL to bypass mode */
> +	ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
> +	writel(ctrl, pll->base + PLLCTL);
> +
> +	udelay(PLL_BYPASS_TIME);
> +
> +	/* Reset and enable PLL */
> +	ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
> +	writel(ctrl, pll->base + PLLCTL);
> +
> +	writel(prediv, pll->base + PREDIV);
> +	writel(mult, pll->base + PLLM);
> +	writel(postdiv, pll->base + POSTDIV);
> +
> +	udelay(PLL_RESET_TIME);
> +
> +	/* Bring PLL out of reset */
> +	ctrl |= PLLCTL_PLLRST;
> +	writel(ctrl, pll->base + PLLCTL);
> +
> +	udelay(locktime);
> +
> +	/* Remove PLL from bypass mode */
> +	ctrl |= PLLCTL_PLLEN;
> +	writel(ctrl, pll->base + PLLCTL);
> +}

[...]

> +/**
> + * davinci_pll_obs_clk_register - Register oscillator divider clock (OBSCLK)
> + * @name: The clock name
> + * @parent_names: The parent clock names
> + * @num_parents: The number of paren clocks
> + * @base: The PLL memory region
> + * @table: A table of values cooresponding to the parent clocks (see OCSEL
> + *         register in SRM for values)
> + */
> +struct clk *davinci_pll_obs_clk_register(const char *name,
> +					 const char * const *parent_names,
> +					 u8 num_parents,
> +					 void __iomem *base,
> +					 u32 *table)
> +{
> +	struct clk_mux *mux;
> +	struct clk_gate *gate;
> +	struct clk_divider *divider;
> +	struct clk *clk;
> +
> +	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> +	if (!mux)
> +		return ERR_PTR(-ENOMEM);
> +
> +	mux->reg = base + OCSEL;
> +	mux->table = table;
> +
> +	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> +	if (!gate) {
> +		kfree(mux);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	gate->reg = base + CKEN;
> +	gate->bit_idx = CKEN_OBSCLK_SHIFT;
> +
> +	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
> +	if (!divider) {
> +		kfree(gate);
> +		kfree(mux);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	divider->reg = base + OSCDIV;
> +	divider->width = OSCDIV_RATIO_WIDTH;

can you write OD1EN of OSCDIV here? I guess the reset default is 1 so
you didnt need to do that. But not doing exposes us to settings that
bootloader left us in.

> +
> +	clk = clk_register_composite(NULL, name, parent_names, num_parents,
> +				     &mux->hw, &clk_mux_ops,
> +				     &divider->hw, &clk_divider_ops,
> +				     &gate->hw, &clk_gate_ops, 0);
> +	if (IS_ERR(clk)) {
> +		kfree(divider);
> +		kfree(gate);
> +		kfree(mux);
> +	}
> +
> +	return clk;
> +}
> +
> +struct clk *
> +davinci_pll_divclk_register(const struct davinci_pll_divclk_info *info,
> +			    void __iomem *base)
> +{
> +	const struct clk_ops *divider_ops = &clk_divider_ops;

setting the sysclk divider requires GOSTAT handling apart from setting
the divider value. So I think .set_rate ops above wont work. Other ops
can be used, I guess. So we need a private structure here.

Can you port over davinci_set_sysclk_rate() too? I understand you cannot
test it due to lack of cpufreq support in DT, but I can help testing there.

Or leave .set_rate NULL and it can be added later.

> +	struct clk_gate *gate;
> +	struct clk_divider *divider;
> +	struct clk *clk;
> +	u32 reg;
> +	u32 flags = 0;
> +
> +	/* PLLDIVn registers are not entirely consecutive */
> +	if (info->id < 4)
> +		reg = PLLDIV1 + 4 * (info->id - 1);
> +	else
> +		reg = PLLDIV4 + 4 * (info->id - 4);
> +
> +	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> +	if (!gate)
> +		return ERR_PTR(-ENOMEM);
> +
> +	gate->reg = base + reg;
> +	gate->bit_idx = PLLDIV_ENABLE_SHIFT;
> +
> +	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
> +	if (!divider) {
> +		kfree(gate);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	divider->reg = base + reg;
> +	divider->width = PLLDIV_RATIO_WIDTH;
> +	divider->flags = 0;
> +
> +	if (info->flags & DIVCLK_FIXED_DIV) {
> +		flags |= CLK_DIVIDER_READ_ONLY;
> +		divider_ops = &clk_divider_ro_ops;
> +	}
> +
> +	/* Only the ARM clock can change the parent PLL rate */
> +	if (info->flags & DIVCLK_ARM_RATE)
> +		flags |= CLK_SET_RATE_PARENT;
> +
> +	if (info->flags & DIVCLK_ALWAYS_ENABLED)
> +		flags |= CLK_IS_CRITICAL;
> +
> +	clk = clk_register_composite(NULL, info->name, &info->parent_name, 1,
> +				     NULL, NULL, &divider->hw, divider_ops,
> +				     &gate->hw, &clk_gate_ops, flags);
> +	if (IS_ERR(clk)) {
> +		kfree(divider);
> +		kfree(gate);
> +	}
> +
> +	return clk;
> +}
> +
> +#ifdef CONFIG_OF
> +#define MAX_NAME_SIZE 20
> +
> +void of_davinci_pll_init(struct device_node *node, const char *name,
> +			 const struct davinci_pll_divclk_info *info,
> +			 u8 max_divclk_id)
> +{
> +	struct device_node *child;
> +	const char *parent_name;
> +	void __iomem *base;
> +	struct clk *clk;
> +
> +	base = of_iomap(node, 0);
> +	if (!base) {
> +		pr_err("%s: ioremap failed\n", __func__);
> +		return;
> +	}
> +
> +	parent_name = of_clk_get_parent_name(node, 0);
> +
> +	clk = davinci_pll_clk_register(name, parent_name, base);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register %s (%ld)\n", __func__, name,
> +		       PTR_ERR(clk));

You can probably avoid these line breaks by adding on top of the file

#define pr_fmt(fmt) "%s: " fmt "\n", __func__

> +		return;
> +	}
> +
> +	child = of_get_child_by_name(node, "sysclk");
> +	if (child && of_device_is_available(child)) {
> +		struct clk_onecell_data *clk_data;
> +
> +		clk_data = clk_alloc_onecell_data(max_divclk_id + 1);
> +		if (!clk_data) {
> +			pr_err("%s: out of memory\n", __func__);
> +			return;
> +		}
> +
> +		for (; info->name; info++) {
> +			clk = davinci_pll_divclk_register(info, base);
> +			if (IS_ERR(clk))
> +				pr_warn("%s: failed to register %s (%ld)\n",
> +					__func__, info->name, PTR_ERR(clk));
> +			else
> +				clk_data->clks[info->id] = clk;
> +		}
> +		of_clk_add_provider(child, of_clk_src_onecell_get, clk_data);
> +	}
> +	of_node_put(child);
> +
> +	child = of_get_child_by_name(node, "auxclk");
> +	if (child && of_device_is_available(child)) {
> +		char child_name[MAX_NAME_SIZE];
> +
> +		snprintf(child_name, MAX_NAME_SIZE, "%s_aux_clk", name);
> +
> +		clk = davinci_pll_aux_clk_register(child_name, parent_name, base);
> +		if (IS_ERR(clk))
> +			pr_warn("%s: failed to register %s (%ld)\n", __func__,
> +				child_name, PTR_ERR(clk));
> +		else
> +			of_clk_add_provider(child, of_clk_src_simple_get, clk);
> +	}

davinci_pll_obs_clk_register() should also be handled here?

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 12, 2018, 9:41 a.m. UTC | #2
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PLL clocks on TI DA830/
> OMAP-L137/AM17XX SoCs.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Reviewed-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 12, 2018, 3:25 p.m. UTC | #3
On 01/12/2018 03:21 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds a new driver for mach-davinci PLL clocks. This is porting the
>> code from arch/arm/mach-davinci/clock.c to the common clock framework.
>> Additionally, it adds device tree support for these clocks.
>>
>> The ifeq ($(CONFIG_COMMON_CLK), y) in the Makefile is needed to prevent
>> compile errors until the clock code in arch/arm/mach-davinci is removed.
>>
>> Note: although there are similar clocks for TI Keystone we are not able
>> to share the code for a few reasons. The keystone clocks are device tree
>> only and use legacy one-node-per-clock bindings. Also the register
>> layouts are a bit different, which would add even more if/else mess
>> to the keystone clocks. And the keystone PLL driver doesn't support
>> setting clock rates.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---

>> +
>> +#define PLLM_MASK		0x1f
>> +#define PREDIV_RATIO_MASK	0x1f
> 
> May be use the mode modern GENMASK()?

I haven't seen that one before. Thanks.

...

>> +static unsigned long davinci_pll_clk_recalc(struct clk_hw *hw,
>> +					    unsigned long parent_rate)
>> +{
>> +	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
>> +	unsigned long rate = parent_rate;
>> +	u32 prediv, mult, postdiv;
>> +
>> +	prediv = readl(pll->base + PREDIV) & PREDIV_RATIO_MASK;
>> +	mult = readl(pll->base + PLLM) & PLLM_MASK;
>> +	postdiv = readl(pll->base + POSTDIV) & POSTDIV_RATIO_MASK;
> 
> Shouldn't we check if the pre and post dividers are enabled before using
> them?

Indeed.

> 
>> +
>> +	rate /= prediv + 1;
>> +	rate *= mult + 1;
>> +	rate /= postdiv + 1;
>> +
>> +	return rate;
>> +}
>> +

...

> 
> PLL output on DA850 must never be below 300MHz or above 600MHz (see
> datasheet table "Allowed PLL Operating Conditions"). Does this take care
> of that? Thats one of the main reasons I recall I went with some
> specific values of prediv, pllm and post div in
> arch/arm/mach-davinci/da850.c

Apparently, I missed this requirement. It looks like I am going to have to
rework things so that there is some coordination between the PLL and the
PLLDIV clocks in order to get the < 300MHz operating points.

...

>> +
>> +	divider->reg = base + OSCDIV;
>> +	divider->width = OSCDIV_RATIO_WIDTH;
> 
> can you write OD1EN of OSCDIV here? I guess the reset default is 1 so
> you didnt need to do that. But not doing exposes us to settings that
> bootloader left us in.
> 

It looks like I am going to have to make a custom implementation for parts
of this clock anyway, so I will probably just make new enable/disable
callbacks that set both OSCDIV_OD1EN and CKEN_OBSCLK.

>> +
>> +	clk = clk_register_composite(NULL, name, parent_names, num_parents,
>> +				     &mux->hw, &clk_mux_ops,
>> +				     &divider->hw, &clk_divider_ops,
>> +				     &gate->hw, &clk_gate_ops, 0);
>> +	if (IS_ERR(clk)) {
>> +		kfree(divider);
>> +		kfree(gate);
>> +		kfree(mux);
>> +	}
>> +
>> +	return clk;
>> +}
>> +
>> +struct clk *
>> +davinci_pll_divclk_register(const struct davinci_pll_divclk_info *info,
>> +			    void __iomem *base)
>> +{
>> +	const struct clk_ops *divider_ops = &clk_divider_ops;
> 
> setting the sysclk divider requires GOSTAT handling apart from setting
> the divider value. So I think .set_rate ops above wont work. Other ops
> can be used, I guess. So we need a private structure here.
> 
> Can you port over davinci_set_sysclk_rate() too? I understand you cannot
> test it due to lack of cpufreq support in DT, but I can help testing there.
> 
> Or leave .set_rate NULL and it can be added later.

Yes, I noticed that I missed this after I submitted this series. And I
will have to rework things to coordinate with the PLL as mentioned above.

FYI, I do have cpufreq-dt working, although the LEGO EV3 has a fixed 1.2V
regulator, so I am limited in what I can test. Basically, I can only switch
between 300MHz and 375MHz according to the datasheets. The chip is technically
the 456MHz version. What would happen if I ran it faster or slower with the
wrong voltage?

...

>> +
>> +	child = of_get_child_by_name(node, "auxclk");
>> +	if (child && of_device_is_available(child)) {
>> +		char child_name[MAX_NAME_SIZE];
>> +
>> +		snprintf(child_name, MAX_NAME_SIZE, "%s_aux_clk", name);
>> +
>> +		clk = davinci_pll_aux_clk_register(child_name, parent_name, base);
>> +		if (IS_ERR(clk))
>> +			pr_warn("%s: failed to register %s (%ld)\n", __func__,
>> +				child_name, PTR_ERR(clk));
>> +		else
>> +			of_clk_add_provider(child, of_clk_src_simple_get, clk);
>> +	}
> 
> davinci_pll_obs_clk_register() should also be handled here?

I omitted it because no one is using it (same reason I left it out of the
device tree bindings). We can certainly add it, though.


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adam Ford Jan. 12, 2018, 3:30 p.m. UTC | #4
On Fri, Jan 12, 2018 at 9:25 AM, David Lechner <david@lechnology.com> wrote:
> On 01/12/2018 03:21 AM, Sekhar Nori wrote:
>>
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>>
>>> This adds a new driver for mach-davinci PLL clocks. This is porting the
>>> code from arch/arm/mach-davinci/clock.c to the common clock framework.
>>> Additionally, it adds device tree support for these clocks.
>>>
>>> The ifeq ($(CONFIG_COMMON_CLK), y) in the Makefile is needed to prevent
>>> compile errors until the clock code in arch/arm/mach-davinci is removed.
>>>
>>> Note: although there are similar clocks for TI Keystone we are not able
>>> to share the code for a few reasons. The keystone clocks are device tree
>>> only and use legacy one-node-per-clock bindings. Also the register
>>> layouts are a bit different, which would add even more if/else mess
>>> to the keystone clocks. And the keystone PLL driver doesn't support
>>> setting clock rates.
>>>
>>> Signed-off-by: David Lechner <david@lechnology.com>
>>> ---
>
>
>>> +
>>> +#define PLLM_MASK              0x1f
>>> +#define PREDIV_RATIO_MASK      0x1f
>>
>>
>> May be use the mode modern GENMASK()?
>
>
> I haven't seen that one before. Thanks.
>
> ...
>
>>> +static unsigned long davinci_pll_clk_recalc(struct clk_hw *hw,
>>> +                                           unsigned long parent_rate)
>>> +{
>>> +       struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
>>> +       unsigned long rate = parent_rate;
>>> +       u32 prediv, mult, postdiv;
>>> +
>>> +       prediv = readl(pll->base + PREDIV) & PREDIV_RATIO_MASK;
>>> +       mult = readl(pll->base + PLLM) & PLLM_MASK;
>>> +       postdiv = readl(pll->base + POSTDIV) & POSTDIV_RATIO_MASK;
>>
>>
>> Shouldn't we check if the pre and post dividers are enabled before using
>> them?
>
>
> Indeed.
>
>>
>>> +
>>> +       rate /= prediv + 1;
>>> +       rate *= mult + 1;
>>> +       rate /= postdiv + 1;
>>> +
>>> +       return rate;
>>> +}
>>> +
>
>
> ...
>
>>
>> PLL output on DA850 must never be below 300MHz or above 600MHz (see
>> datasheet table "Allowed PLL Operating Conditions"). Does this take care
>> of that? Thats one of the main reasons I recall I went with some
>> specific values of prediv, pllm and post div in
>> arch/arm/mach-davinci/da850.c
>
>
> Apparently, I missed this requirement. It looks like I am going to have to
> rework things so that there is some coordination between the PLL and the
> PLLDIV clocks in order to get the < 300MHz operating points.
>
> ...
>
>>> +
>>> +       divider->reg = base + OSCDIV;
>>> +       divider->width = OSCDIV_RATIO_WIDTH;
>>
>>
>> can you write OD1EN of OSCDIV here? I guess the reset default is 1 so
>> you didnt need to do that. But not doing exposes us to settings that
>> bootloader left us in.
>>
>
> It looks like I am going to have to make a custom implementation for parts
> of this clock anyway, so I will probably just make new enable/disable
> callbacks that set both OSCDIV_OD1EN and CKEN_OBSCLK.
>
>
>>> +
>>> +       clk = clk_register_composite(NULL, name, parent_names,
>>> num_parents,
>>> +                                    &mux->hw, &clk_mux_ops,
>>> +                                    &divider->hw, &clk_divider_ops,
>>> +                                    &gate->hw, &clk_gate_ops, 0);
>>> +       if (IS_ERR(clk)) {
>>> +               kfree(divider);
>>> +               kfree(gate);
>>> +               kfree(mux);
>>> +       }
>>> +
>>> +       return clk;
>>> +}
>>> +
>>> +struct clk *
>>> +davinci_pll_divclk_register(const struct davinci_pll_divclk_info *info,
>>> +                           void __iomem *base)
>>> +{
>>> +       const struct clk_ops *divider_ops = &clk_divider_ops;
>>
>>
>> setting the sysclk divider requires GOSTAT handling apart from setting
>> the divider value. So I think .set_rate ops above wont work. Other ops
>> can be used, I guess. So we need a private structure here.
>>
>> Can you port over davinci_set_sysclk_rate() too? I understand you cannot
>> test it due to lack of cpufreq support in DT, but I can help testing
>> there.
>>
>> Or leave .set_rate NULL and it can be added later.
>
>
> Yes, I noticed that I missed this after I submitted this series. And I
> will have to rework things to coordinate with the PLL as mentioned above.
>
> FYI, I do have cpufreq-dt working, although the LEGO EV3 has a fixed 1.2V
> regulator, so I am limited in what I can test. Basically, I can only switch

I can test the cpufreq-dt.  Are there additional patches or are they
part of the same git repo I have been testing?

The DA850 I have may not run all the way to highest speed, but I'll
see what I can find.  I think I had a few at one point, but I don't
think it was part of Logic PD's standard product lineup.

adam

> between 300MHz and 375MHz according to the datasheets. The chip is
> technically
> the 456MHz version. What would happen if I ran it faster or slower with the
> wrong voltage?
>
> ...
>
>>> +
>>> +       child = of_get_child_by_name(node, "auxclk");
>>> +       if (child && of_device_is_available(child)) {
>>> +               char child_name[MAX_NAME_SIZE];
>>> +
>>> +               snprintf(child_name, MAX_NAME_SIZE, "%s_aux_clk", name);
>>> +
>>> +               clk = davinci_pll_aux_clk_register(child_name,
>>> parent_name, base);
>>> +               if (IS_ERR(clk))
>>> +                       pr_warn("%s: failed to register %s (%ld)\n",
>>> __func__,
>>> +                               child_name, PTR_ERR(clk));
>>> +               else
>>> +                       of_clk_add_provider(child, of_clk_src_simple_get,
>>> clk);
>>> +       }
>>
>>
>> davinci_pll_obs_clk_register() should also be handled here?
>
>
> I omitted it because no one is using it (same reason I left it out of the
> device tree bindings). We can certainly add it, though.
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 12, 2018, 3:48 p.m. UTC | #5
On 01/12/2018 09:30 AM, Adam Ford wrote:
> On Fri, Jan 12, 2018 at 9:25 AM, David Lechner <david@lechnology.com> wrote:
>>
>> Yes, I noticed that I missed this after I submitted this series. And I
>> will have to rework things to coordinate with the PLL as mentioned above.
>>
>> FYI, I do have cpufreq-dt working, although the LEGO EV3 has a fixed 1.2V
>> regulator, so I am limited in what I can test. Basically, I can only switch
> 
> I can test the cpufreq-dt.  Are there additional patches or are they
> part of the same git repo I have been testing?
> 
> The DA850 I have may not run all the way to highest speed, but I'll
> see what I can find.  I think I had a few at one point, but I don't
> think it was part of Logic PD's standard product lineup.
> 

There are some extra patches I have not submitted yet. However, based on the
other comments here, I don't have things implemented correctly, so you probably
want to wait to test until I get that straightened out anyway.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 12, 2018, 4:18 p.m. UTC | #6
On Friday 12 January 2018 08:55 PM, David Lechner wrote:
>>
>> PLL output on DA850 must never be below 300MHz or above 600MHz (see
>> datasheet table "Allowed PLL Operating Conditions"). Does this take care
>> of that? Thats one of the main reasons I recall I went with some
>> specific values of prediv, pllm and post div in
>> arch/arm/mach-davinci/da850.c
> 
> Apparently, I missed this requirement. It looks like I am going to have to
> rework things so that there is some coordination between the PLL and the
> PLLDIV clocks in order to get the < 300MHz operating points.

Just to make sure we are on the same page. The datasheet
constraint is 600 >= PLLOUT >= 300. PLLOUT is output of POSTDIV.

The operating points are defined in terms of ARM frequency (and
voltage). The OPPs defined in kernel today are here:
https://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git/tree/arch/arm/mach-davinci/da850.c#n1092

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 13, 2018, 1:11 a.m. UTC | #7
On 01/12/2018 10:18 AM, Sekhar Nori wrote:
> On Friday 12 January 2018 08:55 PM, David Lechner wrote:
>>>
>>> PLL output on DA850 must never be below 300MHz or above 600MHz (see
>>> datasheet table "Allowed PLL Operating Conditions"). Does this take care
>>> of that? Thats one of the main reasons I recall I went with some
>>> specific values of prediv, pllm and post div in
>>> arch/arm/mach-davinci/da850.c
>>
>> Apparently, I missed this requirement. It looks like I am going to have to
>> rework things so that there is some coordination between the PLL and the
>> PLLDIV clocks in order to get the < 300MHz operating points.
> 
> Just to make sure we are on the same page. The datasheet
> constraint is 600 >= PLLOUT >= 300. PLLOUT is output of POSTDIV.

Hmm... I am on a different page. It looks to me like PLLOUT is the output
of PLLM, not POSTDIV. The datasheet says nothing at all and the TRM does
not say it explicitly, but footnote 2 on the table "System PLLC Output
Clocks", for example, makes it pretty clear.

> 
> The operating points are defined in terms of ARM frequency (and
> voltage). The OPPs defined in kernel today are here:
> https://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git/tree/arch/arm/mach-davinci/da850.c#n1092
> 
> Thanks,
> Sekhar
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 13, 2018, 2:13 a.m. UTC | #8
On 01/12/2018 03:21 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> +static unsigned long davinci_pll_clk_recalc(struct clk_hw *hw,
>> +					    unsigned long parent_rate)
>> +{
>> +	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
>> +	unsigned long rate = parent_rate;
>> +	u32 prediv, mult, postdiv;
>> +
>> +	prediv = readl(pll->base + PREDIV) & PREDIV_RATIO_MASK;
>> +	mult = readl(pll->base + PLLM) & PLLM_MASK;
>> +	postdiv = readl(pll->base + POSTDIV) & POSTDIV_RATIO_MASK;
> 
> Shouldn't we check if the pre and post dividers are enabled before using
> them?

I dug into this and the answer is no. The enable bit acts like a gate, not
a bypass, so it does not affect the rate calculation.



--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 6:32 a.m. UTC | #9
On Saturday 13 January 2018 07:43 AM, David Lechner wrote:
> On 01/12/2018 03:21 AM, Sekhar Nori wrote:
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>> +static unsigned long davinci_pll_clk_recalc(struct clk_hw *hw,
>>> +                        unsigned long parent_rate)
>>> +{
>>> +    struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
>>> +    unsigned long rate = parent_rate;
>>> +    u32 prediv, mult, postdiv;
>>> +
>>> +    prediv = readl(pll->base + PREDIV) & PREDIV_RATIO_MASK;
>>> +    mult = readl(pll->base + PLLM) & PLLM_MASK;
>>> +    postdiv = readl(pll->base + POSTDIV) & POSTDIV_RATIO_MASK;
>>
>> Shouldn't we check if the pre and post dividers are enabled before using
>> them?
> 
> I dug into this and the answer is no. The enable bit acts like a gate, not
> a bypass, so it does not affect the rate calculation.

Alright, thanks for checking this.

Regards,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 6:48 a.m. UTC | #10
On Saturday 13 January 2018 06:41 AM, David Lechner wrote:
> On 01/12/2018 10:18 AM, Sekhar Nori wrote:
>> On Friday 12 January 2018 08:55 PM, David Lechner wrote:
>>>>
>>>> PLL output on DA850 must never be below 300MHz or above 600MHz (see
>>>> datasheet table "Allowed PLL Operating Conditions"). Does this take
>>>> care
>>>> of that? Thats one of the main reasons I recall I went with some
>>>> specific values of prediv, pllm and post div in
>>>> arch/arm/mach-davinci/da850.c
>>>
>>> Apparently, I missed this requirement. It looks like I am going to
>>> have to
>>> rework things so that there is some coordination between the PLL and the
>>> PLLDIV clocks in order to get the < 300MHz operating points.
>>
>> Just to make sure we are on the same page. The datasheet
>> constraint is 600 >= PLLOUT >= 300. PLLOUT is output of POSTDIV.
> 
> Hmm... I am on a different page. It looks to me like PLLOUT is the output
> of PLLM, not POSTDIV. The datasheet says nothing at all and the TRM does
> not say it explicitly, but footnote 2 on the table "System PLLC Output
> Clocks", for example, makes it pretty clear.

You are right. There is also this note in "Device clock generation" of
TRM which makes this clear.

"
The PLLOUT stage in PLLC0 and PLLC1 is capable of providing frequencies
greater than what the SYSCLK dividers can handle. The POSTDIV stage
should be programmed to keep the input to the SYSCLK dividers within
operating limits. See the device datasheet for the maximum operating
frequencies.
"

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 8:37 a.m. UTC | #11
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1)
> +{
> +	const struct davinci_pll_divclk_info *info;
> +
> +	davinci_pll_clk_register("pll0", "ref_clk", pll0);

I think this will be more readable with empty lines between these
function calls. So here ..

> +	davinci_pll_aux_clk_register("pll0_aux_clk", "ref_clk", pll0);

.. here

> +	for (info = da850_pll0_divclk_info; info->name; info++)
> +		davinci_pll_divclk_register(info, pll0);
> +
> +	davinci_pll_clk_register("pll1", "ref_clk", pll1);

.. and here.

> +	for (info = da850_pll1_divclk_info; info->name; info++)
> +		davinci_pll_divclk_register(info, pll1);

I see that you have included empty line only when changing the PLL, but
I feel its more readable with the additional spacing suggested.

Same comment for other patches too with similar function implemented.
With that minor comment:

Reviewed-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 8:38 a.m. UTC | #12
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PLL clocks on TI
> DaVinci 355 based systems.

DM355

> 
> Signed-off-by: David Lechner <david@lechnology.com>

Reviewed-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 8:48 a.m. UTC | #13
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PLL clocks on TI
> DaVinci 365 based systems.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  drivers/clk/davinci/Makefile    |  1 +
>  drivers/clk/davinci/pll-dm365.c | 64 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk/davinci.h     |  1 +
>  3 files changed, 66 insertions(+)
>  create mode 100644 drivers/clk/davinci/pll-dm365.c
> 
> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
> index 6720bd0..353aa02 100644
> --- a/drivers/clk/davinci/Makefile
> +++ b/drivers/clk/davinci/Makefile
> @@ -5,4 +5,5 @@ obj-y += pll.o
>  obj-$(CONFIG_ARCH_DAVINCI_DA830)	+= pll-da830.o
>  obj-$(CONFIG_ARCH_DAVINCI_DA850)	+= pll-da850.o
>  obj-$(CONFIG_ARCH_DAVINCI_DM355)	+= pll-dm355.o
> +obj-$(CONFIG_ARCH_DAVINCI_DM365)	+= pll-dm365.o
>  endif
> diff --git a/drivers/clk/davinci/pll-dm365.c b/drivers/clk/davinci/pll-dm365.c
> new file mode 100644
> index 0000000..9892b0b
> --- /dev/null
> +++ b/drivers/clk/davinci/pll-dm365.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PLL clock descriptions for TI DM365
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +
> +#include "pll.h"
> +
> +static const char * const dm365_pll_obsclk_parent_names[] = {
> +	"ref_clk",
> +};
> +
> +static u32 dm365_pll_obsclk_table[] = {
> +	0x10,

Perhaps use a #define here. Something like OBSCLK_SEL_OSC.

> +void __init dm365_pll_clk_init(void __iomem *pll1, void __iomem *pll2)
> +{
> +	const struct davinci_pll_divclk_info *info;
> +
> +	davinci_pll_clk_register("pll1", "ref_clk", pll1);
> +	davinci_pll_aux_clk_register("pll1_aux_clk", "ref_clk", pll1);
> +	davinci_pll_bpdiv_clk_register("pll1_sysclkbp", "ref_clk", pll1);
> +	davinci_pll_obs_clk_register("clkout0", dm365_pll_obsclk_parent_names,
> +				     ARRAY_SIZE(dm365_pll_obsclk_parent_names),
> +				     pll1, dm365_pll_obsclk_table);
> +	for (info = dm365_pll1_divclk_info; info->name; info++)
> +		davinci_pll_divclk_register(info, pll1);
> +
> +	davinci_pll_clk_register("pll2", "ref_clk", pll2);
> +	davinci_pll_aux_clk_register("clkout1", "ref_clk", pll2);
> +	davinci_pll_obs_clk_register("clkout1", dm365_pll_obsclk_parent_names,
> +				    ARRAY_SIZE(dm365_pll_obsclk_parent_names),
> +				    pll2, dm365_pll_obsclk_table);
> +	for (info = dm365_pll2_divclk_info; info->name; info++)
> +		davinci_pll_divclk_register(info, pll2);
> +}

With that and the empty line comment I gave earlier.

Reviewed-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 8:56 a.m. UTC | #14
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PLL clocks on TI
> DaVinci 644x based systems.

DM644x

> Signed-off-by: David Lechner <david@lechnology.com>

> + * Copyright (C) 2017 David Lechner <david@lechnology.com>

2018 now.

> +void __init dm644x_pll_clk_init(void __iomem *pll1, void __iomem *pll2)
> +{
> +	const struct davinci_pll_divclk_info *info;
> +
> +	davinci_pll_clk_register("pll1", "ref_clk", pll1);
> +	for (info = dm644x_pll1_divclk_info; info->name; info++)
> +		davinci_pll_divclk_register(info, pll1);
> +	davinci_pll_aux_clk_register("pll1_aux_clk", "ref_clk", pll1);
> +	davinci_pll_bpdiv_clk_register("pll1_sysclkbp", "ref_clk", pll1);
> +
> +	davinci_pll_clk_register("pll2", "ref_clk", pll2);
> +	for (info = dm644x_pll2_divclk_info; info->name; info++)
> +		davinci_pll_divclk_register(info, pll2);
> +	davinci_pll_bpdiv_clk_register("pll2_sysclkbp", "ref_clk", pll2);
> +}

Here too, more line spacing will help.

With those minor comments.

Reviewed-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 9:01 a.m. UTC | #15
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PLL clocks on TI
> DaVinci 646x based systems.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Some minor comments I gave on other patches apply here too. Apart from
those:

Reviewed-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 11:03 a.m. UTC | #16
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new driver for mach-davinci PSC clocks. This is porting the
> code from arch/arm/mach-davinci/psc.c to the common clock framework and
> is converting it to use regmap to simplify the code. Additionally, it adds
> device tree support for these clocks.
> 
> Note: although there are similar clocks for TI Keystone we are not able
> to share the code for a few reasons. The keystone clocks are device tree
> only and use legacy one-node-per-clock bindings. Also the keystone driver
> makes the assumption that there is only one PSC per SoC and uses global
> variables, but here we have two controllers per SoC.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  drivers/clk/davinci/Makefile |   2 +
>  drivers/clk/davinci/psc.c    | 282 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/davinci/psc.h    |  49 ++++++++
>  3 files changed, 333 insertions(+)
>  create mode 100644 drivers/clk/davinci/psc.c
>  create mode 100644 drivers/clk/davinci/psc.h
> 
> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
> index d471386..cd1bf2c 100644
> --- a/drivers/clk/davinci/Makefile
> +++ b/drivers/clk/davinci/Makefile
> @@ -8,4 +8,6 @@ obj-$(CONFIG_ARCH_DAVINCI_DM355)	+= pll-dm355.o
>  obj-$(CONFIG_ARCH_DAVINCI_DM365)	+= pll-dm365.o
>  obj-$(CONFIG_ARCH_DAVINCI_DM644x)	+= pll-dm644x.o
>  obj-$(CONFIG_ARCH_DAVINCI_DM646x)	+= pll-dm646x.o
> +
> +obj-y += psc.o
>  endif
> diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
> new file mode 100644
> index 0000000..a8b5f57
> --- /dev/null
> +++ b/drivers/clk/davinci/psc.c
> @@ -0,0 +1,282 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Clock driver for TI Davinci PSC controllers
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>

2018

> + *
> + * Based on: drivers/clk/keystone/gate.c
> + * Copyright (C) 2013 Texas Instruments.
> + *	Murali Karicheri <m-karicheri2@ti.com>
> + *	Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * And: arch/arm/mach-davinci/psc.c
> + * Copyright (C) 2006 Texas Instruments.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clk/davinci.h>
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +#include <linux/of_address.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +
> +#include "psc.h"
> +
> +/* PSC register offsets */
> +#define EPCPR			0x070
> +#define PTCMD			0x120
> +#define PTSTAT			0x128
> +#define PDSTAT(n)		(0x200 + 4 * (n))
> +#define PDCTL(n)		(0x300 + 4 * (n))
> +#define MDSTAT(n)		(0x800 + 4 * (n))
> +#define MDCTL(n)		(0xa00 + 4 * (n))
> +
> +/* PSC module states */
> +enum davinci_psc_state {
> +	PSC_STATE_SWRSTDISABLE	= 0,
> +	PSC_STATE_SYNCRST	= 1,
> +	PSC_STATE_DISABLE	= 2,
> +	PSC_STATE_ENABLE	= 3,
> +};
> +
> +#define MDSTAT_STATE_MASK	0x3f> +#define MDSTAT_MCKOUT		BIT(12)
> +#define PDSTAT_STATE_MASK	0x1f

GENMASK() for masks.

> +#define MDCTL_FORCE		BIT(31)
> +#define MDCTL_LRESET		BIT(8)
> +#define PDCTL_EPCGOOD		BIT(8)
> +#define PDCTL_NEXT		BIT(0)
> +
> +/**
> + * struct davinci_psc_clk - PSC clock structure
> + * @hw: clk_hw for the psc
> + * @regmap: PSC MMIO region
> + * @lpsc: Local PSC number (module id)
> + * @pd: Power domain
> + * @flags: LPSC_* quirk flags
> + */
> +struct davinci_psc_clk {
> +	struct clk_hw hw;
> +	struct regmap *regmap;
> +	u32 lpsc;
> +	u32 pd;
> +	u32 flags;
> +};
> +
> +#define to_davinci_psc_clk(_hw) container_of(_hw, struct davinci_psc_clk, hw)
> +
> +static void psc_config(struct davinci_psc_clk *psc,
> +		       enum davinci_psc_state next_state)
> +{
> +	u32 epcpr, pdstat, mdstat, mdctl, ptstat;
> +
> +	mdctl = next_state;
> +	if (psc->flags & LPSC_FORCE)
> +		mdctl |= MDCTL_FORCE;
> +	regmap_write_bits(psc->regmap, MDCTL(psc->lpsc), MDSTAT_STATE_MASK,
> +			  mdctl);

Wont this ignore the MDCTL_FORCE bit since MDSTAT_STATE_MASK does not
cover that?

> +
> +	regmap_read(psc->regmap, PDSTAT(psc->pd), &pdstat);
> +	if ((pdstat & PDSTAT_STATE_MASK) == 0) {
> +		regmap_write_bits(psc->regmap, PDSTAT(psc->pd),
> +				  PDSTAT_STATE_MASK, PDCTL_NEXT);

Shouldn't this be a write to PDCTL register?

> +
> +		regmap_write(psc->regmap, PTCMD, BIT(psc->pd));
> +
> +		regmap_read_poll_timeout(psc->regmap, EPCPR, epcpr,
> +					 epcpr & BIT(psc->pd), 0, 0);
> +
> +		regmap_write_bits(psc->regmap, PDCTL(psc->pd), PDCTL_EPCGOOD,
> +				  PDCTL_EPCGOOD);
> +	} else {
> +		regmap_write(psc->regmap, PTCMD, BIT(psc->pd));
> +	}
> +
> +	regmap_read_poll_timeout(psc->regmap, PTSTAT, ptstat,
> +				 !(ptstat & BIT(psc->pd)), 0, 0);
> +
> +	regmap_read_poll_timeout(psc->regmap, MDSTAT(psc->lpsc), mdstat,
> +				 (mdstat & MDSTAT_STATE_MASK) == next_state,
> +				 0, 0);
> +}
> +

[...]

> +
> +/**
> + * davinci_psc_clk_register - register psc clock
> + * @dev: device that is registering this clock

No dev parameter below.

> + * @name: name of this clock
> + * @parent_name: name of clock's parent
> + * @regmap: PSC MMIO region
> + * @lpsc: local PSC number
> + * @pd: power domain
> + * @flags: LPSC_* flags
> + */
> +static struct clk *davinci_psc_clk_register(const char *name,
> +					    const char *parent_name,
> +					    struct regmap *regmap,
> +					    u32 lpsc, u32 pd, u32 flags)
> +{
> +	struct clk_init_data init;
> +	struct davinci_psc_clk *psc;
> +	struct clk *clk;
> +
> +	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
> +	if (!psc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = &davinci_psc_clk_ops;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +	init.flags = CLK_SET_RATE_PARENT;

Is this needed since PSC does not cause any rate change?

> +
> +	if (flags & LPSC_ALWAYS_ENABLED)
> +		init.flags |= CLK_IS_CRITICAL;
> +
> +	psc->regmap = regmap;
> +	psc->hw.init = &init;
> +	psc->lpsc = lpsc;
> +	psc->pd = pd;
> +	psc->flags = flags;
> +
> +	clk = clk_register(NULL, &psc->hw);
> +	if (IS_ERR(clk))
> +		kfree(psc);
> +
> +	return clk;
> +}
> +
> +/*
> + * FIXME: This needs to be converted to a reset controller. But, the reset
> + * framework is currently device tree only.

Yeah, I see that __reset_control_get() fails with -EINVAL if there is no
of_node.

> + */
> +
> +static int davinci_psc_clk_reset(struct davinci_psc_clk *psc, bool reset)
> +{
> +	u32 mdctl;
> +
> +	if (IS_ERR_OR_NULL(psc))
> +		return -EINVAL;
> +
> +	mdctl = reset ? 0 : MDCTL_LRESET;
> +	regmap_write_bits(psc->regmap, MDCTL(psc->lpsc), MDCTL_LRESET, mdctl);
> +
> +	return 0;
> +}
> +
> +int davinci_clk_reset_assert(struct clk *clk)
> +{
> +	struct davinci_psc_clk *psc = to_davinci_psc_clk(__clk_get_hw(clk));
> +
> +	return davinci_psc_clk_reset(psc, true);
> +}
> +EXPORT_SYMBOL(davinci_clk_reset_assert);
> +
> +int davinci_clk_reset_deassert(struct clk *clk)
> +{
> +	struct davinci_psc_clk *psc = to_davinci_psc_clk(__clk_get_hw(clk));
> +
> +	return davinci_psc_clk_reset(psc, false);
> +}
> +EXPORT_SYMBOL(davinci_clk_reset_deassert);
> +

[...]

> diff --git a/drivers/clk/davinci/psc.h b/drivers/clk/davinci/psc.h
> new file mode 100644
> index 0000000..6022f6e
> --- /dev/null
> +++ b/drivers/clk/davinci/psc.h
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Clock driver for TI Davinci PSC controllers
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
> + */
> +
> +#ifndef __CLK_DAVINCI_PSC_H__
> +#define __CLK_DAVINCI_PSC_H__
> +
> +#include <linux/types.h>
> +
> +/* PSC quirk flags */
> +#define LPSC_ALWAYS_ENABLED	BIT(1) /* never disable this clock */
> +#define LPSC_FORCE		BIT(2) /* requires MDCTL FORCE bit */
> +#define LPSC_LOCAL_RESET	BIT(3) /* acts as reset provider */
> +
> +struct clk_onecell_data;

Rather clk-provider.h should be included in this file?

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 1:38 p.m. UTC | #17
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PSC clocks on TI DA830/
> OMAP-L137/AM17XX SoCs.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  drivers/clk/davinci/Makefile    |  1 +
>  drivers/clk/davinci/psc-da830.c | 96 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk/davinci.h     |  2 +
>  3 files changed, 99 insertions(+)
>  create mode 100644 drivers/clk/davinci/psc-da830.c
> 
> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
> index cd1bf2c..fb14c8c 100644
> --- a/drivers/clk/davinci/Makefile
> +++ b/drivers/clk/davinci/Makefile
> @@ -10,4 +10,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DM644x)	+= pll-dm644x.o
>  obj-$(CONFIG_ARCH_DAVINCI_DM646x)	+= pll-dm646x.o
>  
>  obj-y += psc.o
> +obj-$(CONFIG_ARCH_DAVINCI_DA830)	+= psc-da830.o
>  endif
> diff --git a/drivers/clk/davinci/psc-da830.c b/drivers/clk/davinci/psc-da830.c
> new file mode 100644
> index 0000000..193b08f
> --- /dev/null
> +++ b/drivers/clk/davinci/psc-da830.c
> @@ -0,0 +1,96 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PSC clock descriptions for TI DA830/OMAP-L137/AM17XX
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/init.h>
> +#include <linux/types.h>
> +
> +#include "psc.h"
> +
> +static const struct davinci_psc_clk_info da830_psc0_info[] __initconst = {
> +	LPSC(0, 0, tpcc, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
> +	LPSC(4, 0, spi0, pll0_sysclk2, 0),
> +	LPSC(5, 0, mmcsd, pll0_sysclk2, 0),
> +	LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
> +	LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(8, 0, secu_mgr, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
> +	LPSC(9, 0, uart0, pll0_sysclk2, 0),
> +	LPSC(10, 0, scr0_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(11, 0, scr1_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(12, 0, scr2_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +	LPSC(13, 0, dmax, pll0_sysclk2, LPSC_ALWAYS_ENABLED),

pruss is better (I know the name is coming from existing code).

> +	LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),

This is LPSC 15 which controls DSP too. But its missing from existing
code. Not sure why. Probably a note for future. For now okay with
ignoring it.

> +	{ }
> +};

Tables like these are much easier to parse if columns are spaced using a
tab.

> +
> +static const struct davinci_psc_clk_info da830_psc1_info[] __initconst = {
> +	LPSC(1, 0, usb0, pll0_sysclk2, 0),
> +	LPSC(2, 0, usb1, pll0_sysclk4, 0),
> +	LPSC(3, 0, gpio, pll0_sysclk4, 0),

There is LPSC 4 controlling UHPI. Again, lets ignore for now.

> +	LPSC(5, 0, emac, pll0_sysclk4, 0),
> +	LPSC(6, 0, emif3, pll0_sysclk5, LPSC_ALWAYS_ENABLED),
> +	LPSC(7, 0, mcasp0, pll0_sysclk2, 0),
> +	LPSC(8, 0, mcasp1, pll0_sysclk2, 0),
> +	LPSC(9, 0, mcasp2, pll0_sysclk2, 0),
> +	LPSC(10, 0, spi1, pll0_sysclk2, 0),
> +	LPSC(11, 0, i2c1, pll0_sysclk4, 0),
> +	LPSC(12, 0, uart1, pll0_sysclk2, 0),
> +	LPSC(13, 0, uart2, pll0_sysclk2, 0),
> +	LPSC(16, 0, lcdc, pll0_sysclk2, 0),
> +	LPSC(17, 0, pwm, pll0_sysclk2, 0),
> +	LPSC(20, 0, ecap, pll0_sysclk2, 0),
> +	LPSC(21, 0, eqep, pll0_sysclk2, 0),
> +	{ }
> +};
> +
> +void __init da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
> +{
> +	struct clk_onecell_data *clk_data;
> +
> +	clk_data = davinci_psc_register_clocks(psc0, da830_psc0_info, 16);
> +	if (!clk_data)
> +		return;
> +
> +	clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
> +	clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
> +	clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
> +	clk_register_clkdev(clk_data->clks[14], "arm", NULL);
> +
> +	clk_free_onecell_data(clk_data);
> +
> +	clk_data = davinci_psc_register_clocks(psc1, da830_psc1_info, 32);
> +	if (!clk_data)
> +		return;
> +
> +	clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
> +	clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
> +	clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
> +	clk_register_clkdev(clk_data->clks[3], "gpio", NULL);

This is pretty bad (and no fault of yours) - having a con_id but no
device name. Can you please make a pre-series which passes NULL con_id
in gpio-davinci.c?

> +	clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
> +	clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
> +	clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
> +	clk_register_clkdev(clk_data->clks[8], NULL, "davinci-mcasp.1");
> +	clk_register_clkdev(clk_data->clks[9], NULL, "davinci-mcasp.2");
> +	clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
> +	clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
> +	clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
> +	clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
> +	clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
> +	clk_register_clkdev(clk_data->clks[21], NULL, "eqep.0");
> +	clk_register_clkdev(clk_data->clks[21], NULL, "eqep.1");

This is going to be very difficult to audit for mistakes. How do you
feel about adding the con_id and dev_id to davinci_psc_clk_info[] so
they can be initialized as part of a single static table? And then here
you go over the table looking for non-NULL con_id/dev_id to call
clk_register_clkdev()?

I am guessing you did not take that route because the DT path does not
need those. But still, I think that will be much less error prone.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 2 p.m. UTC | #18
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
> +{
> +	struct clk_onecell_data *clk_data;
> +
> +	clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
> +	if (!clk_data)
> +		return;
> +
> +	clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
> +	clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
> +	clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
> +	clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
> +	clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
> +	clk_register_clkdev(clk_data->clks[14], "arm", NULL);
> +	clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
> +
> +	clk_free_onecell_data(clk_data);
> +
> +	clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
> +	if (!clk_data)
> +		return;
> +
> +	clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);

Is this con_id really needed now? Searching for "usb20_psc_clk" in your
tree results in only this one hit.

> +	clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
> +	clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");

I guess multiple dev_id matches like these are another hurdle in moving
them to davinci_psc_clk_info[] table? If its too cumbersome to keep
multiple entries in the table, they can be handled as an exception at
the end of processing the table? Still they are not the norm so I hope
the normal case will still benefit.

> +	clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
> +	clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
> +	clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
> +	clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
> +	clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
> +	clk_register_clkdev(clk_data->clks[8], "fck", "ahci_da850");
> +	clk_register_clkdev(clk_data->clks[9], NULL, "vpif");
> +	clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
> +	clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
> +	clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
> +	clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
> +	clk_register_clkdev(clk_data->clks[14], NULL, "davinci-mcbsp.0");
> +	clk_register_clkdev(clk_data->clks[15], NULL, "davinci-mcbsp.1");
> +	clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
> +	clk_register_clkdev(clk_data->clks[18], NULL, "da830-mmc.1");
> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
> +
> +	clk_free_onecell_data(clk_data);
> +}

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 2:15 p.m. UTC | #19
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PSC clocks on TI
> DaVinci 355 based systems.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Apart from some comments on other patches that apply to this too, I have
no new comments.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 16, 2018, 2:16 p.m. UTC | #20
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PSC clocks on TI
> DaVinci 365 based systems.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Apart from some comments on other patches that apply to this too, I have
no new comments.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 16, 2018, 4:51 p.m. UTC | #21
On 01/16/2018 05:03 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds a new driver for mach-davinci PSC clocks. This is porting the
>> code from arch/arm/mach-davinci/psc.c to the common clock framework and
>> is converting it to use regmap to simplify the code. Additionally, it adds
>> device tree support for these clocks.
>>
>> Note: although there are similar clocks for TI Keystone we are not able
>> to share the code for a few reasons. The keystone clocks are device tree
>> only and use legacy one-node-per-clock bindings. Also the keystone driver
>> makes the assumption that there is only one PSC per SoC and uses global
>> variables, but here we have two controllers per SoC.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---

>> +static void psc_config(struct davinci_psc_clk *psc,
>> +		       enum davinci_psc_state next_state)
>> +{
>> +	u32 epcpr, pdstat, mdstat, mdctl, ptstat;
>> +
>> +	mdctl = next_state;
>> +	if (psc->flags & LPSC_FORCE)
>> +		mdctl |= MDCTL_FORCE;
>> +	regmap_write_bits(psc->regmap, MDCTL(psc->lpsc), MDSTAT_STATE_MASK,
>> +			  mdctl);
> 
> Wont this ignore the MDCTL_FORCE bit since MDSTAT_STATE_MASK does not
> cover that?
> 
>> +
>> +	regmap_read(psc->regmap, PDSTAT(psc->pd), &pdstat);
>> +	if ((pdstat & PDSTAT_STATE_MASK) == 0) {
>> +		regmap_write_bits(psc->regmap, PDSTAT(psc->pd),
>> +				  PDSTAT_STATE_MASK, PDCTL_NEXT);
> 
> Shouldn't this be a write to PDCTL register?
> 

Looks like I have some mistakes here. Thank you.

...

>> +static struct clk *davinci_psc_clk_register(const char *name,
>> +					    const char *parent_name,
>> +					    struct regmap *regmap,
>> +					    u32 lpsc, u32 pd, u32 flags)
>> +{
>> +	struct clk_init_data init;
>> +	struct davinci_psc_clk *psc;
>> +	struct clk *clk;
>> +
>> +	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
>> +	if (!psc)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	init.name = name;
>> +	init.ops = &davinci_psc_clk_ops;
>> +	init.parent_names = (parent_name ? &parent_name : NULL);
>> +	init.num_parents = (parent_name ? 1 : 0);
>> +	init.flags = CLK_SET_RATE_PARENT;
> 
> Is this needed since PSC does not cause any rate change?

Yes, because one of the PSCs is the ARM clock and for cpufreq, we
need to propagate the rate change up the chain to SYSCLK6.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 16, 2018, 5:16 p.m. UTC | #22
On 01/16/2018 07:38 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds platform-specific declarations for the PSC clocks on TI DA830/
>> OMAP-L137/AM17XX SoCs.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>>   drivers/clk/davinci/Makefile    |  1 +
>>   drivers/clk/davinci/psc-da830.c | 96 +++++++++++++++++++++++++++++++++++++++++
>>   include/linux/clk/davinci.h     |  2 +
>>   3 files changed, 99 insertions(+)
>>   create mode 100644 drivers/clk/davinci/psc-da830.c
>>
>> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
>> index cd1bf2c..fb14c8c 100644
>> --- a/drivers/clk/davinci/Makefile
>> +++ b/drivers/clk/davinci/Makefile
>> @@ -10,4 +10,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DM644x)	+= pll-dm644x.o
>>   obj-$(CONFIG_ARCH_DAVINCI_DM646x)	+= pll-dm646x.o
>>   
>>   obj-y += psc.o
>> +obj-$(CONFIG_ARCH_DAVINCI_DA830)	+= psc-da830.o
>>   endif
>> diff --git a/drivers/clk/davinci/psc-da830.c b/drivers/clk/davinci/psc-da830.c
>> new file mode 100644
>> index 0000000..193b08f
>> --- /dev/null
>> +++ b/drivers/clk/davinci/psc-da830.c
>> @@ -0,0 +1,96 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * PSC clock descriptions for TI DA830/OMAP-L137/AM17XX
>> + *
>> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/init.h>
>> +#include <linux/types.h>
>> +
>> +#include "psc.h"
>> +
>> +static const struct davinci_psc_clk_info da830_psc0_info[] __initconst = {
>> +	LPSC(0, 0, tpcc, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
>> +	LPSC(4, 0, spi0, pll0_sysclk2, 0),
>> +	LPSC(5, 0, mmcsd, pll0_sysclk2, 0),
>> +	LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>> +	LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(8, 0, secu_mgr, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>> +	LPSC(9, 0, uart0, pll0_sysclk2, 0),
>> +	LPSC(10, 0, scr0_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(11, 0, scr1_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(12, 0, scr2_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +	LPSC(13, 0, dmax, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> 
> pruss is better (I know the name is coming from existing code).
> 
>> +	LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
> 
> This is LPSC 15 which controls DSP too. But its missing from existing
> code. Not sure why. Probably a note for future. For now okay with
> ignoring it.
> 
>> +	{ }
>> +};
> 
> Tables like these are much easier to parse if columns are spaced using a
> tab.
> 

Tabs make the lines over 80 columns. How about spaces instead?


>> +
>> +static const struct davinci_psc_clk_info da830_psc1_info[] __initconst = {
>> +	LPSC(1, 0, usb0, pll0_sysclk2, 0),
>> +	LPSC(2, 0, usb1, pll0_sysclk4, 0),
>> +	LPSC(3, 0, gpio, pll0_sysclk4, 0),
> 
> There is LPSC 4 controlling UHPI. Again, lets ignore for now.
> 
>> +	LPSC(5, 0, emac, pll0_sysclk4, 0),
>> +	LPSC(6, 0, emif3, pll0_sysclk5, LPSC_ALWAYS_ENABLED),
>> +	LPSC(7, 0, mcasp0, pll0_sysclk2, 0),
>> +	LPSC(8, 0, mcasp1, pll0_sysclk2, 0),
>> +	LPSC(9, 0, mcasp2, pll0_sysclk2, 0),
>> +	LPSC(10, 0, spi1, pll0_sysclk2, 0),
>> +	LPSC(11, 0, i2c1, pll0_sysclk4, 0),
>> +	LPSC(12, 0, uart1, pll0_sysclk2, 0),
>> +	LPSC(13, 0, uart2, pll0_sysclk2, 0),
>> +	LPSC(16, 0, lcdc, pll0_sysclk2, 0),
>> +	LPSC(17, 0, pwm, pll0_sysclk2, 0),
>> +	LPSC(20, 0, ecap, pll0_sysclk2, 0),
>> +	LPSC(21, 0, eqep, pll0_sysclk2, 0),
>> +	{ }
>> +};
>> +
>> +void __init da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>> +{
>> +	struct clk_onecell_data *clk_data;
>> +
>> +	clk_data = davinci_psc_register_clocks(psc0, da830_psc0_info, 16);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>> +	clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>> +	clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>> +	clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>> +
>> +	clk_free_onecell_data(clk_data);
>> +
>> +	clk_data = davinci_psc_register_clocks(psc1, da830_psc1_info, 32);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>> +	clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>> +	clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
>> +	clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
> 
> This is pretty bad (and no fault of yours) - having a con_id but no
> device name. Can you please make a pre-series which passes NULL con_id
> in gpio-davinci.c?

I'll give it a try. This is complicated by the fact that the con_id has
made it's way into the device tree bindings. However, I think we can
safely deprecate clock-names = "gpio" in the device tree bindings since
we can make the driver ignore that property to preserve backwards
compatibility.

> 
>> +	clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
>> +	clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
>> +	clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
>> +	clk_register_clkdev(clk_data->clks[8], NULL, "davinci-mcasp.1");
>> +	clk_register_clkdev(clk_data->clks[9], NULL, "davinci-mcasp.2");
>> +	clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
>> +	clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
>> +	clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
>> +	clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
>> +	clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
>> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
>> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
>> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
>> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
>> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
>> +	clk_register_clkdev(clk_data->clks[21], NULL, "eqep.0");
>> +	clk_register_clkdev(clk_data->clks[21], NULL, "eqep.1");
> 
> This is going to be very difficult to audit for mistakes. How do you
> feel about adding the con_id and dev_id to davinci_psc_clk_info[] so
> they can be initialized as part of a single static table? And then here
> you go over the table looking for non-NULL con_id/dev_id to call
> clk_register_clkdev()?
> 
> I am guessing you did not take that route because the DT path does not
> need those. But still, I think that will be much less error prone.

I wasn't really happy with this either, but I haven't come up with
anything better. The reason I think this is good enough is that the
array index is the LPSC number, so it is not actually that hard to
audit. You can use the clock declarations above (or the datasheet/
TRM) to know exactly which clock you are dealing with by matching
the array index. I considered using macros instead of the numbers,
but then lines are over 80 columns and it gets hard to read with
wrapped lines.

Any other solution will be much more verbose and require helper
functions for looping through the clocks. I'm thinking that I would
define a list of con_id, dev_id pairs for each clock, so that would
be 15 extra static arrays here.

I'll think about it a little more, but for now, I would like to push
for just calling this "good enough" and leave it as-is.



--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 16, 2018, 5:21 p.m. UTC | #23
On 01/16/2018 08:00 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>> +{
>> +	struct clk_onecell_data *clk_data;
>> +
>> +	clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
>> +	clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
>> +	clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>> +	clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>> +	clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>> +	clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>> +	clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
>> +
>> +	clk_free_onecell_data(clk_data);
>> +
>> +	clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
>> +	if (!clk_data)
>> +		return;
>> +
>> +	clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
> 
> Is this con_id really needed now? Searching for "usb20_psc_clk" in your
> tree results in only this one hit.

Yes, this is left over from previous attempts.

> 
>> +	clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>> +	clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
> 
> I guess multiple dev_id matches like these are another hurdle in moving
> them to davinci_psc_clk_info[] table? If its too cumbersome to keep
> multiple entries in the table, they can be handled as an exception at
> the end of processing the table? Still they are not the norm so I hope
> the normal case will still benefit.

Right, as I mentioned in the reply to the previous patch, instead of
assigning a con_id and dev_id to each clock, we would need to assign
an array with a list of clocks. I think that would work better than
trying to handle the extras as an exception since there, on average,
about 5 per SoC.

> 
>> +	clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
>> +	clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
>> +	clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
>> +	clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
>> +	clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
>> +	clk_register_clkdev(clk_data->clks[8], "fck", "ahci_da850");
>> +	clk_register_clkdev(clk_data->clks[9], NULL, "vpif");
>> +	clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
>> +	clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
>> +	clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
>> +	clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
>> +	clk_register_clkdev(clk_data->clks[14], NULL, "davinci-mcbsp.0");
>> +	clk_register_clkdev(clk_data->clks[15], NULL, "davinci-mcbsp.1");
>> +	clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
>> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
>> +	clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
>> +	clk_register_clkdev(clk_data->clks[18], NULL, "da830-mmc.1");
>> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
>> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
>> +	clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
>> +
>> +	clk_free_onecell_data(clk_data);
>> +}
> 
> Thanks,
> Sekhar
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 17, 2018, 11:57 a.m. UTC | #24
On Tuesday 16 January 2018 10:51 PM, David Lechner wrote:
> On 01/16/2018 08:00 AM, Sekhar Nori wrote:
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>>> +{
>>> +    struct clk_onecell_data *clk_data;
>>> +
>>> +    clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
>>> +    if (!clk_data)
>>> +        return;
>>> +
>>> +    clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
>>> +    clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
>>> +    clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>>> +    clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>>> +    clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>>> +    clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>>> +    clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
>>> +
>>> +    clk_free_onecell_data(clk_data);
>>> +
>>> +    clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
>>> +    if (!clk_data)
>>> +        return;
>>> +
>>> +    clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
>>
>> Is this con_id really needed now? Searching for "usb20_psc_clk" in your
>> tree results in only this one hit.
> 
> Yes, this is left over from previous attempts.
> 
>>
>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>>
>> I guess multiple dev_id matches like these are another hurdle in moving
>> them to davinci_psc_clk_info[] table? If its too cumbersome to keep
>> multiple entries in the table, they can be handled as an exception at
>> the end of processing the table? Still they are not the norm so I hope
>> the normal case will still benefit.
> 
> Right, as I mentioned in the reply to the previous patch, instead of
> assigning a con_id and dev_id to each clock, we would need to assign
> an array with a list of clocks. I think that would work better than
> trying to handle the extras as an exception since there, on average,
> about 5 per SoC.

Okay, are you going to try this to see how it looks? It looks like
samsung (clk-s3c2410.c) and tegra (clk-tegra20.c) use such tables
(although both use separate tables mapping just the gate number to
con_id/dev_id).

Others like u8540_clk.c and clk-mmp2.c have multiple calls in code to
clk_register_clkdev() like you have, but they keep them right after the
gate clock registration which makes it easy to see the mapping.

clk-imx35.c has multiple clk_register_clkdev() calls, but uses an enum
for the gates so its easy to see the mapping. This approach looks fine
to me as well.

So looks like there is a whole gamut of ways people have approached
this. But I do think we need to change the scheme you have currently
since it is difficult to review and audit (believe me on this one :))

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 17, 2018, 12:18 p.m. UTC | #25
On Tuesday 16 January 2018 10:46 PM, David Lechner wrote:

>>> +static const struct davinci_psc_clk_info da830_psc0_info[]
>>> __initconst = {
>>> +    LPSC(0, 0, tpcc, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(4, 0, spi0, pll0_sysclk2, 0),
>>> +    LPSC(5, 0, mmcsd, pll0_sysclk2, 0),
>>> +    LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(8, 0, secu_mgr, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(9, 0, uart0, pll0_sysclk2, 0),
>>> +    LPSC(10, 0, scr0_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(11, 0, scr1_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(12, 0, scr2_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +    LPSC(13, 0, dmax, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>
>> pruss is better (I know the name is coming from existing code).
>>
>>> +    LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
>>
>> This is LPSC 15 which controls DSP too. But its missing from existing
>> code. Not sure why. Probably a note for future. For now okay with
>> ignoring it.
>>
>>> +    { }
>>> +};
>>
>> Tables like these are much easier to parse if columns are spaced using a
>> tab.
>>
> 
> Tabs make the lines over 80 columns. How about spaces instead?

That works for me. I guess checkpatch will complain, but hopefully
maintainers will agree on the exception.

>>> +void __init da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>>> +{
>>> +    struct clk_onecell_data *clk_data;
>>> +
>>> +    clk_data = davinci_psc_register_clocks(psc0, da830_psc0_info, 16);
>>> +    if (!clk_data)
>>> +        return;
>>> +
>>> +    clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>>> +    clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>>> +    clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>>> +    clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>>> +
>>> +    clk_free_onecell_data(clk_data);
>>> +
>>> +    clk_data = davinci_psc_register_clocks(psc1, da830_psc1_info, 32);
>>> +    if (!clk_data)
>>> +        return;
>>> +
>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>>> +    clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
>>> +    clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
>>
>> This is pretty bad (and no fault of yours) - having a con_id but no
>> device name. Can you please make a pre-series which passes NULL con_id
>> in gpio-davinci.c?
> 
> I'll give it a try. This is complicated by the fact that the con_id has
> made it's way into the device tree bindings. However, I think we can
> safely deprecate clock-names = "gpio" in the device tree bindings since
> we can make the driver ignore that property to preserve backwards
> compatibility.

I don't think this breaks DT-backward compatibility. Passing a NULL
con_id in driver should find the clock for that device even if DT entry
has clock-names present. As far as I can read clk_find().

The less intrusive alternate is to add the GPIO device name in the table
here, while keeping the con_id and keeping the driver untouched. The
advantage of that is lesser number of dependent patches for this series
to go in.

Later once CCF conversion has been there in the kernel for one full
release and no regressions, these other clean-ups can be done.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 17, 2018, 12:25 p.m. UTC | #26
On Tuesday 16 January 2018 10:21 PM, David Lechner wrote:

>>> +static struct clk *davinci_psc_clk_register(const char *name,
>>> +                        const char *parent_name,
>>> +                        struct regmap *regmap,
>>> +                        u32 lpsc, u32 pd, u32 flags)
>>> +{
>>> +    struct clk_init_data init;
>>> +    struct davinci_psc_clk *psc;
>>> +    struct clk *clk;
>>> +
>>> +    psc = kzalloc(sizeof(*psc), GFP_KERNEL);
>>> +    if (!psc)
>>> +        return ERR_PTR(-ENOMEM);
>>> +
>>> +    init.name = name;
>>> +    init.ops = &davinci_psc_clk_ops;
>>> +    init.parent_names = (parent_name ? &parent_name : NULL);
>>> +    init.num_parents = (parent_name ? 1 : 0);
>>> +    init.flags = CLK_SET_RATE_PARENT;
>>
>> Is this needed since PSC does not cause any rate change?
> 
> Yes, because one of the PSCs is the ARM clock and for cpufreq, we
> need to propagate the rate change up the chain to SYSCLK6.

Good point. But how about treating that as an exception with a new LPSC_
quirk flag?

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 17, 2018, 1:57 p.m. UTC | #27
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds platform-specific declarations for the PSC clocks on TI
> DaVinci 644x based systems.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Looks good to me except comments I already gave for similar patches.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 17, 2018, 2:59 p.m. UTC | #28
On Monday 08 January 2018 07:47 AM, David Lechner wrote:

> +void __init dm646x_psc_clk_init(void __iomem *psc)
> +{
> +	struct clk_onecell_data *clk_data;
> +
> +	clk_data = davinci_psc_register_clocks(psc, dm646x_psc_info, 41);
> +	if (!clk_data)
> +		return;
> +
> +	clk_register_clkdev(clk_data->clks[0], "arm", NULL);

I don't think this "arm" con_id is used any where for non-DA850 SoCs.
And same with "dsp" in other files. Probably best to drop these dubious
usage ones rather than carry them forward.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 17, 2018, 3:31 p.m. UTC | #29
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new driver for the gate and multiplexer clocks in the
> CFGCHIPn syscon registers on TI DA8XX-type SoCs.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  drivers/clk/davinci/Makefile        |   2 +
>  drivers/clk/davinci/da8xx-cfgchip.c | 203 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 205 insertions(+)
>  create mode 100644 drivers/clk/davinci/da8xx-cfgchip.c
> 
> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
> index 6c388d4..11178b7 100644
> --- a/drivers/clk/davinci/Makefile
> +++ b/drivers/clk/davinci/Makefile
> @@ -1,6 +1,8 @@
>  # SPDX-License-Identifier: GPL-2.0
>  
>  ifeq ($(CONFIG_COMMON_CLK), y)
> +obj-$(CONFIG_ARCH_DAVINCI_DA8XX)	+= da8xx-cfgchip.o
> +
>  obj-y += pll.o
>  obj-$(CONFIG_ARCH_DAVINCI_DA830)	+= pll-da830.o
>  obj-$(CONFIG_ARCH_DAVINCI_DA850)	+= pll-da850.o
> diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c
> new file mode 100644
> index 0000000..772e09a
> --- /dev/null
> +++ b/drivers/clk/davinci/da8xx-cfgchip.c
> @@ -0,0 +1,203 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Clock driver for DA8xx/AM17xx/AM18xx/OMAP-L13x CFGCHIP
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>

2018

> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/mfd/da8xx-cfgchip.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +#ifdef CONFIG_OF

Is this ifdef really needed, or included to save space for non-OF
builds? I think it can be removed if not really needed.

> +static void da8xx_cfgchip_gate_clk_init(struct device_node *np, u32 reg,
> +					u32 mask)
> +{
> +	struct da8xx_cfgchip_gate_clk *clk;
> +	struct clk_init_data init;
> +	const char *name = np->name;
> +	const char *parent_name;
> +	struct regmap *regmap;
> +	int ret;
> +
> +	of_property_read_string(np, "clock-output-names", &name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +
> +	regmap = syscon_node_to_regmap(of_get_parent(np));
> +	if (IS_ERR(regmap)) {
> +		pr_err("%s: no regmap for syscon parent of %s (%ld)\n",
> +		       __func__, np->full_name, PTR_ERR(regmap));

please use pr_fmt for this driver too.

> +static void da8xx_cfgchip_mux_clk_init(struct device_node *np, u32 reg,
> +				       u32 mask)
> +{
> +	struct da8xx_cfgchip_mux_clk *clk;
> +	struct clk_init_data init;
> +	const char *name = np->name;
> +	const char *parent_names[2];
> +	struct regmap *regmap;
> +	int ret;
> +
> +	ret = of_property_match_string(np, "clock-names", "pll0_sysclk2");
> +	parent_names[0] = of_clk_get_parent_name(np, ret);
> +	if (!parent_names[0]) {
> +		pr_err("%s: missing pll0_sysclk2 clock\n", __func__);
> +		return;
> +	}
> +
> +	ret = of_property_match_string(np, "clock-names", "pll1_sysclk2");
> +	parent_names[1] = of_clk_get_parent_name(np, ret);
> +	if (!parent_names[1]) {
> +		pr_err("%s: missing pll1_sysclk2 clock\n", __func__);
> +		return;
> +	}

The fact that you are looking specifically for pll0_sysclk2 and
pll1_sysclk2 makes it really specific to async3 and the same function
cannot be used for something like EMIFA clock source. Can this part of
the function be factored out so rest of the function can still be reused
for another clock?

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 17, 2018, 5:28 p.m. UTC | #30
On 01/17/2018 06:25 AM, Sekhar Nori wrote:
> On Tuesday 16 January 2018 10:21 PM, David Lechner wrote:
> 
>>>> +static struct clk *davinci_psc_clk_register(const char *name,
>>>> +                        const char *parent_name,
>>>> +                        struct regmap *regmap,
>>>> +                        u32 lpsc, u32 pd, u32 flags)
>>>> +{
>>>> +    struct clk_init_data init;
>>>> +    struct davinci_psc_clk *psc;
>>>> +    struct clk *clk;
>>>> +
>>>> +    psc = kzalloc(sizeof(*psc), GFP_KERNEL);
>>>> +    if (!psc)
>>>> +        return ERR_PTR(-ENOMEM);
>>>> +
>>>> +    init.name = name;
>>>> +    init.ops = &davinci_psc_clk_ops;
>>>> +    init.parent_names = (parent_name ? &parent_name : NULL);
>>>> +    init.num_parents = (parent_name ? 1 : 0);
>>>> +    init.flags = CLK_SET_RATE_PARENT;
>>>
>>> Is this needed since PSC does not cause any rate change?
>>
>> Yes, because one of the PSCs is the ARM clock and for cpufreq, we
>> need to propagate the rate change up the chain to SYSCLK6.
> 
> Good point. But how about treating that as an exception with a new LPSC_
> quirk flag?

Sure.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 17, 2018, 5:32 p.m. UTC | #31
On 01/17/2018 06:18 AM, Sekhar Nori wrote:
> On Tuesday 16 January 2018 10:46 PM, David Lechner wrote:
> 
>>>> +static const struct davinci_psc_clk_info da830_psc0_info[]
>>>> __initconst = {
>>>> +    LPSC(0, 0, tpcc, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(4, 0, spi0, pll0_sysclk2, 0),
>>>> +    LPSC(5, 0, mmcsd, pll0_sysclk2, 0),
>>>> +    LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(8, 0, secu_mgr, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(9, 0, uart0, pll0_sysclk2, 0),
>>>> +    LPSC(10, 0, scr0_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(11, 0, scr1_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(12, 0, scr2_ss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>> +    LPSC(13, 0, dmax, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>>
>>> pruss is better (I know the name is coming from existing code).
>>>
>>>> +    LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
>>>
>>> This is LPSC 15 which controls DSP too. But its missing from existing
>>> code. Not sure why. Probably a note for future. For now okay with
>>> ignoring it.
>>>
>>>> +    { }
>>>> +};
>>>
>>> Tables like these are much easier to parse if columns are spaced using a
>>> tab.
>>>
>>
>> Tabs make the lines over 80 columns. How about spaces instead?
> 
> That works for me. I guess checkpatch will complain, but hopefully
> maintainers will agree on the exception.
> 
>>>> +void __init da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>>>> +{
>>>> +    struct clk_onecell_data *clk_data;
>>>> +
>>>> +    clk_data = davinci_psc_register_clocks(psc0, da830_psc0_info, 16);
>>>> +    if (!clk_data)
>>>> +        return;
>>>> +
>>>> +    clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>>>> +    clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>>>> +    clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>>>> +    clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>>>> +
>>>> +    clk_free_onecell_data(clk_data);
>>>> +
>>>> +    clk_data = davinci_psc_register_clocks(psc1, da830_psc1_info, 32);
>>>> +    if (!clk_data)
>>>> +        return;
>>>> +
>>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>>>> +    clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
>>>> +    clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
>>>
>>> This is pretty bad (and no fault of yours) - having a con_id but no
>>> device name. Can you please make a pre-series which passes NULL con_id
>>> in gpio-davinci.c?
>>
>> I'll give it a try. This is complicated by the fact that the con_id has
>> made it's way into the device tree bindings. However, I think we can
>> safely deprecate clock-names = "gpio" in the device tree bindings since
>> we can make the driver ignore that property to preserve backwards
>> compatibility.

Agreed.

> I don't think this breaks DT-backward compatibility. Passing a NULL
> con_id in driver should find the clock for that device even if DT entry
> has clock-names present. As far as I can read clk_find().
> 
> The less intrusive alternate is to add the GPIO device name in the table
> here, while keeping the con_id and keeping the driver untouched. The
> advantage of that is lesser number of dependent patches for this series
> to go in.
> 
> Later once CCF conversion has been there in the kernel for one full
> release and no regressions, these other clean-ups can be done.

I like this approach.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 17, 2018, 5:33 p.m. UTC | #32
On 01/17/2018 05:57 AM, Sekhar Nori wrote:
> On Tuesday 16 January 2018 10:51 PM, David Lechner wrote:
>> On 01/16/2018 08:00 AM, Sekhar Nori wrote:
>>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>>> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>>>> +{
>>>> +    struct clk_onecell_data *clk_data;
>>>> +
>>>> +    clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
>>>> +    if (!clk_data)
>>>> +        return;
>>>> +
>>>> +    clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
>>>> +    clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
>>>> +    clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>>>> +    clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>>>> +    clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>>>> +    clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>>>> +    clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
>>>> +
>>>> +    clk_free_onecell_data(clk_data);
>>>> +
>>>> +    clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
>>>> +    if (!clk_data)
>>>> +        return;
>>>> +
>>>> +    clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
>>>
>>> Is this con_id really needed now? Searching for "usb20_psc_clk" in your
>>> tree results in only this one hit.
>>
>> Yes, this is left over from previous attempts.
>>
>>>
>>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>>>
>>> I guess multiple dev_id matches like these are another hurdle in moving
>>> them to davinci_psc_clk_info[] table? If its too cumbersome to keep
>>> multiple entries in the table, they can be handled as an exception at
>>> the end of processing the table? Still they are not the norm so I hope
>>> the normal case will still benefit.
>>
>> Right, as I mentioned in the reply to the previous patch, instead of
>> assigning a con_id and dev_id to each clock, we would need to assign
>> an array with a list of clocks. I think that would work better than
>> trying to handle the extras as an exception since there, on average,
>> about 5 per SoC.
> 
> Okay, are you going to try this to see how it looks? It looks like
> samsung (clk-s3c2410.c) and tegra (clk-tegra20.c) use such tables
> (although both use separate tables mapping just the gate number to
> con_id/dev_id).
> 
> Others like u8540_clk.c and clk-mmp2.c have multiple calls in code to
> clk_register_clkdev() like you have, but they keep them right after the
> gate clock registration which makes it easy to see the mapping.
> 
> clk-imx35.c has multiple clk_register_clkdev() calls, but uses an enum
> for the gates so its easy to see the mapping. This approach looks fine
> to me as well.
> 
> So looks like there is a whole gamut of ways people have approached
> this. But I do think we need to change the scheme you have currently
> since it is difficult to review and audit (believe me on this one :))
> 

OK, I'll figure out something here.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 17, 2018, 5:35 p.m. UTC | #33
On 01/17/2018 09:31 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds a new driver for the gate and multiplexer clocks in the
>> CFGCHIPn syscon registers on TI DA8XX-type SoCs.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>>   drivers/clk/davinci/Makefile        |   2 +
>>   drivers/clk/davinci/da8xx-cfgchip.c | 203 ++++++++++++++++++++++++++++++++++++
>>   2 files changed, 205 insertions(+)
>>   create mode 100644 drivers/clk/davinci/da8xx-cfgchip.c
>>
>> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
>> index 6c388d4..11178b7 100644
>> --- a/drivers/clk/davinci/Makefile
>> +++ b/drivers/clk/davinci/Makefile
>> @@ -1,6 +1,8 @@
>>   # SPDX-License-Identifier: GPL-2.0
>>   
>>   ifeq ($(CONFIG_COMMON_CLK), y)
>> +obj-$(CONFIG_ARCH_DAVINCI_DA8XX)	+= da8xx-cfgchip.o
>> +
>>   obj-y += pll.o
>>   obj-$(CONFIG_ARCH_DAVINCI_DA830)	+= pll-da830.o
>>   obj-$(CONFIG_ARCH_DAVINCI_DA850)	+= pll-da850.o
>> diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c
>> new file mode 100644
>> index 0000000..772e09a
>> --- /dev/null
>> +++ b/drivers/clk/davinci/da8xx-cfgchip.c
>> @@ -0,0 +1,203 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Clock driver for DA8xx/AM17xx/AM18xx/OMAP-L13x CFGCHIP
>> + *
>> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
> 
> 2018
> 
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/mfd/da8xx-cfgchip.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/of.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +
>> +#ifdef CONFIG_OF
> 
> Is this ifdef really needed, or included to save space for non-OF
> builds? I think it can be removed if not really needed.
> 
>> +static void da8xx_cfgchip_gate_clk_init(struct device_node *np, u32 reg,
>> +					u32 mask)
>> +{
>> +	struct da8xx_cfgchip_gate_clk *clk;
>> +	struct clk_init_data init;
>> +	const char *name = np->name;
>> +	const char *parent_name;
>> +	struct regmap *regmap;
>> +	int ret;
>> +
>> +	of_property_read_string(np, "clock-output-names", &name);
>> +	parent_name = of_clk_get_parent_name(np, 0);
>> +
>> +	regmap = syscon_node_to_regmap(of_get_parent(np));
>> +	if (IS_ERR(regmap)) {
>> +		pr_err("%s: no regmap for syscon parent of %s (%ld)\n",
>> +		       __func__, np->full_name, PTR_ERR(regmap));
> 
> please use pr_fmt for this driver too.
> 
>> +static void da8xx_cfgchip_mux_clk_init(struct device_node *np, u32 reg,
>> +				       u32 mask)
>> +{
>> +	struct da8xx_cfgchip_mux_clk *clk;
>> +	struct clk_init_data init;
>> +	const char *name = np->name;
>> +	const char *parent_names[2];
>> +	struct regmap *regmap;
>> +	int ret;
>> +
>> +	ret = of_property_match_string(np, "clock-names", "pll0_sysclk2");
>> +	parent_names[0] = of_clk_get_parent_name(np, ret);
>> +	if (!parent_names[0]) {
>> +		pr_err("%s: missing pll0_sysclk2 clock\n", __func__);
>> +		return;
>> +	}
>> +
>> +	ret = of_property_match_string(np, "clock-names", "pll1_sysclk2");
>> +	parent_names[1] = of_clk_get_parent_name(np, ret);
>> +	if (!parent_names[1]) {
>> +		pr_err("%s: missing pll1_sysclk2 clock\n", __func__);
>> +		return;
>> +	}
> 
> The fact that you are looking specifically for pll0_sysclk2 and
> pll1_sysclk2 makes it really specific to async3 and the same function
> cannot be used for something like EMIFA clock source. Can this part of
> the function be factored out so rest of the function can still be reused
> for another clock?
> 

Already fixed this stuff a couple days ago. ;-)

And I went ahead and added the EMIFA clocks (the mux and the DIV4.5)


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 17, 2018, 7:08 p.m. UTC | #34
On 01/17/2018 05:57 AM, Sekhar Nori wrote:
> On Tuesday 16 January 2018 10:51 PM, David Lechner wrote:
>> On 01/16/2018 08:00 AM, Sekhar Nori wrote:
>>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>>> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>>>> +{
>>>> +    struct clk_onecell_data *clk_data;
>>>> +
>>>> +    clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
>>>> +    if (!clk_data)
>>>> +        return;
>>>> +
>>>> +    clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
>>>> +    clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
>>>> +    clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>>>> +    clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>>>> +    clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>>>> +    clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>>>> +    clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
>>>> +
>>>> +    clk_free_onecell_data(clk_data);
>>>> +
>>>> +    clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
>>>> +    if (!clk_data)
>>>> +        return;
>>>> +
>>>> +    clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
>>>
>>> Is this con_id really needed now? Searching for "usb20_psc_clk" in your
>>> tree results in only this one hit.
>>
>> Yes, this is left over from previous attempts.
>>
>>>
>>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>>>> +    clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>>>
>>> I guess multiple dev_id matches like these are another hurdle in moving
>>> them to davinci_psc_clk_info[] table? If its too cumbersome to keep
>>> multiple entries in the table, they can be handled as an exception at
>>> the end of processing the table? Still they are not the norm so I hope
>>> the normal case will still benefit.
>>
>> Right, as I mentioned in the reply to the previous patch, instead of
>> assigning a con_id and dev_id to each clock, we would need to assign
>> an array with a list of clocks. I think that would work better than
>> trying to handle the extras as an exception since there, on average,
>> about 5 per SoC.
> 
> Okay, are you going to try this to see how it looks?

It is looking like this:


static const struct davinci_psc_clkdev_info emfia_clkdev[] __initconst = {
	LPSC_CLKDEV(NULL,	"ti-aemif"),
	LPSC_CLKDEV("aemif",	"davinci-nand.0"),
	{ }
};

static const struct davinci_psc_clkdev_info spi0_clkdev[] __initconst = {
	LPSC_CLKDEV(NULL,	"spi_davinci.0"),
	{ }
};

static const struct davinci_psc_clkdev_info mmcsd0_clkdev[] __initconst = {
	LPSC_CLKDEV(NULL,	"da830-mmc.0"),
	{ }
};

static const struct davinci_psc_clkdev_info uart0_clkdev[] __initconst = {
	LPSC_CLKDEV(NULL,	"serial8250.0"),
	{ }
};

static const struct davinci_psc_clkdev_info arm_clkdev[] __initconst = {
	/*
	 * REVISIT: cpufreq-davinci should be modified to use dev_id and drop
	 * use of con_id.
	 */
	LPSC_CLKDEV("arm",	NULL),
	{ }
};

static const struct davinci_psc_clkdev_info dsp_clkdev[] __initconst = {
	LPSC_CLKDEV(NULL,	"davinci-rproc.0"),
	{ }
};

static const struct davinci_psc_clk_info da850_psc0_info[] __initconst = {
	LPSC(0,  0, tpcc0,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
	LPSC(1,  0, tptc0,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
	LPSC(2,  0, tptc1,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
	LPSC(3,  0, emifa,   async1,       emfia_clkdev,  0),
	LPSC(4,  0, spi0,    pll0_sysclk2, spi0_clkdev,   0),
	LPSC(5,  0, mmcsd0,  pll0_sysclk2, mmcsd0_clkdev, 0),
	LPSC(6,  0, aintc,   pll0_sysclk4, NULL,          LPSC_ALWAYS_ENABLED),
	LPSC(7,  0, arm_rom, pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
	LPSC(9,  0, uart0,   pll0_sysclk2, uart0_clkdev,  0),
	LPSC(13, 0, pruss,   pll0_sysclk2, NULL,          0),
	LPSC(14, 0, arm,     pll0_sysclk6, arm_clkdev,    LPSC_ALWAYS_ENABLED |
							  LPSC_ARM_RATE),
	LPSC(15, 1, dsp,     pll0_sysclk1, dsp_clkdev,    LPSC_FORCE |
							  LPSC_LOCAL_RESET),
	{ }
};
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 18, 2018, 6:37 a.m. UTC | #35
On Thursday 18 January 2018 12:38 AM, David Lechner wrote:
> It is looking like this:
> 
> 
> static const struct davinci_psc_clkdev_info emfia_clkdev[] __initconst = {
>     LPSC_CLKDEV(NULL,    "ti-aemif"),
>     LPSC_CLKDEV("aemif",    "davinci-nand.0"),
>     { }
> };
> 
> static const struct davinci_psc_clkdev_info spi0_clkdev[] __initconst = {
>     LPSC_CLKDEV(NULL,    "spi_davinci.0"),
>     { }
> };
> 
> static const struct davinci_psc_clkdev_info mmcsd0_clkdev[] __initconst = {
>     LPSC_CLKDEV(NULL,    "da830-mmc.0"),
>     { }
> };
> 
> static const struct davinci_psc_clkdev_info uart0_clkdev[] __initconst = {
>     LPSC_CLKDEV(NULL,    "serial8250.0"),
>     { }
> };
> 
> static const struct davinci_psc_clkdev_info arm_clkdev[] __initconst = {
>     /*
>      * REVISIT: cpufreq-davinci should be modified to use dev_id and drop
>      * use of con_id.
>      */
>     LPSC_CLKDEV("arm",    NULL),
>     { }
> };
> 
> static const struct davinci_psc_clkdev_info dsp_clkdev[] __initconst = {
>     LPSC_CLKDEV(NULL,    "davinci-rproc.0"),
>     { }
> };
> 
> static const struct davinci_psc_clk_info da850_psc0_info[] __initconst = {
>     LPSC(0,  0, tpcc0,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
>     LPSC(1,  0, tptc0,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
>     LPSC(2,  0, tptc1,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
>     LPSC(3,  0, emifa,   async1,       emfia_clkdev,  0),
>     LPSC(4,  0, spi0,    pll0_sysclk2, spi0_clkdev,   0),
>     LPSC(5,  0, mmcsd0,  pll0_sysclk2, mmcsd0_clkdev, 0),
>     LPSC(6,  0, aintc,   pll0_sysclk4, NULL,          LPSC_ALWAYS_ENABLED),
>     LPSC(7,  0, arm_rom, pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
>     LPSC(9,  0, uart0,   pll0_sysclk2, uart0_clkdev,  0),
>     LPSC(13, 0, pruss,   pll0_sysclk2, NULL,          0),
>     LPSC(14, 0, arm,     pll0_sysclk6, arm_clkdev,    LPSC_ALWAYS_ENABLED |
>                               LPSC_ARM_RATE),
>     LPSC(15, 1, dsp,     pll0_sysclk1, dsp_clkdev,    LPSC_FORCE |
>                               LPSC_LOCAL_RESET),
>     { }
> };

This looks good to me!

Regards,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 18, 2018, 7:53 a.m. UTC | #36
On Wednesday 17 January 2018 11:02 PM, David Lechner wrote:
>>>>> +    clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
>>>>
>>>> This is pretty bad (and no fault of yours) - having a con_id but no
>>>> device name. Can you please make a pre-series which passes NULL con_id
>>>> in gpio-davinci.c?
>>>
>>> I'll give it a try. This is complicated by the fact that the con_id has
>>> made it's way into the device tree bindings. However, I think we can
>>> safely deprecate clock-names = "gpio" in the device tree bindings since
>>> we can make the driver ignore that property to preserve backwards
>>> compatibility.
> 
> Agreed.
> 
>> I don't think this breaks DT-backward compatibility. Passing a NULL
>> con_id in driver should find the clock for that device even if DT entry
>> has clock-names present. As far as I can read clk_find().
>>
>> The less intrusive alternate is to add the GPIO device name in the table
>> here, while keeping the con_id and keeping the driver untouched. The
>> advantage of that is lesser number of dependent patches for this series
>> to go in.
>>
>> Later once CCF conversion has been there in the kernel for one full
>> release and no regressions, these other clean-ups can be done.
> 
> I like this approach.

One downside is that we will have to have clock-names = "gpio" in da850
device-tree too. Since its already present in keystone already, I don't
think adding one more is such a big issue.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 18, 2018, 1:05 p.m. UTC | #37
On Monday 08 January 2018 07:47 AM, David Lechner wrote:

> +static int da8xx_usb1_phy_clk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct da8xx_usb1_phy_clk *clk = to_da8xx_usb1_phy_clk(hw);
> +	unsigned int mask, val;
> +
> +	/* Set the USB 1.1 PHY clock mux based on the parent clock. */
> +	mask = CFGCHIP2_USB1PHYCLKMUX;
> +	switch (index) {
> +	case DA8XX_USB1_PHY_CLK_PARENT_USB_REFCLKIN:
> +		val = CFGCHIP2_USB1PHYCLKMUX;
> +		break;
> +	case DA8XX_USB1_PHY_CLK_PARENT_USB0_PHY_PLL:
> +		val = 0;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	regmap_write_bits(clk->regmap, CFGCHIP(2), mask, val);

This function can be simplified quite a bit if you use a shift.

#define CFGCHIP2_USB1PHYCLKMUX_SHIFT	12

static int da8xx_usb1_phy_clk_set_parent(struct clk_hw *hw, u8 index)
{
	struct da8xx_usb1_phy_clk *clk = to_da8xx_usb1_phy_clk(hw);

	regmap_write_bits(clk->regmap, CFGCHIP(2),
			  CFGCHIP2_USB1PHYCLKMUX,
			  index << CFGCHIP2_USB1PHYCLKMUX_SHIFT);
}

Same thing for da8xx_usb0_phy_clk_set_parent() as well.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 18, 2018, 3:14 p.m. UTC | #38
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> +int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
> +{
> +	struct regmap *cfgchip;
> +	struct clk *usb0_psc_clk, *clk;
> +	struct clk_hw *parent;
> +
> +	cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");

Am I right in understanding that this API is only called for non-DT
boot? If yes, do we really need the lookup by compatible?

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 18, 2018, 3:24 p.m. UTC | #39
On Monday 08 January 2018 07:47 AM, David Lechner wrote:

> +#ifndef CONFIG_COMMON_CLK
>  static int da850_set_armrate(struct clk *clk, unsigned long rate);
>  static int da850_round_armrate(struct clk *clk, unsigned long rate);
>  static int da850_set_pll0rate(struct clk *clk, unsigned long armrate);
> @@ -583,6 +588,7 @@ static struct clk_lookup da850_clks[] = {
>  	CLK("ecap.2",		"fck",		&ecap2_clk),
>  	CLK(NULL,		NULL,		NULL),
>  };
> +#endif

Don't like these temporary ifdefs (which I am sure is the case with you
too). But don't have any other good idea for splitting these patches
into review-able and build-able pieces. So lets go with this for now.

>  void __init da850_init_time(void)
>  {
> +#ifdef CONFIG_COMMON_CLK
> +	void __iomem *pll0, *pll1, *psc0, *psc1;
> +	struct clk *clk;
> +	struct clk_hw *parent;
> +
> +	pll0 = ioremap(DA8XX_PLL0_BASE, SZ_4K);
> +	pll1 = ioremap(DA850_PLL1_BASE, SZ_4K);
> +	psc0 = ioremap(DA8XX_PSC0_BASE, SZ_4K);
> +	psc1 = ioremap(DA8XX_PSC1_BASE, SZ_4K);
> +
> +	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA850_REF_FREQ);

Overall, this and other functions like this in this series need some
more line spacing. Please add a space here..

> +	da850_pll_clk_init(pll0, pll1);

.. and here.

> +	clk = clk_register_mux(NULL, "async3",
> +		(const char * const[]){ "pll0_sysclk2", "pll1_sysclk2" },
> +		2, 0, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG),
> +		ilog2(CFGCHIP3_ASYNC3_CLKSRC), 1, 0, NULL);

.. here before the comment ..

> +	/* pll1_sysclk2 is not affected by CPU scaling, so use it for async3 */
> +	parent = clk_hw_get_parent_by_index(__clk_get_hw(clk), 1);
> +	if (parent)
> +		clk_set_parent(clk, parent->clk);
> +	else
> +		pr_warn("%s: Failed to find async3 parent clock\n", __func__);

.. and here. And so on.

I have not taken a closer look at mach patches. But may be you should
send the next version anyway and make sure everyone is happy with the
driver first.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 18, 2018, 6:43 p.m. UTC | #40
On 01/18/2018 09:14 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> +int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
>> +{
>> +	struct regmap *cfgchip;
>> +	struct clk *usb0_psc_clk, *clk;
>> +	struct clk_hw *parent;
>> +
>> +	cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");
> 
> Am I right in understanding that this API is only called for non-DT
> boot? If yes, do we really need the lookup by compatible?

This code is used in DT boot until [PATCH v5 43/44] "ARM: da8xx-dt:
switch to device tree clocks". So, yes it is needed temporarily to
prevent breaking USB.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Jan. 18, 2018, 6:49 p.m. UTC | #41
On 01/18/2018 07:05 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> 
>> +static int da8xx_usb1_phy_clk_set_parent(struct clk_hw *hw, u8 index)
>> +{
>> +	struct da8xx_usb1_phy_clk *clk = to_da8xx_usb1_phy_clk(hw);
>> +	unsigned int mask, val;
>> +
>> +	/* Set the USB 1.1 PHY clock mux based on the parent clock. */
>> +	mask = CFGCHIP2_USB1PHYCLKMUX;
>> +	switch (index) {
>> +	case DA8XX_USB1_PHY_CLK_PARENT_USB_REFCLKIN:
>> +		val = CFGCHIP2_USB1PHYCLKMUX;
>> +		break;
>> +	case DA8XX_USB1_PHY_CLK_PARENT_USB0_PHY_PLL:
>> +		val = 0;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	regmap_write_bits(clk->regmap, CFGCHIP(2), mask, val);
> 
> This function can be simplified quite a bit if you use a shift.
> 
> #define CFGCHIP2_USB1PHYCLKMUX_SHIFT	12
> 
> static int da8xx_usb1_phy_clk_set_parent(struct clk_hw *hw, u8 index)
> {
> 	struct da8xx_usb1_phy_clk *clk = to_da8xx_usb1_phy_clk(hw);
> 
> 	regmap_write_bits(clk->regmap, CFGCHIP(2),
> 			  CFGCHIP2_USB1PHYCLKMUX,
> 			  index << CFGCHIP2_USB1PHYCLKMUX_SHIFT);
> }
> 
> Same thing for da8xx_usb0_phy_clk_set_parent() as well.
> 

or to avoid defining a new macro?


> 	regmap_write_bits(clk->regmap, CFGCHIP(2),
> 			  CFGCHIP2_USB1PHYCLKMUX,
> 			  index ? CFGCHIP2_USB1PHYCLKMUX : 0);
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 19, 2018, 5:04 a.m. UTC | #42
On Friday 19 January 2018 12:19 AM, David Lechner wrote:
>>
> 
> or to avoid defining a new macro?
> 
> 
>>     regmap_write_bits(clk->regmap, CFGCHIP(2),
>>               CFGCHIP2_USB1PHYCLKMUX,
>>               index ? CFGCHIP2_USB1PHYCLKMUX : 0); 

Looks good as well!

Regards,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori Jan. 19, 2018, 5:08 a.m. UTC | #43
On Friday 19 January 2018 12:13 AM, David Lechner wrote:
> On 01/18/2018 09:14 AM, Sekhar Nori wrote:
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>> +int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
>>> +{
>>> +    struct regmap *cfgchip;
>>> +    struct clk *usb0_psc_clk, *clk;
>>> +    struct clk_hw *parent;
>>> +
>>> +    cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");
>>
>> Am I right in understanding that this API is only called for non-DT
>> boot? If yes, do we really need the lookup by compatible?
> 
> This code is used in DT boot until [PATCH v5 43/44] "ARM: da8xx-dt:
> switch to device tree clocks". So, yes it is needed temporarily to
> prevent breaking USB.

Alright, so this line should probably be dropped either as part of 43/44
or later.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bartosz Golaszewski Feb. 9, 2018, 4:22 p.m. UTC | #44
2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
> This adds platform-specific declarations for the PSC clocks on TI DA850/
> OMAP-L138/AM18XX SoCs.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  drivers/clk/davinci/Makefile    |   1 +
>  drivers/clk/davinci/psc-da850.c | 117 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk/davinci.h     |   1 +
>  3 files changed, 119 insertions(+)
>  create mode 100644 drivers/clk/davinci/psc-da850.c
>
> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
> index fb14c8c..aef0390 100644
> --- a/drivers/clk/davinci/Makefile
> +++ b/drivers/clk/davinci/Makefile
> @@ -11,4 +11,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DM646x)     += pll-dm646x.o
>
>  obj-y += psc.o
>  obj-$(CONFIG_ARCH_DAVINCI_DA830)       += psc-da830.o
> +obj-$(CONFIG_ARCH_DAVINCI_DA850)       += psc-da850.o
>  endif
> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
> new file mode 100644
> index 0000000..3b4583d
> --- /dev/null
> +++ b/drivers/clk/davinci/psc-da850.c
> @@ -0,0 +1,117 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PSC clock descriptions for TI DA850/OMAP-L138/AM18XX
> + *
> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/types.h>
> +
> +#include "psc.h"
> +
> +static const struct davinci_psc_clk_info da850_psc0_info[] __initconst = {
> +       LPSC(0, 0, tpcc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +       LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +       LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +       LPSC(3, 0, aemif, pll0_sysclk3, 0),
> +       LPSC(4, 0, spi0, pll0_sysclk2, 0),
> +       LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
> +       LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
> +       LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +       LPSC(9, 0, uart0, pll0_sysclk2, 0),
> +       LPSC(13, 0, pruss, pll0_sysclk2, 0),
> +       LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
> +       LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET),
> +       { }
> +};
> +
> +static const struct davinci_psc_clk_info da850_psc1_info[] __initconst = {
> +       LPSC(0, 0, tpcc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +       LPSC(1, 0, usb0, pll0_sysclk2, 0),
> +       LPSC(2, 0, usb1, pll0_sysclk4, 0),
> +       LPSC(3, 0, gpio, pll0_sysclk4, 0),
> +       LPSC(5, 0, emac, pll0_sysclk4, 0),
> +       LPSC(6, 0, emif3, pll0_sysclk5, LPSC_ALWAYS_ENABLED),
> +       LPSC(7, 0, mcasp0, async3, 0),
> +       LPSC(8, 0, sata, pll0_sysclk2, LPSC_FORCE),
> +       LPSC(9, 0, vpif, pll0_sysclk2, 0),
> +       LPSC(10, 0, spi1, async3, 0),
> +       LPSC(11, 0, i2c1, pll0_sysclk4, 0),
> +       LPSC(12, 0, uart1, async3, 0),
> +       LPSC(13, 0, uart2, async3, 0),
> +       LPSC(14, 0, mcbsp0, async3, 0),
> +       LPSC(15, 0, mcbsp1, async3, 0),
> +       LPSC(16, 0, lcdc, pll0_sysclk2, 0),
> +       LPSC(17, 0, ehrpwm, async3, 0),
> +       LPSC(18, 0, mmcsd1, pll0_sysclk2, 0),
> +       LPSC(20, 0, ecap, async3, 0),
> +       LPSC(21, 0, tptc2, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
> +       { }
> +};
> +
> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
> +{
> +       struct clk_onecell_data *clk_data;
> +
> +       clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
> +       if (!clk_data)
> +               return;
> +
> +       clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
> +       clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
> +       clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
> +       clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
> +       clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
> +       clk_register_clkdev(clk_data->clks[14], "arm", NULL);
> +       clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
> +
> +       clk_free_onecell_data(clk_data);
> +
> +       clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
> +       if (!clk_data)
> +               return;
> +
> +       clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
> +       clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
> +       clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
> +       clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
> +       clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
> +       clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
> +       clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
> +       clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
> +       clk_register_clkdev(clk_data->clks[8], "fck", "ahci_da850");
> +       clk_register_clkdev(clk_data->clks[9], NULL, "vpif");
> +       clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
> +       clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
> +       clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
> +       clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
> +       clk_register_clkdev(clk_data->clks[14], NULL, "davinci-mcbsp.0");
> +       clk_register_clkdev(clk_data->clks[15], NULL, "davinci-mcbsp.1");
> +       clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
> +       clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
> +       clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
> +       clk_register_clkdev(clk_data->clks[18], NULL, "da830-mmc.1");
> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
> +
> +       clk_free_onecell_data(clk_data);
> +}
> +
> +#ifdef CONFIG_OF
> +static void __init of_da850_psc0_clk_init(struct device_node *node)
> +{
> +       of_davinci_psc_clk_init(node, da850_psc0_info, 16);
> +}
> +CLK_OF_DECLARE(da850_psc0_clk, "ti,da850-psc0", of_da850_psc0_clk_init);
> +
> +static void __init of_da850_psc1_clk_init(struct device_node *node)
> +{
> +       of_davinci_psc_clk_init(node, da850_psc1_info, 32);
> +}
> +CLK_OF_DECLARE(da850_psc1_clk, "ti,da850-psc1", of_da850_psc1_clk_init);
> +#endif
> diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
> index 3ec8100..3d8bdfa 100644
> --- a/include/linux/clk/davinci.h
> +++ b/include/linux/clk/davinci.h
> @@ -17,5 +17,6 @@ void dm644x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
>  void dm646x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
>
>  void da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
> +void da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
>
>  #endif /* __LINUX_CLK_DAVINCI_H__ */
> --
> 2.7.4
>

Hi David,

I've been working on moving the genpd code from its own driver to the
psc one. I couldn't get the system to boot though and problems
happened very early in the boot sequence. I struggled to figure out
what's happening, but eventually I noticed that psc uses
CLK_OF_DECLARE() to initialize clocks. The functions registered this
way are called very early in the boot sequence, way before
late_initcall() in which the genpd framework is initialized. This of
course makes it impossible to register genpd at the same time we
register PSCs.

Mike, Stephen - it would be great if you could confirm, but I believe
the clock framework now only accepts clock drivers which create real
platform drivers, in which case this series would need to be modified.

David: FYI I quickly converted the functions in psc-da850.c to actual
probe callbacks and it worked just fine on a da850-lcdk board.

Best regards,
Bartosz Golaszewski
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Turquette Feb. 9, 2018, 4:48 p.m. UTC | #45
Hi Bartosz, all,

On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
>> This adds platform-specific declarations for the PSC clocks on TI DA850/
>> OMAP-L138/AM18XX SoCs.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>>  drivers/clk/davinci/Makefile    |   1 +
>>  drivers/clk/davinci/psc-da850.c | 117 ++++++++++++++++++++++++++++++++++++++++
>>  include/linux/clk/davinci.h     |   1 +
>>  3 files changed, 119 insertions(+)
>>  create mode 100644 drivers/clk/davinci/psc-da850.c
>>
>> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
>> index fb14c8c..aef0390 100644
>> --- a/drivers/clk/davinci/Makefile
>> +++ b/drivers/clk/davinci/Makefile
>> @@ -11,4 +11,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DM646x)     += pll-dm646x.o
>>
>>  obj-y += psc.o
>>  obj-$(CONFIG_ARCH_DAVINCI_DA830)       += psc-da830.o
>> +obj-$(CONFIG_ARCH_DAVINCI_DA850)       += psc-da850.o
>>  endif
>> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
>> new file mode 100644
>> index 0000000..3b4583d
>> --- /dev/null
>> +++ b/drivers/clk/davinci/psc-da850.c
>> @@ -0,0 +1,117 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * PSC clock descriptions for TI DA850/OMAP-L138/AM18XX
>> + *
>> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/init.h>
>> +#include <linux/of.h>
>> +#include <linux/types.h>
>> +
>> +#include "psc.h"
>> +
>> +static const struct davinci_psc_clk_info da850_psc0_info[] __initconst = {
>> +       LPSC(0, 0, tpcc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +       LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +       LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +       LPSC(3, 0, aemif, pll0_sysclk3, 0),
>> +       LPSC(4, 0, spi0, pll0_sysclk2, 0),
>> +       LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
>> +       LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>> +       LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +       LPSC(9, 0, uart0, pll0_sysclk2, 0),
>> +       LPSC(13, 0, pruss, pll0_sysclk2, 0),
>> +       LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
>> +       LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET),
>> +       { }
>> +};
>> +
>> +static const struct davinci_psc_clk_info da850_psc1_info[] __initconst = {
>> +       LPSC(0, 0, tpcc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +       LPSC(1, 0, usb0, pll0_sysclk2, 0),
>> +       LPSC(2, 0, usb1, pll0_sysclk4, 0),
>> +       LPSC(3, 0, gpio, pll0_sysclk4, 0),
>> +       LPSC(5, 0, emac, pll0_sysclk4, 0),
>> +       LPSC(6, 0, emif3, pll0_sysclk5, LPSC_ALWAYS_ENABLED),
>> +       LPSC(7, 0, mcasp0, async3, 0),
>> +       LPSC(8, 0, sata, pll0_sysclk2, LPSC_FORCE),
>> +       LPSC(9, 0, vpif, pll0_sysclk2, 0),
>> +       LPSC(10, 0, spi1, async3, 0),
>> +       LPSC(11, 0, i2c1, pll0_sysclk4, 0),
>> +       LPSC(12, 0, uart1, async3, 0),
>> +       LPSC(13, 0, uart2, async3, 0),
>> +       LPSC(14, 0, mcbsp0, async3, 0),
>> +       LPSC(15, 0, mcbsp1, async3, 0),
>> +       LPSC(16, 0, lcdc, pll0_sysclk2, 0),
>> +       LPSC(17, 0, ehrpwm, async3, 0),
>> +       LPSC(18, 0, mmcsd1, pll0_sysclk2, 0),
>> +       LPSC(20, 0, ecap, async3, 0),
>> +       LPSC(21, 0, tptc2, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>> +       { }
>> +};
>> +
>> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>> +{
>> +       struct clk_onecell_data *clk_data;
>> +
>> +       clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
>> +       clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
>> +       clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>> +       clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>> +       clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>> +       clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>> +       clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
>> +
>> +       clk_free_onecell_data(clk_data);
>> +
>> +       clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
>> +       if (!clk_data)
>> +               return;
>> +
>> +       clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
>> +       clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>> +       clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>> +       clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
>> +       clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
>> +       clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
>> +       clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
>> +       clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
>> +       clk_register_clkdev(clk_data->clks[8], "fck", "ahci_da850");
>> +       clk_register_clkdev(clk_data->clks[9], NULL, "vpif");
>> +       clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
>> +       clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
>> +       clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
>> +       clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
>> +       clk_register_clkdev(clk_data->clks[14], NULL, "davinci-mcbsp.0");
>> +       clk_register_clkdev(clk_data->clks[15], NULL, "davinci-mcbsp.1");
>> +       clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
>> +       clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
>> +       clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
>> +       clk_register_clkdev(clk_data->clks[18], NULL, "da830-mmc.1");
>> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
>> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
>> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
>> +
>> +       clk_free_onecell_data(clk_data);
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +static void __init of_da850_psc0_clk_init(struct device_node *node)
>> +{
>> +       of_davinci_psc_clk_init(node, da850_psc0_info, 16);
>> +}
>> +CLK_OF_DECLARE(da850_psc0_clk, "ti,da850-psc0", of_da850_psc0_clk_init);
>> +
>> +static void __init of_da850_psc1_clk_init(struct device_node *node)
>> +{
>> +       of_davinci_psc_clk_init(node, da850_psc1_info, 32);
>> +}
>> +CLK_OF_DECLARE(da850_psc1_clk, "ti,da850-psc1", of_da850_psc1_clk_init);
>> +#endif
>> diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
>> index 3ec8100..3d8bdfa 100644
>> --- a/include/linux/clk/davinci.h
>> +++ b/include/linux/clk/davinci.h
>> @@ -17,5 +17,6 @@ void dm644x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
>>  void dm646x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
>>
>>  void da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
>> +void da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
>>
>>  #endif /* __LINUX_CLK_DAVINCI_H__ */
>> --
>> 2.7.4
>>
>
> Hi David,
>
> I've been working on moving the genpd code from its own driver to the
> psc one. I couldn't get the system to boot though and problems
> happened very early in the boot sequence. I struggled to figure out
> what's happening, but eventually I noticed that psc uses
> CLK_OF_DECLARE() to initialize clocks. The functions registered this
> way are called very early in the boot sequence, way before
> late_initcall() in which the genpd framework is initialized. This of
> course makes it impossible to register genpd at the same time we
> register PSCs.
>
> Mike, Stephen - it would be great if you could confirm, but I believe
> the clock framework now only accepts clock drivers which create real
> platform drivers, in which case this series would need to be modified.

You are correct. All new uses of CLK_OF_DECLARE are met with high
suspicion, and all new drivers should be platform drivers.

There are cases when CLK_OF_DECLARE is necessary (sometimes
temporarily while things are reworked), but it seems this is not the
case for this driver based on your testing of the platform driver
approach. Please use the platform driver approach instead.

Thanks,
Mike

>
> David: FYI I quickly converted the functions in psc-da850.c to actual
> probe callbacks and it worked just fine on a da850-lcdk board.
>
> Best regards,
> Bartosz Golaszewski
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner Feb. 12, 2018, 3:03 a.m. UTC | #46
On 02/09/2018 10:48 AM, Michael Turquette wrote:
> Hi Bartosz, all,
> 
> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
>>> This adds platform-specific declarations for the PSC clocks on TI DA850/
>>> OMAP-L138/AM18XX SoCs.
>>>
>>> Signed-off-by: David Lechner <david@lechnology.com>
>>> ---
>>>   drivers/clk/davinci/Makefile    |   1 +
>>>   drivers/clk/davinci/psc-da850.c | 117 ++++++++++++++++++++++++++++++++++++++++
>>>   include/linux/clk/davinci.h     |   1 +
>>>   3 files changed, 119 insertions(+)
>>>   create mode 100644 drivers/clk/davinci/psc-da850.c
>>>
>>> diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
>>> index fb14c8c..aef0390 100644
>>> --- a/drivers/clk/davinci/Makefile
>>> +++ b/drivers/clk/davinci/Makefile
>>> @@ -11,4 +11,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DM646x)     += pll-dm646x.o
>>>
>>>   obj-y += psc.o
>>>   obj-$(CONFIG_ARCH_DAVINCI_DA830)       += psc-da830.o
>>> +obj-$(CONFIG_ARCH_DAVINCI_DA850)       += psc-da850.o
>>>   endif
>>> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
>>> new file mode 100644
>>> index 0000000..3b4583d
>>> --- /dev/null
>>> +++ b/drivers/clk/davinci/psc-da850.c
>>> @@ -0,0 +1,117 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * PSC clock descriptions for TI DA850/OMAP-L138/AM18XX
>>> + *
>>> + * Copyright (C) 2017 David Lechner <david@lechnology.com>
>>> + */
>>> +
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/clkdev.h>
>>> +#include <linux/init.h>
>>> +#include <linux/of.h>
>>> +#include <linux/types.h>
>>> +
>>> +#include "psc.h"
>>> +
>>> +static const struct davinci_psc_clk_info da850_psc0_info[] __initconst = {
>>> +       LPSC(0, 0, tpcc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(1, 0, tptc0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(2, 0, tptc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(3, 0, aemif, pll0_sysclk3, 0),
>>> +       LPSC(4, 0, spi0, pll0_sysclk2, 0),
>>> +       LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
>>> +       LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(7, 0, arm_rom, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(9, 0, uart0, pll0_sysclk2, 0),
>>> +       LPSC(13, 0, pruss, pll0_sysclk2, 0),
>>> +       LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET),
>>> +       { }
>>> +};
>>> +
>>> +static const struct davinci_psc_clk_info da850_psc1_info[] __initconst = {
>>> +       LPSC(0, 0, tpcc1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(1, 0, usb0, pll0_sysclk2, 0),
>>> +       LPSC(2, 0, usb1, pll0_sysclk4, 0),
>>> +       LPSC(3, 0, gpio, pll0_sysclk4, 0),
>>> +       LPSC(5, 0, emac, pll0_sysclk4, 0),
>>> +       LPSC(6, 0, emif3, pll0_sysclk5, LPSC_ALWAYS_ENABLED),
>>> +       LPSC(7, 0, mcasp0, async3, 0),
>>> +       LPSC(8, 0, sata, pll0_sysclk2, LPSC_FORCE),
>>> +       LPSC(9, 0, vpif, pll0_sysclk2, 0),
>>> +       LPSC(10, 0, spi1, async3, 0),
>>> +       LPSC(11, 0, i2c1, pll0_sysclk4, 0),
>>> +       LPSC(12, 0, uart1, async3, 0),
>>> +       LPSC(13, 0, uart2, async3, 0),
>>> +       LPSC(14, 0, mcbsp0, async3, 0),
>>> +       LPSC(15, 0, mcbsp1, async3, 0),
>>> +       LPSC(16, 0, lcdc, pll0_sysclk2, 0),
>>> +       LPSC(17, 0, ehrpwm, async3, 0),
>>> +       LPSC(18, 0, mmcsd1, pll0_sysclk2, 0),
>>> +       LPSC(20, 0, ecap, async3, 0),
>>> +       LPSC(21, 0, tptc2, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
>>> +       { }
>>> +};
>>> +
>>> +void __init da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1)
>>> +{
>>> +       struct clk_onecell_data *clk_data;
>>> +
>>> +       clk_data = davinci_psc_register_clocks(psc0, da850_psc0_info, 16);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       clk_register_clkdev(clk_data->clks[3], NULL, "ti-aemif");
>>> +       clk_register_clkdev(clk_data->clks[3], "aemif", "davinci-nand.0");
>>> +       clk_register_clkdev(clk_data->clks[4], NULL, "spi_davinci.0");
>>> +       clk_register_clkdev(clk_data->clks[5], NULL, "da830-mmc.0");
>>> +       clk_register_clkdev(clk_data->clks[9], NULL, "serial8250.0");
>>> +       clk_register_clkdev(clk_data->clks[14], "arm", NULL);
>>> +       clk_register_clkdev(clk_data->clks[15], NULL, "davinci-rproc.0");
>>> +
>>> +       clk_free_onecell_data(clk_data);
>>> +
>>> +       clk_data = davinci_psc_register_clocks(psc1, da850_psc1_info, 32);
>>> +       if (!clk_data)
>>> +               return;
>>> +
>>> +       clk_register_clkdev(clk_data->clks[1], "usb20_psc_clk", NULL);
>>> +       clk_register_clkdev(clk_data->clks[1], NULL, "musb-da8xx");
>>> +       clk_register_clkdev(clk_data->clks[1], NULL, "cppi41-dmaengine");
>>> +       clk_register_clkdev(clk_data->clks[2], NULL, "ohci-da8xx");
>>> +       clk_register_clkdev(clk_data->clks[3], "gpio", NULL);
>>> +       clk_register_clkdev(clk_data->clks[5], NULL, "davinci_emac.1");
>>> +       clk_register_clkdev(clk_data->clks[5], "fck", "davinci_mdio.0");
>>> +       clk_register_clkdev(clk_data->clks[7], NULL, "davinci-mcasp.0");
>>> +       clk_register_clkdev(clk_data->clks[8], "fck", "ahci_da850");
>>> +       clk_register_clkdev(clk_data->clks[9], NULL, "vpif");
>>> +       clk_register_clkdev(clk_data->clks[10], NULL, "spi_davinci.1");
>>> +       clk_register_clkdev(clk_data->clks[11], NULL, "i2c_davinci.2");
>>> +       clk_register_clkdev(clk_data->clks[12], NULL, "serial8250.1");
>>> +       clk_register_clkdev(clk_data->clks[13], NULL, "serial8250.2");
>>> +       clk_register_clkdev(clk_data->clks[14], NULL, "davinci-mcbsp.0");
>>> +       clk_register_clkdev(clk_data->clks[15], NULL, "davinci-mcbsp.1");
>>> +       clk_register_clkdev(clk_data->clks[16], "fck", "da8xx_lcdc.0");
>>> +       clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.0");
>>> +       clk_register_clkdev(clk_data->clks[17], "fck", "ehrpwm.1");
>>> +       clk_register_clkdev(clk_data->clks[18], NULL, "da830-mmc.1");
>>> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.0");
>>> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.1");
>>> +       clk_register_clkdev(clk_data->clks[20], "fck", "ecap.2");
>>> +
>>> +       clk_free_onecell_data(clk_data);
>>> +}
>>> +
>>> +#ifdef CONFIG_OF
>>> +static void __init of_da850_psc0_clk_init(struct device_node *node)
>>> +{
>>> +       of_davinci_psc_clk_init(node, da850_psc0_info, 16);
>>> +}
>>> +CLK_OF_DECLARE(da850_psc0_clk, "ti,da850-psc0", of_da850_psc0_clk_init);
>>> +
>>> +static void __init of_da850_psc1_clk_init(struct device_node *node)
>>> +{
>>> +       of_davinci_psc_clk_init(node, da850_psc1_info, 32);
>>> +}
>>> +CLK_OF_DECLARE(da850_psc1_clk, "ti,da850-psc1", of_da850_psc1_clk_init);
>>> +#endif
>>> diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
>>> index 3ec8100..3d8bdfa 100644
>>> --- a/include/linux/clk/davinci.h
>>> +++ b/include/linux/clk/davinci.h
>>> @@ -17,5 +17,6 @@ void dm644x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
>>>   void dm646x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
>>>
>>>   void da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
>>> +void da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
>>>
>>>   #endif /* __LINUX_CLK_DAVINCI_H__ */
>>> --
>>> 2.7.4
>>>
>>
>> Hi David,
>>
>> I've been working on moving the genpd code from its own driver to the
>> psc one. I couldn't get the system to boot though and problems
>> happened very early in the boot sequence. I struggled to figure out
>> what's happening, but eventually I noticed that psc uses
>> CLK_OF_DECLARE() to initialize clocks. The functions registered this
>> way are called very early in the boot sequence, way before
>> late_initcall() in which the genpd framework is initialized. This of
>> course makes it impossible to register genpd at the same time we
>> register PSCs.
>>
>> Mike, Stephen - it would be great if you could confirm, but I believe
>> the clock framework now only accepts clock drivers which create real
>> platform drivers, in which case this series would need to be modified.
> 
> You are correct. All new uses of CLK_OF_DECLARE are met with high
> suspicion, and all new drivers should be platform drivers.

Oh boy. I'll try to get a v7 out this week with these changes.



> 
> There are cases when CLK_OF_DECLARE is necessary (sometimes
> temporarily while things are reworked), but it seems this is not the
> case for this driver based on your testing of the platform driver
> approach. Please use the platform driver approach instead.
> 
> Thanks,
> Mike
> 
>>
>> David: FYI I quickly converted the functions in psc-da850.c to actual
>> probe callbacks and it worked just fine on a da850-lcdk board.
>>
>> Best regards,
>> Bartosz Golaszewski

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori April 5, 2018, 1:09 p.m. UTC | #47
Hi Bartosz,

On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:

>> Hi David,
>>
>> I've been working on moving the genpd code from its own driver to the
>> psc one. I couldn't get the system to boot though and problems
>> happened very early in the boot sequence. I struggled to figure out
>> what's happening, but eventually I noticed that psc uses
>> CLK_OF_DECLARE() to initialize clocks. The functions registered this
>> way are called very early in the boot sequence, way before
>> late_initcall() in which the genpd framework is initialized. This of

late_initcall() is too late for genpd to be initialized. As you may have
seen with the latest set of patches, we have problems with timer
initialization. After converting to platform devices, PSC and PLL clocks
get initialized post time_init(). We are working that around using
fixed-clocks, which hopefully will work (I still need to test many of
the affected platforms).

Can you please reply with the exact issue you faced with genpd framework
initialization so we do have that on record.

Thanks,
Sekhar

>> course makes it impossible to register genpd at the same time we
>> register PSCs.
>>
>> Mike, Stephen - it would be great if you could confirm, but I believe
>> the clock framework now only accepts clock drivers which create real
>> platform drivers, in which case this series would need to be modified.
> 
> You are correct. All new uses of CLK_OF_DECLARE are met with high
> suspicion, and all new drivers should be platform drivers.
> 
> There are cases when CLK_OF_DECLARE is necessary (sometimes
> temporarily while things are reworked), but it seems this is not the
> case for this driver based on your testing of the platform driver
> approach. Please use the platform driver approach instead.
> 
> Thanks,
> Mike
> 
>>
>> David: FYI I quickly converted the functions in psc-da850.c to actual
>> probe callbacks and it worked just fine on a da850-lcdk board.
>>
>> Best regards,
>> Bartosz Golaszewski

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bartosz Golaszewski April 5, 2018, 1:44 p.m. UTC | #48
2018-04-05 15:09 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
> Hi Bartosz,
>
> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
>
>>> Hi David,
>>>
>>> I've been working on moving the genpd code from its own driver to the
>>> psc one. I couldn't get the system to boot though and problems
>>> happened very early in the boot sequence. I struggled to figure out
>>> what's happening, but eventually I noticed that psc uses
>>> CLK_OF_DECLARE() to initialize clocks. The functions registered this
>>> way are called very early in the boot sequence, way before
>>> late_initcall() in which the genpd framework is initialized. This of
>
> late_initcall() is too late for genpd to be initialized. As you may have
> seen with the latest set of patches, we have problems with timer
> initialization. After converting to platform devices, PSC and PLL clocks
> get initialized post time_init(). We are working that around using
> fixed-clocks, which hopefully will work (I still need to test many of
> the affected platforms).
>
> Can you please reply with the exact issue you faced with genpd framework
> initialization so we do have that on record.
>

The exact issue manifested itself in a NULL-pointer dereference panic
when I tried moving the genpd code I had initially implemented as a
separate platform driver to what I believe was v6 or v7 of David's
series (before the psc driver became a platform driver, when it was
still using CLK_OF_DECLARE()). When I had tested a simple conversion
of that version to a platform_driver, genpd worked fine.

I don't have the stack traces from these panics, but I recall some
debugfs functions being involved and the genpd late_initcalls are
related to debugfs. Looking at it now I don't see how exactly it could
fail though.

Best regards,
Bartosz
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori April 5, 2018, 2:36 p.m. UTC | #49
On Thursday 05 April 2018 07:14 PM, Bartosz Golaszewski wrote:
> 2018-04-05 15:09 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
>> Hi Bartosz,
>>
>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
>>
>>>> Hi David,
>>>>
>>>> I've been working on moving the genpd code from its own driver to the
>>>> psc one. I couldn't get the system to boot though and problems
>>>> happened very early in the boot sequence. I struggled to figure out
>>>> what's happening, but eventually I noticed that psc uses
>>>> CLK_OF_DECLARE() to initialize clocks. The functions registered this
>>>> way are called very early in the boot sequence, way before
>>>> late_initcall() in which the genpd framework is initialized. This of
>>
>> late_initcall() is too late for genpd to be initialized. As you may have
>> seen with the latest set of patches, we have problems with timer
>> initialization. After converting to platform devices, PSC and PLL clocks
>> get initialized post time_init(). We are working that around using
>> fixed-clocks, which hopefully will work (I still need to test many of
>> the affected platforms).
>>
>> Can you please reply with the exact issue you faced with genpd framework
>> initialization so we do have that on record.
>>
> 
> The exact issue manifested itself in a NULL-pointer dereference panic
> when I tried moving the genpd code I had initially implemented as a
> separate platform driver to what I believe was v6 or v7 of David's
> series (before the psc driver became a platform driver, when it was
> still using CLK_OF_DECLARE()). When I had tested a simple conversion
> of that version to a platform_driver, genpd worked fine.
> 
> I don't have the stack traces from these panics, but I recall some
> debugfs functions being involved and the genpd late_initcalls are
> related to debugfs. Looking at it now I don't see how exactly it could
> fail though.

Do you have the code where you faced the problem stashed somewhere? I am
not (yet) advocating going back to CLK_OF_DECLARE(). But there is a
definite issue with timer being ready when not using CLK_OF_DECLARE().
So, I want to make sure there the reason why we are going down the
platform device path is a amply clear.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner April 5, 2018, 3:37 p.m. UTC | #50
On 04/05/2018 09:36 AM, Sekhar Nori wrote:
> On Thursday 05 April 2018 07:14 PM, Bartosz Golaszewski wrote:
>> 2018-04-05 15:09 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
>>> Hi Bartosz,
>>>
>>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
>>>
>>>>> Hi David,
>>>>>
>>>>> I've been working on moving the genpd code from its own driver to the
>>>>> psc one. I couldn't get the system to boot though and problems
>>>>> happened very early in the boot sequence. I struggled to figure out
>>>>> what's happening, but eventually I noticed that psc uses
>>>>> CLK_OF_DECLARE() to initialize clocks. The functions registered this
>>>>> way are called very early in the boot sequence, way before
>>>>> late_initcall() in which the genpd framework is initialized. This of
>>>
>>> late_initcall() is too late for genpd to be initialized. As you may have
>>> seen with the latest set of patches, we have problems with timer
>>> initialization. After converting to platform devices, PSC and PLL clocks
>>> get initialized post time_init(). We are working that around using
>>> fixed-clocks, which hopefully will work (I still need to test many of
>>> the affected platforms).
>>>
>>> Can you please reply with the exact issue you faced with genpd framework
>>> initialization so we do have that on record.
>>>
>>
>> The exact issue manifested itself in a NULL-pointer dereference panic
>> when I tried moving the genpd code I had initially implemented as a
>> separate platform driver to what I believe was v6 or v7 of David's
>> series (before the psc driver became a platform driver, when it was
>> still using CLK_OF_DECLARE()). When I had tested a simple conversion
>> of that version to a platform_driver, genpd worked fine.
>>
>> I don't have the stack traces from these panics, but I recall some
>> debugfs functions being involved and the genpd late_initcalls are
>> related to debugfs. Looking at it now I don't see how exactly it could
>> fail though.
> 
> Do you have the code where you faced the problem stashed somewhere? I am
> not (yet) advocating going back to CLK_OF_DECLARE(). But there is a
> definite issue with timer being ready when not using CLK_OF_DECLARE().
> So, I want to make sure there the reason why we are going down the
> platform device path is a amply clear.
> 
> Thanks,
> Sekhar
> 
This is the thread that led to the conversion to platform devices:

https://lkml.org/lkml/2018/2/9/541

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bartosz Golaszewski April 5, 2018, 3:51 p.m. UTC | #51
2018-04-05 16:36 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
> On Thursday 05 April 2018 07:14 PM, Bartosz Golaszewski wrote:
>> 2018-04-05 15:09 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
>>> Hi Bartosz,
>>>
>>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <david@lechnology.com>:
>>>
>>>>> Hi David,
>>>>>
>>>>> I've been working on moving the genpd code from its own driver to the
>>>>> psc one. I couldn't get the system to boot though and problems
>>>>> happened very early in the boot sequence. I struggled to figure out
>>>>> what's happening, but eventually I noticed that psc uses
>>>>> CLK_OF_DECLARE() to initialize clocks. The functions registered this
>>>>> way are called very early in the boot sequence, way before
>>>>> late_initcall() in which the genpd framework is initialized. This of
>>>
>>> late_initcall() is too late for genpd to be initialized. As you may have
>>> seen with the latest set of patches, we have problems with timer
>>> initialization. After converting to platform devices, PSC and PLL clocks
>>> get initialized post time_init(). We are working that around using
>>> fixed-clocks, which hopefully will work (I still need to test many of
>>> the affected platforms).
>>>
>>> Can you please reply with the exact issue you faced with genpd framework
>>> initialization so we do have that on record.
>>>
>>
>> The exact issue manifested itself in a NULL-pointer dereference panic
>> when I tried moving the genpd code I had initially implemented as a
>> separate platform driver to what I believe was v6 or v7 of David's
>> series (before the psc driver became a platform driver, when it was
>> still using CLK_OF_DECLARE()). When I had tested a simple conversion
>> of that version to a platform_driver, genpd worked fine.
>>
>> I don't have the stack traces from these panics, but I recall some
>> debugfs functions being involved and the genpd late_initcalls are
>> related to debugfs. Looking at it now I don't see how exactly it could
>> fail though.
>
> Do you have the code where you faced the problem stashed somewhere? I am
> not (yet) advocating going back to CLK_OF_DECLARE(). But there is a
> definite issue with timer being ready when not using CLK_OF_DECLARE().
> So, I want to make sure there the reason why we are going down the
> platform device path is a amply clear.
>
> Thanks,
> Sekhar

Yes, you can still find it on my github[1].

Bart

[1] github.com:brgl/linux.git  topic/davinci-genpd-final-v2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Boyd April 6, 2018, 4:46 p.m. UTC | #52
Quoting Sekhar Nori (2018-04-06 02:37:03)
> 
> Can you please check that and confirm there is no issue with genpd and 
> using CLK_OF_DECLARE() to initialize clocks?
> 
> Unless you report an issue back, or Mike and Stephen have ideas about 
> how to handle the dependency between PSC/PLL derived timer clock 
> initialization and and timer_probe(), I think we need to move back to 
> using CLK_OF_DECLARE(). 

In such a case, please use the hybrid approach where the clks required
for the clockevent and/or clocksource are registered in the early
CLK_OF_DECLARE path but the rest of the clks get registered with a
proper platform device and driver. There are examples of this approach
on other platforms already.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner April 23, 2018, 2:59 p.m. UTC | #53
On 04/06/2018 11:46 AM, Stephen Boyd wrote:
> Quoting Sekhar Nori (2018-04-06 02:37:03)
>>
>> Can you please check that and confirm there is no issue with genpd and
>> using CLK_OF_DECLARE() to initialize clocks?
>>
>> Unless you report an issue back, or Mike and Stephen have ideas about
>> how to handle the dependency between PSC/PLL derived timer clock
>> initialization and and timer_probe(), I think we need to move back to
>> using CLK_OF_DECLARE().
> 
> In such a case, please use the hybrid approach where the clks required
> for the clockevent and/or clocksource are registered in the early
> CLK_OF_DECLARE path but the rest of the clks get registered with a
> proper platform device and driver. There are examples of this approach
> on other platforms already.
> 

I looked at this a bit last week, but I didn't come up with any approach
that I was happy with. It seems like it would be nice to just register
the absolute minimum clocks needed. On DA8XX, that would just be the PLL0
AUXCLK. On most of the other SoCs, it would be the PLL AUXCLK plus one
LPSC clock. The AUXCLKs are easy because they are just a simple gate
from the oscillator. The LPSC clocks are a bit more tricky because they
have a complex sequence for turning on. Furthermore, on DM646X, we need
the whole PLL up to SYSCLK3 plus one LPSC clock, so things get a bit
messy there.

The other approach I considered was to make the PLL and PSC drivers
work as platform devices or pure clock devices so that when needed,
the whole IP block could be registered in very early init. However,
this approach will pretty much require massive changes to the drivers
to remove all of the uses of devm_, dev_err, etc. so that it works
when dev == NULL.

Any other bright ideas or a preference for one of these two approaches?

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori April 24, 2018, 8:28 a.m. UTC | #54
On Monday 23 April 2018 08:29 PM, David Lechner wrote:
> On 04/06/2018 11:46 AM, Stephen Boyd wrote:
>> Quoting Sekhar Nori (2018-04-06 02:37:03)
>>>
>>> Can you please check that and confirm there is no issue with genpd and
>>> using CLK_OF_DECLARE() to initialize clocks?
>>>
>>> Unless you report an issue back, or Mike and Stephen have ideas about
>>> how to handle the dependency between PSC/PLL derived timer clock
>>> initialization and and timer_probe(), I think we need to move back to
>>> using CLK_OF_DECLARE().
>>
>> In such a case, please use the hybrid approach where the clks required
>> for the clockevent and/or clocksource are registered in the early
>> CLK_OF_DECLARE path but the rest of the clks get registered with a
>> proper platform device and driver. There are examples of this approach
>> on other platforms already.
>>
> 
> I looked at this a bit last week, but I didn't come up with any approach
> that I was happy with. It seems like it would be nice to just register
> the absolute minimum clocks needed. On DA8XX, that would just be the PLL0
> AUXCLK. On most of the other SoCs, it would be the PLL AUXCLK plus one
> LPSC clock. The AUXCLKs are easy because they are just a simple gate
> from the oscillator. The LPSC clocks are a bit more tricky because they
> have a complex sequence for turning on. Furthermore, on DM646X, we need
> the whole PLL up to SYSCLK3 plus one LPSC clock, so things get a bit
> messy there.

Things might change in the context of work being done here by Bartosz
for converting clocks to early platform devices.

But, keeping that development aside for a moment: I think this means the
PLLs and PSCs need to be CLK_OF_DECLARE(). What we can have as platform
devices are clocks that are not in the path to get timer clock working
(like CFGCHIP clocks).

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner April 24, 2018, 4:11 p.m. UTC | #55
On 04/24/2018 03:28 AM, Sekhar Nori wrote:
> On Monday 23 April 2018 08:29 PM, David Lechner wrote:
>> On 04/06/2018 11:46 AM, Stephen Boyd wrote:
>>> Quoting Sekhar Nori (2018-04-06 02:37:03)
>>>>
>>>> Can you please check that and confirm there is no issue with genpd and
>>>> using CLK_OF_DECLARE() to initialize clocks?
>>>>
>>>> Unless you report an issue back, or Mike and Stephen have ideas about
>>>> how to handle the dependency between PSC/PLL derived timer clock
>>>> initialization and and timer_probe(), I think we need to move back to
>>>> using CLK_OF_DECLARE().
>>>
>>> In such a case, please use the hybrid approach where the clks required
>>> for the clockevent and/or clocksource are registered in the early
>>> CLK_OF_DECLARE path but the rest of the clks get registered with a
>>> proper platform device and driver. There are examples of this approach
>>> on other platforms already.
>>>
>>
>> I looked at this a bit last week, but I didn't come up with any approach
>> that I was happy with. It seems like it would be nice to just register
>> the absolute minimum clocks needed. On DA8XX, that would just be the PLL0
>> AUXCLK. On most of the other SoCs, it would be the PLL AUXCLK plus one
>> LPSC clock. The AUXCLKs are easy because they are just a simple gate
>> from the oscillator. The LPSC clocks are a bit more tricky because they
>> have a complex sequence for turning on. Furthermore, on DM646X, we need
>> the whole PLL up to SYSCLK3 plus one LPSC clock, so things get a bit
>> messy there.
> 
> Things might change in the context of work being done here by Bartosz
> for converting clocks to early platform devices.
> 
> But, keeping that development aside for a moment: I think this means the
> PLLs and PSCs need to be CLK_OF_DECLARE(). What we can have as platform
> devices are clocks that are not in the path to get timer clock working
> (like CFGCHIP clocks).

CLK_OF_DECLARE() only matters on DA850. None of the other SoCs use device
tree. And on DA850, the timer0 clock is just the PLL0 AUXCLK, so PSCs can
still be platform devices there. And in fact, one of the PSC clocks on
DA850 depends on async3, which is a CFGCHIP clock, so if we made the PSCs
CLK_OF_DECLARE(), then we also have to make at least the async3 CFGCHIP
clock CLK_OF_DECLARE(). But, like I said, I think that can be avoided by
leaving the PSC clocks as a platform device on DA850 (and DA830).

For everything else, we need the legacy board file equivalent of
CLK_OF_DECLARE(), which is basically what I had here in v5 of the
series.

So, if we want this to keep moving before the if/when of Bartosz's
early platform device stuff, I'm thinking that I will make the PLL
and PSC drivers loadable with or without a platform device and let
each SoC pick which one it should use.


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori April 25, 2018, 6:07 a.m. UTC | #56
On Tuesday 24 April 2018 09:41 PM, David Lechner wrote:
> On 04/24/2018 03:28 AM, Sekhar Nori wrote:
>> On Monday 23 April 2018 08:29 PM, David Lechner wrote:
>>> On 04/06/2018 11:46 AM, Stephen Boyd wrote:
>>>> Quoting Sekhar Nori (2018-04-06 02:37:03)
>>>>>
>>>>> Can you please check that and confirm there is no issue with genpd and
>>>>> using CLK_OF_DECLARE() to initialize clocks?
>>>>>
>>>>> Unless you report an issue back, or Mike and Stephen have ideas about
>>>>> how to handle the dependency between PSC/PLL derived timer clock
>>>>> initialization and and timer_probe(), I think we need to move back to
>>>>> using CLK_OF_DECLARE().
>>>>
>>>> In such a case, please use the hybrid approach where the clks required
>>>> for the clockevent and/or clocksource are registered in the early
>>>> CLK_OF_DECLARE path but the rest of the clks get registered with a
>>>> proper platform device and driver. There are examples of this approach
>>>> on other platforms already.
>>>>
>>>
>>> I looked at this a bit last week, but I didn't come up with any approach
>>> that I was happy with. It seems like it would be nice to just register
>>> the absolute minimum clocks needed. On DA8XX, that would just be the
>>> PLL0
>>> AUXCLK. On most of the other SoCs, it would be the PLL AUXCLK plus one
>>> LPSC clock. The AUXCLKs are easy because they are just a simple gate
>>> from the oscillator. The LPSC clocks are a bit more tricky because they
>>> have a complex sequence for turning on. Furthermore, on DM646X, we need
>>> the whole PLL up to SYSCLK3 plus one LPSC clock, so things get a bit
>>> messy there.
>>
>> Things might change in the context of work being done here by Bartosz
>> for converting clocks to early platform devices.
>>
>> But, keeping that development aside for a moment: I think this means the
>> PLLs and PSCs need to be CLK_OF_DECLARE(). What we can have as platform
>> devices are clocks that are not in the path to get timer clock working
>> (like CFGCHIP clocks).
> 
> CLK_OF_DECLARE() only matters on DA850. None of the other SoCs use device

Thats true today, but lets not make the assumption that none of the
other DaVinci SoCs will gain DT support ever. We don't want churn in CCF
support once someone tries to add DT support for other platforms.

I already have people using DM365 in mainline, for example.

> tree. And on DA850, the timer0 clock is just the PLL0 AUXCLK, so PSCs can> still be platform devices there. And in fact, one of the PSC clocks on
> DA850 depends on async3, which is a CFGCHIP clock, so if we made the PSCs
> CLK_OF_DECLARE(), then we also have to make at least the async3 CFGCHIP
> clock CLK_OF_DECLARE(). But, like I said, I think that can be avoided by
> leaving the PSC clocks as a platform device on DA850 (and DA830).

Okay, I did not realize that there is a dependency between CFGCHIP clk
and PSC too.

> For everything else, we need the legacy board file equivalent of
> CLK_OF_DECLARE(), which is basically what I had here in v5 of the
> series.

Yeah. I did not realize the dependency with timer when platform devices
were suggested. Sorry.

> 
> So, if we want this to keep moving before the if/when of Bartosz's
> early platform device stuff, I'm thinking that I will make the PLL

After looking at feedback to Bartosz's series, and the fact that
previous attempts at doing the same thing were rejected, I think there
is benefit in keeping CCF support moving independent Bartosz's work.
Otherwise, we have no chance of getting anything merged for v4.18.

Early initialization of clocks and dependency with timer is a pretty
common theme across SoCs. As and when a better way to support is found,
I am sure DaVinci can be converted over along with rest of the devices.

> and PSC drivers loadable with or without a platform device and let
> each SoC pick which one it should use.

This sounds flexible. We have to see how the patches look. But I would
caution against adding a lot of dead code. If there is no way some of
the clocks will be useful as platform device, I see no point of
supporting them as such just in anticipation.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bartosz Golaszewski April 25, 2018, 10:09 a.m. UTC | #57
2018-04-25 8:07 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
> On Tuesday 24 April 2018 09:41 PM, David Lechner wrote:
>> On 04/24/2018 03:28 AM, Sekhar Nori wrote:
>>> On Monday 23 April 2018 08:29 PM, David Lechner wrote:
>>>> On 04/06/2018 11:46 AM, Stephen Boyd wrote:
>>>>> Quoting Sekhar Nori (2018-04-06 02:37:03)
>>>>>>
>>>>>> Can you please check that and confirm there is no issue with genpd and
>>>>>> using CLK_OF_DECLARE() to initialize clocks?
>>>>>>
>>>>>> Unless you report an issue back, or Mike and Stephen have ideas about
>>>>>> how to handle the dependency between PSC/PLL derived timer clock
>>>>>> initialization and and timer_probe(), I think we need to move back to
>>>>>> using CLK_OF_DECLARE().
>>>>>
>>>>> In such a case, please use the hybrid approach where the clks required
>>>>> for the clockevent and/or clocksource are registered in the early
>>>>> CLK_OF_DECLARE path but the rest of the clks get registered with a
>>>>> proper platform device and driver. There are examples of this approach
>>>>> on other platforms already.
>>>>>
>>>>
>>>> I looked at this a bit last week, but I didn't come up with any approach
>>>> that I was happy with. It seems like it would be nice to just register
>>>> the absolute minimum clocks needed. On DA8XX, that would just be the
>>>> PLL0
>>>> AUXCLK. On most of the other SoCs, it would be the PLL AUXCLK plus one
>>>> LPSC clock. The AUXCLKs are easy because they are just a simple gate
>>>> from the oscillator. The LPSC clocks are a bit more tricky because they
>>>> have a complex sequence for turning on. Furthermore, on DM646X, we need
>>>> the whole PLL up to SYSCLK3 plus one LPSC clock, so things get a bit
>>>> messy there.
>>>
>>> Things might change in the context of work being done here by Bartosz
>>> for converting clocks to early platform devices.
>>>
>>> But, keeping that development aside for a moment: I think this means the
>>> PLLs and PSCs need to be CLK_OF_DECLARE(). What we can have as platform
>>> devices are clocks that are not in the path to get timer clock working
>>> (like CFGCHIP clocks).
>>
>> CLK_OF_DECLARE() only matters on DA850. None of the other SoCs use device
>
> Thats true today, but lets not make the assumption that none of the
> other DaVinci SoCs will gain DT support ever. We don't want churn in CCF
> support once someone tries to add DT support for other platforms.
>
> I already have people using DM365 in mainline, for example.
>
>> tree. And on DA850, the timer0 clock is just the PLL0 AUXCLK, so PSCs can> still be platform devices there. And in fact, one of the PSC clocks on
>> DA850 depends on async3, which is a CFGCHIP clock, so if we made the PSCs
>> CLK_OF_DECLARE(), then we also have to make at least the async3 CFGCHIP
>> clock CLK_OF_DECLARE(). But, like I said, I think that can be avoided by
>> leaving the PSC clocks as a platform device on DA850 (and DA830).
>
> Okay, I did not realize that there is a dependency between CFGCHIP clk
> and PSC too.
>
>> For everything else, we need the legacy board file equivalent of
>> CLK_OF_DECLARE(), which is basically what I had here in v5 of the
>> series.
>
> Yeah. I did not realize the dependency with timer when platform devices
> were suggested. Sorry.
>
>>
>> So, if we want this to keep moving before the if/when of Bartosz's
>> early platform device stuff, I'm thinking that I will make the PLL
>
> After looking at feedback to Bartosz's series, and the fact that
> previous attempts at doing the same thing were rejected, I think there
> is benefit in keeping CCF support moving independent Bartosz's work.
> Otherwise, we have no chance of getting anything merged for v4.18.
>

It's true, that the feedback was not very positive, but I'm still
thinking I can come up with something that would get accepted. Last
time someone came up with the idea, the problem it was supposed to
solve was different (dependencies between devices) and was eventually
fixed with introduction of probe deferral.

This time around we really want these devices probed early. The main
concern was using a device tree compatible. If I can instead just
early probe all devices whose drivers are registered as early without
touching the device tree (as Frank Rowand suggested) then maybe the
response of the community would be better.

Thanks,
Bart

> Early initialization of clocks and dependency with timer is a pretty
> common theme across SoCs. As and when a better way to support is found,
> I am sure DaVinci can be converted over along with rest of the devices.
>
>> and PSC drivers loadable with or without a platform device and let
>> each SoC pick which one it should use.
>
> This sounds flexible. We have to see how the patches look. But I would
> caution against adding a lot of dead code. If there is no way some of
> the clocks will be useful as platform device, I see no point of
> supporting them as such just in anticipation.
>
> Thanks,
> Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bartosz Golaszewski April 25, 2018, 10:26 a.m. UTC | #58
2018-04-25 12:09 GMT+02:00 Bartosz Golaszewski <brgl@bgdev.pl>:
> 2018-04-25 8:07 GMT+02:00 Sekhar Nori <nsekhar@ti.com>:
>> On Tuesday 24 April 2018 09:41 PM, David Lechner wrote:
>>> On 04/24/2018 03:28 AM, Sekhar Nori wrote:
>>>> On Monday 23 April 2018 08:29 PM, David Lechner wrote:
>>>>> On 04/06/2018 11:46 AM, Stephen Boyd wrote:
>>>>>> Quoting Sekhar Nori (2018-04-06 02:37:03)
>>>>>>>
>>>>>>> Can you please check that and confirm there is no issue with genpd and
>>>>>>> using CLK_OF_DECLARE() to initialize clocks?
>>>>>>>
>>>>>>> Unless you report an issue back, or Mike and Stephen have ideas about
>>>>>>> how to handle the dependency between PSC/PLL derived timer clock
>>>>>>> initialization and and timer_probe(), I think we need to move back to
>>>>>>> using CLK_OF_DECLARE().
>>>>>>
>>>>>> In such a case, please use the hybrid approach where the clks required
>>>>>> for the clockevent and/or clocksource are registered in the early
>>>>>> CLK_OF_DECLARE path but the rest of the clks get registered with a
>>>>>> proper platform device and driver. There are examples of this approach
>>>>>> on other platforms already.
>>>>>>
>>>>>
>>>>> I looked at this a bit last week, but I didn't come up with any approach
>>>>> that I was happy with. It seems like it would be nice to just register
>>>>> the absolute minimum clocks needed. On DA8XX, that would just be the
>>>>> PLL0
>>>>> AUXCLK. On most of the other SoCs, it would be the PLL AUXCLK plus one
>>>>> LPSC clock. The AUXCLKs are easy because they are just a simple gate
>>>>> from the oscillator. The LPSC clocks are a bit more tricky because they
>>>>> have a complex sequence for turning on. Furthermore, on DM646X, we need
>>>>> the whole PLL up to SYSCLK3 plus one LPSC clock, so things get a bit
>>>>> messy there.
>>>>
>>>> Things might change in the context of work being done here by Bartosz
>>>> for converting clocks to early platform devices.
>>>>
>>>> But, keeping that development aside for a moment: I think this means the
>>>> PLLs and PSCs need to be CLK_OF_DECLARE(). What we can have as platform
>>>> devices are clocks that are not in the path to get timer clock working
>>>> (like CFGCHIP clocks).
>>>
>>> CLK_OF_DECLARE() only matters on DA850. None of the other SoCs use device
>>
>> Thats true today, but lets not make the assumption that none of the
>> other DaVinci SoCs will gain DT support ever. We don't want churn in CCF
>> support once someone tries to add DT support for other platforms.
>>
>> I already have people using DM365 in mainline, for example.
>>
>>> tree. And on DA850, the timer0 clock is just the PLL0 AUXCLK, so PSCs can> still be platform devices there. And in fact, one of the PSC clocks on
>>> DA850 depends on async3, which is a CFGCHIP clock, so if we made the PSCs
>>> CLK_OF_DECLARE(), then we also have to make at least the async3 CFGCHIP
>>> clock CLK_OF_DECLARE(). But, like I said, I think that can be avoided by
>>> leaving the PSC clocks as a platform device on DA850 (and DA830).
>>
>> Okay, I did not realize that there is a dependency between CFGCHIP clk
>> and PSC too.
>>
>>> For everything else, we need the legacy board file equivalent of
>>> CLK_OF_DECLARE(), which is basically what I had here in v5 of the
>>> series.
>>
>> Yeah. I did not realize the dependency with timer when platform devices
>> were suggested. Sorry.
>>
>>>
>>> So, if we want this to keep moving before the if/when of Bartosz's
>>> early platform device stuff, I'm thinking that I will make the PLL
>>
>> After looking at feedback to Bartosz's series, and the fact that
>> previous attempts at doing the same thing were rejected, I think there
>> is benefit in keeping CCF support moving independent Bartosz's work.
>> Otherwise, we have no chance of getting anything merged for v4.18.
>>
>
> It's true, that the feedback was not very positive, but I'm still
> thinking I can come up with something that would get accepted. Last
> time someone came up with the idea, the problem it was supposed to
> solve was different (dependencies between devices) and was eventually
> fixed with introduction of probe deferral.
>
> This time around we really want these devices probed early. The main
> concern was using a device tree compatible. If I can instead just
> early probe all devices whose drivers are registered as early without
> touching the device tree (as Frank Rowand suggested) then maybe the

* It was actually Mark Rutland.

> response of the community would be better.
>
> Thanks,
> Bart
>
>> Early initialization of clocks and dependency with timer is a pretty
>> common theme across SoCs. As and when a better way to support is found,
>> I am sure DaVinci can be converted over along with rest of the devices.
>>
>>> and PSC drivers loadable with or without a platform device and let
>>> each SoC pick which one it should use.
>>
>> This sounds flexible. We have to see how the patches look. But I would
>> caution against adding a lot of dead code. If there is no way some of
>> the clocks will be useful as platform device, I see no point of
>> supporting them as such just in anticipation.
>>
>> Thanks,
>> Sekhar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html