2018-01-08 02:18:23

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 00/44] ARM: davinci: convert to common clock framework​

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

--
2.7.4


2018-01-08 02:18:28

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

This adds a new binding for the PLL IP blocks in the mach-davinci family
of processors. Currently, only the SYSCLKn and AUXCLK outputs are needed,
but in the future additional child nodes could be added for OBSCLK and
BPDIV.

Note: Although these PLL controllers are very similar to the TI Keystone
SoCs, we are not re-using those bindings. The Keystone bindings use a
legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs
have a slightly different PLL register layout and a number of quirks that
can't be handled by the existing bindings, so the keystone bindings could
not be used as-is anyway.

Signed-off-by: David Lechner <[email protected]>
---
.../devicetree/bindings/clock/ti/davinci/pll.txt | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt

diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
new file mode 100644
index 0000000..99bf5da
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
@@ -0,0 +1,47 @@
+Binding for TI DaVinci PLL Controllers
+
+The PLL provides clocks to most of the components on the SoC. In addition
+to the PLL itself, this controller also contains bypasses, gates, dividers,
+an multiplexers for various clock signals.
+
+Required properties:
+- compatible: shall be one of:
+ - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
+ - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
+- reg: physical base address and size of the controller's register area.
+- clocks: phandle to the PLL input clock source
+
+Optional child nodes:
+
+sysclk
+ Describes the PLLDIVn divider clocks that provide the SYSCLKn clock
+ domains. The node name must be "sysclk". Consumers of this node should
+ use "n" in "SYSCLKn" as the parameter for the clock cell.
+
+ Required properties:
+ - #clock-cells: must be 1
+
+auxclk
+ Describes the AUXCLK output of the PLL. The node name must be "auxclk".
+
+ Required properties:
+ - #clock-cells: must be 0
+
+Examples:
+
+ pll0: clock-controller@11000 {
+ compatible = "ti,da850-pll0";
+ reg = <0x11000 0x1000>;
+ clocks = <&ref_clk>;
+
+ pll0_sysclk: sysclk {
+ #clock-cells = <1>;
+ };
+
+ pll0_aux_clk: auxclk {
+ #clock-cells = <0>;
+ };
+ };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
--
2.7.4

2018-01-08 02:18:38

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 07/44] clk: davinci: Add platform information for TI DM644x PLL

This adds platform-specific declarations for the PLL clocks on TI
DaVinci 644x based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/pll-dm644x.c | 41 ++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 43 insertions(+)
create mode 100644 drivers/clk/davinci/pll-dm644x.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index 353aa02..59d8ab6 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -6,4 +6,5 @@ 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
+obj-$(CONFIG_ARCH_DAVINCI_DM644x) += pll-dm644x.o
endif
diff --git a/drivers/clk/davinci/pll-dm644x.c b/drivers/clk/davinci/pll-dm644x.c
new file mode 100644
index 0000000..b0d0373
--- /dev/null
+++ b/drivers/clk/davinci/pll-dm644x.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM644X
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_divclk_info dm644x_pll1_divclk_info[] __initconst = {
+ DIVCLK(1, pll1_sysclk1, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(2, pll1_sysclk2, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(3, pll1_sysclk3, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(5, pll1_sysclk5, pll1, DIVCLK_FIXED_DIV),
+ { }
+};
+
+static const struct davinci_pll_divclk_info dm644x_pll2_divclk_info[] __initconst = {
+ DIVCLK(1, pll2_sysclk1, pll2, 0),
+ DIVCLK(2, pll2_sysclk2, pll2, 0),
+ { }
+};
+
+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);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 5bf60a7..535990a 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -13,5 +13,6 @@ void da830_pll_clk_init(void __iomem *pll);
void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1);
void dm355_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
void dm365_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
+void dm644x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:18:44

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

This adds platform-specific declarations for the PSC clocks on TI DA850/
OMAP-L138/AM18XX SoCs.

Signed-off-by: David Lechner <[email protected]>
---
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 <[email protected]>
+ */
+
+#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

2018-01-08 02:18:48

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 15/44] clk: davinci: Add platform information for TI DM644x PSC

This adds platform-specific declarations for the PSC clocks on TI
DaVinci 644x based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/psc-dm644x.c | 73 ++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 75 insertions(+)
create mode 100644 drivers/clk/davinci/psc-dm644x.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index 78dc1eb..a20e379 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -14,4 +14,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DA830) += psc-da830.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += psc-da850.o
obj-$(CONFIG_ARCH_DAVINCI_DM355) += psc-dm355.o
obj-$(CONFIG_ARCH_DAVINCI_DM365) += psc-dm365.o
+obj-$(CONFIG_ARCH_DAVINCI_DM644x) += psc-dm644x.o
endif
diff --git a/drivers/clk/davinci/psc-dm644x.c b/drivers/clk/davinci/psc-dm644x.c
new file mode 100644
index 0000000..ef5ef14
--- /dev/null
+++ b/drivers/clk/davinci/psc-dm644x.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM644x
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#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 dm644x_psc_info[] __initconst = {
+ LPSC(0, 0, vpss_master, pll1_sysclk3, 0),
+ LPSC(1, 0, vpss_slave, pll1_sysclk3, 0),
+ LPSC(6, 0, emac, pll1_sysclk5, 0),
+ LPSC(9, 0, usb, pll1_sysclk5, 0),
+ LPSC(10, 0, ide, pll1_sysclk5, 0),
+ LPSC(11, 0, vlynq, pll1_sysclk5, 0),
+ LPSC(14, 0, aemif, pll1_sysclk5, 0),
+ LPSC(15, 0, mmcsd, pll1_sysclk5, 0),
+ LPSC(17, 0, asp0, pll1_sysclk5, 0),
+ LPSC(18, 0, i2c, pll1_aux_clk, 0),
+ LPSC(19, 0, uart0, pll1_aux_clk, 0),
+ LPSC(20, 0, uart1, pll1_aux_clk, 0),
+ LPSC(21, 0, uart2, pll1_aux_clk, 0),
+ LPSC(22, 0, spi, pll1_sysclk5, 0),
+ LPSC(23, 0, pwm0, pll1_aux_clk, 0),
+ LPSC(24, 0, pwm1, pll1_aux_clk, 0),
+ LPSC(25, 0, pwm2, pll1_aux_clk, 0),
+ LPSC(26, 0, gpio, pll1_sysclk5, 0),
+ LPSC(27, 0, timer0, pll1_aux_clk, 0),
+ LPSC(28, 0, timer1, pll1_aux_clk, 0),
+ /* REVISIT: why can't this be disabled? */
+ LPSC(29, 0, timer2, pll1_aux_clk, LPSC_ALWAYS_ENABLED),
+ LPSC(31, 0, arm, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ /* REVISIT how to disable? */
+ LPSC(39, 1, dsp, pll1_sysclk1, LPSC_ALWAYS_ENABLED),
+ /* REVISIT how to disable? */
+ LPSC(40, 1, vicp, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ { }
+};
+
+void __init dm644x_psc_clk_init(void __iomem *psc)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = davinci_psc_register_clocks(psc, dm644x_psc_info, 41);
+ if (!clk_data)
+ return;
+
+ clk_register_clkdev(clk_data->clks[0], "master", "vpss");
+ clk_register_clkdev(clk_data->clks[1], "slave", "vpss");
+ clk_register_clkdev(clk_data->clks[6], NULL, "davinci_emac.1");
+ clk_register_clkdev(clk_data->clks[6], "fck", "davinci_mdio.0");
+ clk_register_clkdev(clk_data->clks[9], "usb", NULL);
+ clk_register_clkdev(clk_data->clks[10], NULL, "palm_bk3710");
+ clk_register_clkdev(clk_data->clks[14], "aemif", NULL);
+ clk_register_clkdev(clk_data->clks[15], NULL, "dm6441-mmc.0");
+ clk_register_clkdev(clk_data->clks[17], NULL, "davinci-mcbsp");
+ clk_register_clkdev(clk_data->clks[18], NULL, "i2c_davinci.1");
+ clk_register_clkdev(clk_data->clks[19], NULL, "serial8250.0");
+ clk_register_clkdev(clk_data->clks[20], NULL, "serial8250.1");
+ clk_register_clkdev(clk_data->clks[21], NULL, "serial8250.2");
+ clk_register_clkdev(clk_data->clks[26], "gpio", NULL);
+ clk_register_clkdev(clk_data->clks[27], "timer0", NULL);
+ clk_register_clkdev(clk_data->clks[29], NULL, "davinci-wdt");
+ clk_register_clkdev(clk_data->clks[31], "arm", NULL);
+
+ clk_free_onecell_data(clk_data);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index c7d8c5f..6d2896d 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -20,5 +20,6 @@ void da830_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
void da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
void dm355_psc_clk_init(void __iomem *psc);
void dm365_psc_clk_init(void __iomem *psc);
+void dm644x_psc_clk_init(void __iomem *psc);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:19:00

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 20/44] dt-bindings: clock: Add bindings for TI DA8XX USB PHY clocks

This adds a new binding for TI DA8XX USB PHY clocks. These clocks are part
of a syscon register called CFGCHIP3.

Signed-off-by: David Lechner <[email protected]>
---
.../clock/ti/davinci/da8xx-cfgchip-usb-phy.txt | 55 ++++++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-usb-phy.txt

diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-usb-phy.txt b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-usb-phy.txt
new file mode 100644
index 0000000..8a12e1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-usb-phy.txt
@@ -0,0 +1,55 @@
+Binding for TI DA8XX/OMAP-L13X/AM17XX/AM18XX CFGCHIP USB PHY clocks
+
+TI DA8XX/OMAP-L13X/AM17XX/AM18XX SoCs contain a general purpose set of
+registers call CFGCHIPn. Some of these registers function as the USB PHY
+clocks. This document describes the bindings for those clocks.
+
+Required properties:
+- compatible: shall be one of:
+ - "ti,da830-usb0-phy-clock" for the USB 2.0 PHY
+ - "ti,da830-usb1-phy-clock" for the USB 1.1 PHY
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandle list of clocks corresponding to clock-names
+- clock-names: depends on compatible:
+ - for "ti,da830-usb0-phy-clock" must be "usb_refclkin", "auxclk",
+ "usb0_lpsc"
+ - for "ti,da830-usb1-phy-clock" must be "usb0_phy", "usb_refclkin"
+
+Optional properties:
+- clock-output-names: from common clock binding.
+
+Parent:
+ This node must be a child of a "ti,da830-cfgchip" node.
+
+Assignment:
+ The assigned-clocks and assigned-clock-parents properties from the
+ common clock bindings can be used to indicate which parent clock should
+ be used. Note: for "ti,da830-usb0-phy-clock", only "usb_refclkin" or
+ "auxclk" can be used as the assigned parent clock ("usb0_lpsc" is not
+ an actual parent clock and only used internally).
+
+Examples:
+
+ cfgchip: syscon@1417c {
+ compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+ reg = <0x1417c 0x14>;
+
+ usb0_phy_clk: usb0-phy-clock {
+ compatible = "ti,da830-usb0-phy-clock";
+ #clock-cells = <0>;
+ clocks = <&usb_refclkin>, <&pll0_aux_clk>, <&psc1 1>;
+ clock-names = "usb_refclkin", "auxclk", "usb0_lpsc";
+ clock-output-names = "usb0_phy_clk";
+ };
+
+ usb1_phy_clk: usb1-phy-clock {
+ compatible = "ti,da830-usb1-phy-clock";
+ #clock-cells = <0>;
+ clocks = <&usb0_phy_clk>, <&usb_refclkin>;
+ clock-names = "usb0_phy", "usb_refclkin";
+ clock-output-names = "usb1_phy_clk";
+ };
+ };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
--
2.7.4

2018-01-08 02:19:04

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 25/44] ARM: dm355: add new clock init using common clock framework

This adds the new board-specfic clock init in mach-davinci/dm355.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Also clean up the #includes since we are adding some here.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/dm355.c | 47 +++++++++++++++++++++++++++++++++----------
1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index f294804..f087840 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -8,31 +8,37 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#include <linux/init.h>
+#include <linux/clk-provider.h>
#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/platform_device.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
-#include <linux/spi/spi.h>
+#include <linux/init.h>
#include <linux/platform_data/edma.h>
#include <linux/platform_data/gpio-davinci.h>
#include <linux/platform_data/spi-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>

#include <asm/mach/map.h>

+#include <mach/common.h>
#include <mach/cputype.h>
-#include "psc.h"
-#include <mach/mux.h>
#include <mach/irqs.h>
-#include <mach/time.h>
+#include <mach/mux.h>
#include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>

+#include "asp.h"
#include "davinci.h"
-#include "clock.h"
#include "mux.h"
-#include "asp.h"
+
+#ifndef CONFIG_COMMON_CLK
+#include "clock.h"
+#include "psc.h"
+#endif

#define DM355_UART2_BASE (IO_PHYS + 0x206000)
#define DM355_OSD_BASE (IO_PHYS + 0x70200)
@@ -43,6 +49,7 @@
*/
#define DM355_REF_FREQ 24000000 /* 24 or 36 MHz */

+#ifndef CONFIG_COMMON_CLK
static struct pll_data pll1_data = {
.num = 1,
.phys_base = DAVINCI_PLL1_BASE,
@@ -382,7 +389,7 @@ static struct clk_lookup dm355_clks[] = {
CLK(NULL, "usb", &usb_clk),
CLK(NULL, NULL, NULL),
};
-
+#endif
/*----------------------------------------------------------------------*/

static u64 dm355_spi0_dma_mask = DMA_BIT_MASK(32);
@@ -1046,7 +1053,25 @@ void __init dm355_init(void)

void __init dm355_init_time(void)
{
+#ifdef CONFIG_COMMON_CLK
+ void __iomem *pll1, *pll2, *psc;
+
+ pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_4K);
+ pll2 = ioremap(DAVINCI_PLL2_BASE, SZ_4K);
+ psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+
+ clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM355_REF_FREQ);
+ dm355_pll_clk_init(pll1, pll2);
+ dm355_psc_clk_init(psc);
+
+ /* NOTE: clkout1 can be externally gated by muxing GPIO-18 */
+ clk_register_fixed_factor(NULL, "clkout1", "pll1_aux_clk", 0, 1, 1);
+ clk_register_fixed_factor(NULL, "clkout2", "pll1_sysclkbp", 0, 1, 1);
+ /* NOTE: clkout3 can be externally gated by muxing GPIO-16 */
+ clk_register_fixed_factor(NULL, "clkout3", "pll2_sysclkbp", 0, 1, 1);
+#else
davinci_clk_init(dm355_clks);
+#endif
davinci_timer_init();
}

--
2.7.4

2018-01-08 02:19:07

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 27/44] ARM: dm644x: add new clock init using common clock framework

This adds the new board-specfic clock init in mach-davinci/dm644x.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Also clean up the #includes since we are adding some here.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/dm644x.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index b409801..bc2e243 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -8,28 +8,34 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#include <linux/init.h>
+#include <linux/clk-provider.h>
#include <linux/clk.h>
-#include <linux/serial_8250.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
#include <linux/dmaengine.h>
-#include <linux/platform_device.h>
+#include <linux/init.h>
#include <linux/platform_data/edma.h>
#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>

#include <asm/mach/map.h>

+#include <mach/common.h>
#include <mach/cputype.h>
#include <mach/irqs.h>
-#include "psc.h"
#include <mach/mux.h>
-#include <mach/time.h>
#include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>

+#include "asp.h"
#include "davinci.h"
-#include "clock.h"
#include "mux.h"
-#include "asp.h"
+
+#ifndef CONFIG_COMMON_CLK
+#include "clock.h"
+#include "psc.h"
+#endif

/*
* Device specific clocks
@@ -43,6 +49,7 @@
#define DM644X_EMAC_CNTRL_RAM_OFFSET 0x2000
#define DM644X_EMAC_CNTRL_RAM_SIZE 0x2000

+#ifndef CONFIG_COMMON_CLK
static struct pll_data pll1_data = {
.num = 1,
.phys_base = DAVINCI_PLL1_BASE,
@@ -326,6 +333,7 @@ static struct clk_lookup dm644x_clks[] = {
CLK("davinci-wdt", NULL, &timer2_clk),
CLK(NULL, NULL, NULL),
};
+#endif

static struct emac_platform_data dm644x_emac_pdata = {
.ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET,
@@ -934,7 +942,19 @@ void __init dm644x_init(void)

void __init dm644x_init_time(void)
{
+#ifdef CONFIG_COMMON_CLK
+ void __iomem *pll1, *pll2, *psc;
+
+ pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_4K);
+ pll2 = ioremap(DAVINCI_PLL2_BASE, SZ_4K);
+ psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+
+ clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM644X_REF_FREQ);
+ dm644x_pll_clk_init(pll1, pll2);
+ dm644x_psc_clk_init(psc);
+#else
davinci_clk_init(dm644x_clks);
+#endif
davinci_timer_init();
}

--
2.7.4

2018-01-08 02:19:12

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 29/44] ARM: da8xx: add new USB PHY clock init using common clock framework

This adds the new USB PHY clock init in mach-davinci/usb-da8xx.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/usb-da8xx.c | 84 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c
index d480a02..d7340670 100644
--- a/arch/arm/mach-davinci/usb-da8xx.c
+++ b/arch/arm/mach-davinci/usb-da8xx.c
@@ -2,28 +2,36 @@
/*
* DA8xx USB
*/
+#include <linux/clk-provider.h>
#include <linux/clk.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
#include <linux/platform_data/usb-davinci.h>
#include <linux/platform_device.h>
#include <linux/usb/musb.h>

-#include <mach/clock.h>
#include <mach/common.h>
#include <mach/cputype.h>
#include <mach/da8xx.h>
#include <mach/irqs.h>

+#ifndef CONFIG_COMMON_CLK
+#include <mach/clock.h>
#include "clock.h"
+#endif

#define DA8XX_USB0_BASE 0x01e00000
#define DA8XX_USB1_BASE 0x01e25000

+#ifndef CONFIG_COMMON_CLK
static struct clk *usb20_clk;
+#endif

static struct platform_device da8xx_usb_phy = {
.name = "da8xx-usb-phy",
@@ -128,6 +136,7 @@ int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
return platform_device_register(&da8xx_usb11_device);
}

+#ifndef CONFIG_COMMON_CLK
static struct clk usb_refclkin = {
.name = "usb_refclkin",
.set_rate = davinci_simple_set_rate,
@@ -354,3 +363,76 @@ int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)

return ret;
}
+#else
+/**
+ * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
+ *
+ * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
+ * or "pll0_aux_clk" if false.
+ */
+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");
+ if (IS_ERR(cfgchip))
+ cfgchip = syscon_regmap_lookup_by_pdevname("syscon");
+ if (IS_ERR(cfgchip))
+ return PTR_ERR(cfgchip);
+
+ usb0_psc_clk = clk_get_sys("musb-da8xx", NULL);
+ if (IS_ERR(usb0_psc_clk))
+ return PTR_ERR(usb0_psc_clk);
+
+ clk = da8xx_usb0_phy_clk_register("usb0_phy_clk", "usb_refclkin",
+ "pll0_aux_clk", usb0_psc_clk, cfgchip);
+ if (IS_ERR(clk)) {
+ clk_put(usb0_psc_clk);
+ return PTR_ERR(clk);
+ }
+
+ parent = clk_hw_get_parent_by_index(__clk_get_hw(clk),
+ use_usb_refclkin ? 0 : 1);
+ if (parent)
+ clk_set_parent(clk, parent->clk);
+ else
+ pr_warn("%s: Failed to find parent clock\n", __func__);
+
+ return clk_register_clkdev(clk, "usb20_phy", "da8xx-usb-phy");
+}
+
+/**
+ * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
+ *
+ * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
+ * or "usb0_phy_clk" if false.
+ */
+int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
+{
+ struct regmap *cfgchip;
+ struct clk *clk;
+ struct clk_hw *parent;
+
+ cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");
+ if (IS_ERR(cfgchip))
+ cfgchip = syscon_regmap_lookup_by_pdevname("syscon");
+ if (IS_ERR(cfgchip))
+ return PTR_ERR(cfgchip);
+
+ clk = da8xx_usb1_phy_clk_register("usb1_phy_clk", "usb0_phy_clk",
+ "usb_refclkin", cfgchip);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ parent = clk_hw_get_parent_by_index(__clk_get_hw(clk),
+ use_usb_refclkin ? 1 : 0);
+ if (parent)
+ clk_set_parent(clk, parent->clk);
+ else
+ pr_warn("%s: Failed to find parent clock\n", __func__);
+
+ return clk_register_clkdev(clk, "usb11_phy", "da8xx-usb-phy");
+}
+#endif
--
2.7.4

2018-01-08 02:19:36

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 28/44] ARM: dm646x: add new clock init using common clock framework

This adds the new board-specfic clock init in mach-davinci/dm646x.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Also clean up the #includes since we are adding some here.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/dm646x.c | 41 +++++++++++++++++++++++++++++++++--------
1 file changed, 33 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index d4d7658..bdaf769 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -8,29 +8,35 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/platform_device.h>
#include <linux/platform_data/edma.h>
#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>

#include <asm/mach/map.h>

+#include <mach/common.h>
#include <mach/cputype.h>
#include <mach/irqs.h>
-#include "psc.h"
#include <mach/mux.h>
-#include <mach/time.h>
#include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>

+#include "asp.h"
#include "davinci.h"
-#include "clock.h"
#include "mux.h"
-#include "asp.h"
+
+#ifndef CONFIG_COMMON_CLK
+#include "clock.h"
+#include "psc.h"
+#endif

#define DAVINCI_VPIF_BASE (0x01C12000)

@@ -46,6 +52,7 @@
#define DM646X_EMAC_CNTRL_RAM_OFFSET 0x2000
#define DM646X_EMAC_CNTRL_RAM_SIZE 0x2000

+#ifndef CONFIG_COMMON_CLK
static struct pll_data pll1_data = {
.num = 1,
.phys_base = DAVINCI_PLL1_BASE,
@@ -356,6 +363,7 @@ static struct clk_lookup dm646x_clks[] = {
CLK(NULL, "vpif1", &vpif1_clk),
CLK(NULL, NULL, NULL),
};
+#endif

static struct emac_platform_data dm646x_emac_pdata = {
.ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET,
@@ -953,9 +961,26 @@ void __init dm646x_init(void)
void __init dm646x_init_time(unsigned long ref_clk_rate,
unsigned long aux_clkin_rate)
{
+#ifdef CONFIG_COMMON_CLK
+ void __iomem *pll1, *pll2, *psc;
+ struct clk *clk;
+
+ pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_4K);
+ pll2 = ioremap(DAVINCI_PLL2_BASE, SZ_4K);
+ psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+
+ clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, ref_clk_rate);
+ clk_register_fixed_rate(NULL, "aux_clkin", NULL, 0, aux_clkin_rate);
+ dm646x_pll_clk_init(pll1, pll2);
+ dm646x_psc_clk_init(psc);
+ /* no LPSC, always enabled; c.f. spruep9a */
+ clk = clk_register_fixed_factor(NULL, "timer2", "pll1_sysclk3", 0, 1, 1);
+ clk_register_clkdev(clk, NULL, "davinci-wdt");
+#else
ref_clk.rate = ref_clk_rate;
aux_clkin.rate = aux_clkin_rate;
davinci_clk_init(dm646x_clks);
+#endif
davinci_timer_init();
}

--
2.7.4

2018-01-08 02:20:16

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 26/44] ARM: dm365: add new clock init using common clock framework

This adds the new board-specfic clock init in mach-davinci/dm365.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Also clean up the #includes since we are adding some here.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/dm365.c | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 1e3df9d..fbbe31c 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -12,32 +12,38 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#include <linux/init.h>
+#include <linux/clk-provider.h>
#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/platform_device.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
-#include <linux/spi/spi.h>
+#include <linux/init.h>
#include <linux/platform_data/edma.h>
#include <linux/platform_data/gpio-davinci.h>
#include <linux/platform_data/keyscan-davinci.h>
#include <linux/platform_data/spi-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>

#include <asm/mach/map.h>

+#include <mach/common.h>
#include <mach/cputype.h>
-#include "psc.h"
-#include <mach/mux.h>
#include <mach/irqs.h>
-#include <mach/time.h>
+#include <mach/mux.h>
#include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>

+#include "asp.h"
#include "davinci.h"
-#include "clock.h"
#include "mux.h"
-#include "asp.h"
+
+#ifndef CONFIG_COMMON_CLK
+#include "clock.h"
+#include "psc.h"
+#endif

#define DM365_REF_FREQ 24000000 /* 24 MHz on the DM365 EVM */
#define DM365_RTC_BASE 0x01c69000
@@ -54,6 +60,7 @@
#define DM365_EMAC_CNTRL_RAM_OFFSET 0x1000
#define DM365_EMAC_CNTRL_RAM_SIZE 0x2000

+#ifndef CONFIG_COMMON_CLK
static struct pll_data pll1_data = {
.num = 1,
.phys_base = DAVINCI_PLL1_BASE,
@@ -485,7 +492,7 @@ static struct clk_lookup dm365_clks[] = {
CLK(NULL, "mjcp", &mjcp_clk),
CLK(NULL, NULL, NULL),
};
-
+#endif
/*----------------------------------------------------------------------*/

#define INTMUX 0x18
@@ -1171,7 +1178,19 @@ void __init dm365_init(void)

void __init dm365_init_time(void)
{
+#ifdef CONFIG_COMMON_CLK
+ void __iomem *pll1, *pll2, *psc;
+
+ pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_4K);
+ pll2 = ioremap(DAVINCI_PLL2_BASE, SZ_4K);
+ psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+
+ clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM365_REF_FREQ);
+ dm365_pll_clk_init(pll1, pll2);
+ dm365_psc_clk_init(psc);
+#else
davinci_clk_init(dm365_clks);
+#endif
davinci_timer_init();
}

--
2.7.4

2018-01-08 02:20:33

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 24/44] ARM: da850: add new clock init using common clock framework

This adds the new board-specfic clock init in mach-davinci/da850.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Some CFGCHIP* #defines are removed since they are included in the
linux/mfd/da8xx-cfgchip.h header file.

Also clean up the #includes since we are adding some here.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/da850.c | 74 +++++++++++++++++++++++++++++++++++--------
1 file changed, 61 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 34117e61..4804096 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -11,39 +11,44 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
+#include <linux/cpufreq.h>
#include <linux/gpio.h>
#include <linux/init.h>
-#include <linux/clk.h>
+#include <linux/log2.h>
+#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/platform_data/gpio-davinci.h>
#include <linux/platform_device.h>
-#include <linux/cpufreq.h>
#include <linux/regulator/consumer.h>
-#include <linux/platform_data/gpio-davinci.h>

#include <asm/mach/map.h>

-#include "psc.h"
-#include <mach/irqs.h>
-#include <mach/cputype.h>
#include <mach/common.h>
-#include <mach/time.h>
-#include <mach/da8xx.h>
#include <mach/cpufreq.h>
+#include <mach/cputype.h>
+#include <mach/da8xx.h>
+#include <mach/irqs.h>
#include <mach/pm.h>
+#include <mach/time.h>

-#include "clock.h"
#include "mux.h"

+#ifndef CONFIG_COMMON_CLK
+#include "clock.h"
+#include "psc.h"
+#endif
+
#define DA850_PLL1_BASE 0x01e1a000
#define DA850_TIMER64P2_BASE 0x01f0c000
#define DA850_TIMER64P3_BASE 0x01f0d000

#define DA850_REF_FREQ 24000000

-#define CFGCHIP3_ASYNC3_CLKSRC BIT(4)
-#define CFGCHIP3_PLL1_MASTER_LOCK BIT(5)
-#define CFGCHIP0_PLL_MASTER_LOCK BIT(4)
-
+#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

/*
* Device specific mux setup
@@ -1170,6 +1176,7 @@ int da850_register_cpufreq(char *async_clk)
return platform_device_register(&da850_cpufreq_device);
}

+#ifndef CONFIG_COMMON_CLK
static int da850_round_armrate(struct clk *clk, unsigned long rate)
{
int ret = 0, diff;
@@ -1232,12 +1239,14 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long rate)

return 0;
}
+#endif /* CONFIG_COMMON_CLK */
#else
int __init da850_register_cpufreq(char *async_clk)
{
return 0;
}

+#ifndef CONFIG_COMMON_CLK
static int da850_set_armrate(struct clk *clk, unsigned long rate)
{
return -EINVAL;
@@ -1252,6 +1261,7 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate)
{
return clk->rate;
}
+#endif /* CONFIG_COMMON_CLK */
#endif

/* VPIF resource, platform data */
@@ -1395,6 +1405,44 @@ void __init da850_init(void)

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);
+ da850_pll_clk_init(pll0, pll1);
+ 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);
+ /* 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__);
+ da850_psc_clk_init(psc0, psc1);
+ clk = clk_register_fixed_factor(NULL, "i2c0", "pll0_aux_clk", 0, 1, 1);
+ clk_register_clkdev(clk, NULL, "i2c_davinci.1");
+ clk = clk_register_fixed_factor(NULL, "timer0", "pll0_aux_clk", 0, 1, 1);
+ clk_register_clkdev(clk, "timer0", NULL);
+ clk = clk_register_fixed_factor(NULL, "timer1", "pll0_aux_clk", 0, 1, 1);
+ clk_register_clkdev(clk, NULL, "davinci-wdt");
+ clk = clk_register_fixed_factor(NULL, "rmii", "pll0_sysclk7", 0, 1, 1);
+ clk_register_clkdev(clk, "rmii", NULL);
+ clk = clk_register_gate(NULL, "ehrpwm_tbclk", "ehrpwm", 0,
+ DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG),
+ ilog2(CFGCHIP1_TBCLKSYNC), 0, NULL);
+ clk_register_clkdev(clk, "tbclk", "ehrpwm.0");
+ clk_register_clkdev(clk, "tbclk", "ehrpwm.1");
+#else
davinci_clk_init(da850_clks);
+#endif
davinci_timer_init();
}
--
2.7.4

2018-01-08 02:18:58

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 18/44] dt-bindings: clock: Add binding for TI DA8XX CFGCHIP mux clocks

This adds a new binding for multiplexer clocks that are part of the
CFGCHIPn registers on TI DA8XX-like SoCs. Currently, there are only
bindings given for the ASYNC3 clock domain, but there are additional
clock multiplexers in this syscon that could be added in the future
if needed.

Signed-off-by: David Lechner <[email protected]>
---
.../clock/ti/davinci/da8xx-cfgchip-mux.txt | 42 ++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-mux.txt

diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-mux.txt b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-mux.txt
new file mode 100644
index 0000000..8c874ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-mux.txt
@@ -0,0 +1,42 @@
+Binding for TI DA8XX/OMAP-L13X/AM17XX/AM18XX CFGCHIP multiplexer clocks
+
+TI DA8XX/OMAP-L13X/AM17XX/AM18XX SoCs contain a general purpose set of
+registers call CFGCHIPn. Some of these registers function as clock
+multiplexers. This document describes the bindings for those clocks.
+
+Required properties:
+- compatible: shall be "ti,da850-async3-clock".
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandle list of clocks corresponding to clock-names
+- clock-names: must include the following: "pll0_sysclk2", "pll1_sysclk2".
+
+Optional properties:
+- clock-output-names: from common clock binding.
+
+Parent:
+This node must be a child of a "ti,da830-cfgchip" node.
+
+Assignment:
+The assigned-clocks and assigned-clock-parents from the common clock bindings
+can be used to indicate which parent clock should be used.
+
+Examples:
+
+ cfgchip: syscon@1417c {
+ compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+ reg = <0x1417c 0x14>;
+
+ async3_clk: async3 {
+ compatible = "ti,da850-async3-clock";
+ #clock-cells = <0>;
+ clocks = <&pll0_sysclk 2>, <&pll1_sysclk 2>;
+ clock-names = "pll0_sysclk2", "pll1_sysclk2";
+ assigned-clocks = <&async3_clk>;
+ assigned-clock-parents = <&pll1_sysclk 2>;
+ clock-output-names = "async3";
+ };
+ };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
+
--
2.7.4

2018-01-08 02:21:01

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 23/44] ARM: da830: add new clock init using common clock framework

This adds the new board-specfic clock init in mach-davinci/da830.c using
the new common clock framework drivers.

The #ifdefs are needed to prevent compile errors until the entire
ARCH_DAVINCI is converted.

Also clean up the #includes since we are adding some here.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/da830.c | 41 +++++++++++++++++++++++++++++++++++------
1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 350d767..cbb351d 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -8,23 +8,29 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
#include <linux/gpio.h>
#include <linux/init.h>
-#include <linux/clk.h>
#include <linux/platform_data/gpio-davinci.h>

#include <asm/mach/map.h>

-#include "psc.h"
-#include <mach/irqs.h>
-#include <mach/cputype.h>
#include <mach/common.h>
-#include <mach/time.h>
+#include <mach/cputype.h>
#include <mach/da8xx.h>
+#include <mach/irqs.h>
+#include <mach/time.h>

-#include "clock.h"
#include "mux.h"

+#ifndef CONFIG_COMMON_CLK
+#include "clock.h"
+#include "psc.h"
+#endif
+
/* Offsets of the 8 compare registers on the da830 */
#define DA830_CMP12_0 0x60
#define DA830_CMP12_1 0x64
@@ -37,6 +43,7 @@

#define DA830_REF_FREQ 24000000

+#ifndef CONFIG_COMMON_CLK
static struct pll_data pll0_data = {
.num = 1,
.phys_base = DA8XX_PLL0_BASE,
@@ -432,6 +439,7 @@ static struct clk_lookup da830_clks[] = {
CLK(NULL, "rmii", &rmii_clk),
CLK(NULL, NULL, NULL),
};
+#endif

/*
* Device specific mux setup
@@ -1223,6 +1231,27 @@ void __init da830_init(void)

void __init da830_init_time(void)
{
+#ifdef CONFIG_COMMON_CLK
+ void __iomem *pll0, *psc0, *psc1;
+ struct clk *clk;
+
+ pll0 = ioremap(DA8XX_PLL0_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, DA830_REF_FREQ);
+ da830_pll_clk_init(pll0);
+ da830_psc_clk_init(psc0, psc1);
+ clk = clk_register_fixed_factor(NULL, "i2c0", "pll0_aux_clk", 0, 1, 1);
+ clk_register_clkdev(clk, NULL, "i2c_davinci.1");
+ clk = clk_register_fixed_factor(NULL, "timer0", "pll0_aux_clk", 0, 1, 1);
+ clk_register_clkdev(clk, "timer0", NULL);
+ clk = clk_register_fixed_factor(NULL, "timer1", "pll0_aux_clk", 0, 1, 1);
+ clk_register_clkdev(clk, NULL, "davinci-wdt");
+ clk = clk_register_fixed_factor(NULL, "rmii", "pll0_sysclk7", 0, 1, 1);
+ clk_register_clkdev(clk, "rmii", NULL);
+#else
davinci_clk_init(da830_clks);
+#endif
davinci_timer_init();
}
--
2.7.4

2018-01-08 02:21:20

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 22/44] ARM: davinci: move davinci_clk_init() to init_time

This moves the call of davinci_clk_init() from map_io to init_time for all
boards.

This is the proper place to init clocks. This is also done in preparation
for moving to the common clock framework.

dm646x is a special case because we need to handle different ref_clk rates
depending on which board is being used. The clock init in this case is
modified to set the rate before registering the clocks instead of using
davinci_set_refclk_rate() to recalculate the entire clock tree after all
of the clocks are registered.

Also, the cpu_clks field is removed from struct davinci_soc_info since it
is no longer needed.

Signed-off-by: David Lechner <[email protected]>
---
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/da830.c | 7 +++++--
arch/arm/mach-davinci/da850.c | 7 +++++--
arch/arm/mach-davinci/da8xx-dt.c | 2 +-
arch/arm/mach-davinci/davinci.h | 4 ++++
arch/arm/mach-davinci/dm355.c | 8 ++++++--
arch/arm/mach-davinci/dm365.c | 8 ++++++--
arch/arm/mach-davinci/dm644x.c | 8 ++++++--
arch/arm/mach-davinci/dm646x.c | 22 +++++++++++-----------
arch/arm/mach-davinci/include/mach/common.h | 1 -
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +++
21 files changed, 70 insertions(+), 39 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index a58bfca..7adf009 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -638,7 +638,7 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
.atag_offset = 0x100,
.map_io = da830_evm_map_io,
.init_irq = cp_intc_init,
- .init_time = davinci_timer_init,
+ .init_time = da830_init_time,
.init_machine = da830_evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 6039ec1..8602d0d 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1481,7 +1481,7 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
.atag_offset = 0x100,
.map_io = da850_evm_map_io,
.init_irq = cp_intc_init,
- .init_time = davinci_timer_init,
+ .init_time = da850_init_time,
.init_machine = da850_evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index d60d998..3c15cb7 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -416,7 +416,7 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
.atag_offset = 0x100,
.map_io = dm355_evm_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm355_init_time,
.init_machine = dm355_evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 1e7e9b8..3ebc89d 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -271,7 +271,7 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
.atag_offset = 0x100,
.map_io = dm355_leopard_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm355_init_time,
.init_machine = dm355_leopard_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 17b2c29..3daeac7 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -774,7 +774,7 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
.atag_offset = 0x100,
.map_io = dm365_evm_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm365_init_time,
.init_machine = dm365_evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 5e1afc2..8d8c4ab 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -817,7 +817,7 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
.atag_offset = 0x100,
.map_io = davinci_evm_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm644x_init_time,
.init_machine = davinci_evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 003bbe5..2d37f5b 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -44,10 +44,8 @@
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/serial.h>
-#include <mach/clock.h>

#include "davinci.h"
-#include "clock.h"

#define NAND_BLOCK_SIZE SZ_128K

@@ -716,14 +714,23 @@ static void __init evm_init_i2c(void)
}
#endif

+#define DM646X_REF_FREQ 27000000
+#define DM646X_AUX_FREQ 24000000
#define DM6467T_EVM_REF_FREQ 33000000

static void __init davinci_map_io(void)
{
dm646x_init();
+}

- if (machine_is_davinci_dm6467tevm())
- davinci_set_refclk_rate(DM6467T_EVM_REF_FREQ);
+static void __init dm646x_evm_init_time(void)
+{
+ dm646x_init_time(DM646X_REF_FREQ, DM646X_AUX_FREQ);
+}
+
+static void __init dm6467t_evm_init_time(void)
+{
+ dm646x_init_time(DM6467T_EVM_REF_FREQ, DM646X_AUX_FREQ);
}

#define DM646X_EVM_PHY_ID "davinci_mdio-0:01"
@@ -797,7 +804,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
.atag_offset = 0x100,
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm646x_evm_init_time,
.init_machine = evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
@@ -807,7 +814,7 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
.atag_offset = 0x100,
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm6467t_evm_init_time,
.init_machine = evm_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 0b23cf3..f9a725a 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -570,7 +570,7 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
.atag_offset = 0x100,
.map_io = mityomapl138_map_io,
.init_irq = cp_intc_init,
- .init_time = davinci_timer_init,
+ .init_time = da850_init_time,
.init_machine = mityomapl138_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 1e27baa..ff871a0 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -227,7 +227,7 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
.atag_offset = 0x100,
.map_io = davinci_ntosd2_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm644x_init_time,
.init_machine = davinci_ntosd2_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 88ab45c..bc8a747 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -334,7 +334,7 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
.atag_offset = 0x100,
.map_io = omapl138_hawk_map_io,
.init_irq = cp_intc_init,
- .init_time = davinci_timer_init,
+ .init_time = da850_init_time,
.init_machine = omapl138_hawk_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 1f02d4e..2922da9 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -150,7 +150,7 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
.atag_offset = 0x100,
.map_io = davinci_sffsdr_map_io,
.init_irq = davinci_irq_init,
- .init_time = davinci_timer_init,
+ .init_time = dm644x_init_time,
.init_machine = davinci_sffsdr_init,
.init_late = davinci_init_late,
.dma_zone_size = SZ_128M,
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 57ab18c..350d767 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -1200,7 +1200,6 @@ static const struct davinci_soc_info davinci_soc_info_da830 = {
.jtag_id_reg = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG,
.ids = da830_ids,
.ids_num = ARRAY_SIZE(da830_ids),
- .cpu_clks = da830_clks,
.psc_bases = da830_psc_bases,
.psc_bases_num = ARRAY_SIZE(da830_psc_bases),
.pinmux_base = DA8XX_SYSCFG0_BASE + 0x120,
@@ -1220,6 +1219,10 @@ void __init da830_init(void)

da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module");
+}

- davinci_clk_init(davinci_soc_info_da830.cpu_clks);
+void __init da830_init_time(void)
+{
+ davinci_clk_init(da830_clks);
+ davinci_timer_init();
}
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index aa37cbd..34117e61 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -1353,7 +1353,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = {
.jtag_id_reg = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG,
.ids = da850_ids,
.ids_num = ARRAY_SIZE(da850_ids),
- .cpu_clks = da850_clks,
.psc_bases = da850_psc_bases,
.psc_bases_num = ARRAY_SIZE(da850_psc_bases),
.pinmux_base = DA8XX_SYSCFG0_BASE + 0x120,
@@ -1392,6 +1391,10 @@ void __init da850_init(void)
v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
v &= ~CFGCHIP3_PLL1_MASTER_LOCK;
__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
+}

- davinci_clk_init(davinci_soc_info_da850.cpu_clks);
+void __init da850_init_time(void)
+{
+ davinci_clk_init(da850_clks);
+ davinci_timer_init();
}
diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index 779e8ce..ab199f4 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -96,7 +96,7 @@ static const char *const da850_boards_compat[] __initconst = {

DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
.map_io = da850_init,
- .init_time = davinci_timer_init,
+ .init_time = da850_init_time,
.init_machine = da850_init_machine,
.dt_compat = da850_boards_compat,
.init_late = davinci_init_late,
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index c62b90c..270cef8 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -83,6 +83,7 @@ int davinci_init_wdt(void);

/* DM355 function declarations */
void dm355_init(void);
+void dm355_init_time(void);
void dm355_init_spi0(unsigned chipselect_mask,
const struct spi_board_info *info, unsigned len);
void dm355_init_asp1(u32 evt_enable);
@@ -91,6 +92,7 @@ int dm355_gpio_register(void);

/* DM365 function declarations */
void dm365_init(void);
+void dm365_init_time(void);
void dm365_init_asp(void);
void dm365_init_vc(void);
void dm365_init_ks(struct davinci_ks_platform_data *pdata);
@@ -102,12 +104,14 @@ int dm365_gpio_register(void);

/* DM644x function declarations */
void dm644x_init(void);
+void dm644x_init_time(void);
void dm644x_init_asp(void);
int dm644x_init_video(struct vpfe_config *, struct vpbe_config *);
int dm644x_gpio_register(void);

/* DM646x function declarations */
void dm646x_init(void);
+void dm646x_init_time(unsigned long ref_clk_rate, unsigned long aux_clkin_rate);
void dm646x_init_mcasp0(struct snd_platform_data *pdata);
void dm646x_init_mcasp1(struct snd_platform_data *pdata);
int dm646x_init_edma(struct edma_rsv_info *rsv);
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 938747f..f294804 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -1012,7 +1012,6 @@ static const struct davinci_soc_info davinci_soc_info_dm355 = {
.jtag_id_reg = 0x01c40028,
.ids = dm355_ids,
.ids_num = ARRAY_SIZE(dm355_ids),
- .cpu_clks = dm355_clks,
.psc_bases = dm355_psc_bases,
.psc_bases_num = ARRAY_SIZE(dm355_psc_bases),
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
@@ -1043,7 +1042,12 @@ void __init dm355_init(void)
{
davinci_common_init(&davinci_soc_info_dm355);
davinci_map_sysmod();
- davinci_clk_init(davinci_soc_info_dm355.cpu_clks);
+}
+
+void __init dm355_init_time(void)
+{
+ davinci_clk_init(dm355_clks);
+ davinci_timer_init();
}

int __init dm355_init_video(struct vpfe_config *vpfe_cfg,
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 5d9f96d..1e3df9d 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -1116,7 +1116,6 @@ static const struct davinci_soc_info davinci_soc_info_dm365 = {
.jtag_id_reg = 0x01c40028,
.ids = dm365_ids,
.ids_num = ARRAY_SIZE(dm365_ids),
- .cpu_clks = dm365_clks,
.psc_bases = dm365_psc_bases,
.psc_bases_num = ARRAY_SIZE(dm365_psc_bases),
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
@@ -1168,7 +1167,12 @@ void __init dm365_init(void)
{
davinci_common_init(&davinci_soc_info_dm365);
davinci_map_sysmod();
- davinci_clk_init(davinci_soc_info_dm365.cpu_clks);
+}
+
+void __init dm365_init_time(void)
+{
+ davinci_clk_init(dm365_clks);
+ davinci_timer_init();
}

static struct resource dm365_vpss_resources[] = {
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 6b41e1c..b409801 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -905,7 +905,6 @@ static const struct davinci_soc_info davinci_soc_info_dm644x = {
.jtag_id_reg = 0x01c40028,
.ids = dm644x_ids,
.ids_num = ARRAY_SIZE(dm644x_ids),
- .cpu_clks = dm644x_clks,
.psc_bases = dm644x_psc_bases,
.psc_bases_num = ARRAY_SIZE(dm644x_psc_bases),
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
@@ -931,7 +930,12 @@ void __init dm644x_init(void)
{
davinci_common_init(&davinci_soc_info_dm644x);
davinci_map_sysmod();
- davinci_clk_init(davinci_soc_info_dm644x.cpu_clks);
+}
+
+void __init dm644x_init_time(void)
+{
+ davinci_clk_init(dm644x_clks);
+ davinci_timer_init();
}

int __init dm644x_init_video(struct vpfe_config *vpfe_cfg,
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 6fc06a6..d4d7658 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -39,12 +39,6 @@
#define VSCLKDIS_MASK (BIT_MASK(11) | BIT_MASK(10) | BIT_MASK(9) |\
BIT_MASK(8))

-/*
- * Device specific clocks
- */
-#define DM646X_REF_FREQ 27000000
-#define DM646X_AUX_FREQ 24000000
-
#define DM646X_EMAC_BASE 0x01c80000
#define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000)
#define DM646X_EMAC_CNTRL_OFFSET 0x0000
@@ -64,13 +58,12 @@ static struct pll_data pll2_data = {

static struct clk ref_clk = {
.name = "ref_clk",
- .rate = DM646X_REF_FREQ,
- .set_rate = davinci_simple_set_rate,
+ /* rate is initalized in dm646x_init_time() */
};

static struct clk aux_clkin = {
.name = "aux_clkin",
- .rate = DM646X_AUX_FREQ,
+ /* rate is initalized in dm646x_init_time() */
};

static struct clk pll1_clk = {
@@ -888,7 +881,6 @@ static const struct davinci_soc_info davinci_soc_info_dm646x = {
.jtag_id_reg = 0x01c40028,
.ids = dm646x_ids,
.ids_num = ARRAY_SIZE(dm646x_ids),
- .cpu_clks = dm646x_clks,
.psc_bases = dm646x_psc_bases,
.psc_bases_num = ARRAY_SIZE(dm646x_psc_bases),
.pinmux_base = DAVINCI_SYSTEM_MODULE_BASE,
@@ -956,7 +948,15 @@ void __init dm646x_init(void)
{
davinci_common_init(&davinci_soc_info_dm646x);
davinci_map_sysmod();
- davinci_clk_init(davinci_soc_info_dm646x.cpu_clks);
+}
+
+void __init dm646x_init_time(unsigned long ref_clk_rate,
+ unsigned long aux_clkin_rate)
+{
+ ref_clk.rate = ref_clk_rate;
+ aux_clkin.rate = aux_clkin_rate;
+ davinci_clk_init(dm646x_clks);
+ davinci_timer_init();
}

static int __init dm646x_init_devices(void)
diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
index 19b9346..f0d5e858 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -53,7 +53,6 @@ struct davinci_soc_info {
u32 jtag_id_reg;
struct davinci_id *ids;
unsigned long ids_num;
- struct clk_lookup *cpu_clks;
u32 *psc_bases;
unsigned long psc_bases_num;
u32 pinmux_base;
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 751d2ac..3481a0d 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -87,7 +87,10 @@ extern unsigned int da850_max_speed;
#define DA8XX_ARM_RAM_BASE 0xffff0000

void da830_init(void);
+void da830_init_time(void);
+
void da850_init(void);
+void da850_init_time(void);

int da830_register_edma(struct edma_rsv_info *rsv);
int da850_register_edma(struct edma_rsv_info *rsv[2]);
--
2.7.4

2018-01-08 02:18:56

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 19/44] clk: davinci: New driver for TI DA8XX CFGCHIP clocks

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 <[email protected]>
---
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 <[email protected]>
+ */
+
+#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
+struct da8xx_cfgchip_gate_clk {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u32 reg;
+ u32 mask;
+};
+
+#define to_da8xx_cfgchip_gate_clk(_hw) \
+ container_of((_hw), struct da8xx_cfgchip_gate_clk, hw)
+
+static int da8xx_cfgchip_gate_clk_enable(struct clk_hw *hw)
+{
+ struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
+
+ return regmap_write_bits(clk->regmap, clk->reg, clk->mask, clk->mask);
+}
+
+static void da8xx_cfgchip_gate_clk_disable(struct clk_hw *hw)
+{
+ struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
+
+ regmap_write_bits(clk->regmap, clk->reg, clk->mask, 0);
+}
+
+static int da8xx_cfgchip_gate_clk_is_enabled(struct clk_hw *hw)
+{
+ struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
+ unsigned int val;
+
+ regmap_read(clk->regmap, clk->reg, &val);
+
+ return !!(val & clk->mask);
+}
+
+static const struct clk_ops da8xx_cfgchip_gate_clk_ops = {
+ .enable = da8xx_cfgchip_gate_clk_enable,
+ .disable = da8xx_cfgchip_gate_clk_disable,
+ .is_enabled = da8xx_cfgchip_gate_clk_is_enabled,
+};
+
+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));
+ return;
+ }
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return;
+
+ init.name = name;
+ init.ops = &da8xx_cfgchip_gate_clk_ops;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.flags = 0;
+
+ clk->hw.init = &init;
+ clk->regmap = regmap;
+ clk->reg = reg;
+ clk->mask = mask;
+
+ ret = clk_hw_register(NULL, &clk->hw);
+ if (ret) {
+ pr_err("%s: failed to register %s (%d)\n", __func__,
+ np->full_name, ret);
+ return;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_simple_get, &clk->hw);
+}
+
+static void da8xx_tbclk_init(struct device_node *np)
+{
+ da8xx_cfgchip_gate_clk_init(np, CFGCHIP(1), CFGCHIP1_TBCLKSYNC);
+}
+CLK_OF_DECLARE(da8xx_tbclk, "ti,da830-tbclk", da8xx_tbclk_init);
+
+struct da8xx_cfgchip_mux_clk {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u32 reg;
+ u32 mask;
+};
+
+#define to_da8xx_cfgchip_mux_clk(_hw) \
+ container_of((_hw), struct da8xx_cfgchip_mux_clk, hw)
+
+static int da8xx_cfgchip_mux_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw);
+ unsigned int val = index ? clk->mask : 0;
+
+ return regmap_write_bits(clk->regmap, clk->reg, clk->mask, val);
+}
+
+static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw)
+{
+ struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw);
+ unsigned int val;
+
+ regmap_read(clk->regmap, clk->reg, &val);
+
+ return (val & clk->mask) ? 1 : 0;
+}
+
+static const struct clk_ops da8xx_cfgchip_mux_clk_ops = {
+ .set_parent = da8xx_cfgchip_mux_clk_set_parent,
+ .get_parent = da8xx_cfgchip_mux_clk_get_parent,
+};
+
+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;
+ }
+
+ 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));
+ return;
+ }
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return;
+
+ init.name = name;
+ init.ops = &da8xx_cfgchip_mux_clk_ops;
+ init.parent_names = parent_names;
+ init.num_parents = 2;
+ init.flags = 0;
+
+ clk->hw.init = &init;
+ clk->regmap = regmap;
+ clk->reg = reg;
+ clk->mask = mask;
+
+ ret = clk_hw_register(NULL, &clk->hw);
+ if (ret) {
+ pr_err("%s: failed to register %s (%d)\n", __func__,
+ np->full_name, ret);
+ return;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_simple_get, &clk->hw);
+}
+
+static void da8xx_async3_init(struct device_node *np)
+{
+ da8xx_cfgchip_mux_clk_init(np, CFGCHIP(3), CFGCHIP3_ASYNC3_CLKSRC);
+}
+CLK_OF_DECLARE(da8xx_async3, "ti,da850-async3-clock", da8xx_async3_init);
+#endif
--
2.7.4

2018-01-08 02:21:50

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 21/44] clk: davinci: New driver for TI DA8XX USB PHY clocks

This adds a new driver for the USB PHY clocks in the CFGCHIP2 syscon
register on TI DA8XX-type SoCs.

The USB0 (USB 2.0) PHY clock is an interesting case because it calls
clk_enable() in a reentrant way. The USB 2.0 PSC only has to be enabled
temporarily while we are locking the PLL, which takes place during the
clk_enable() callback.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/da8xx-usb-phy-clk.c | 425 ++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 13 +
3 files changed, 439 insertions(+)
create mode 100644 drivers/clk/davinci/da8xx-usb-phy-clk.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index 11178b7..4c772a7 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -2,6 +2,7 @@

ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx-cfgchip.o
+obj-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx-usb-phy-clk.o

obj-y += pll.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += pll-da830.o
diff --git a/drivers/clk/davinci/da8xx-usb-phy-clk.c b/drivers/clk/davinci/da8xx-usb-phy-clk.c
new file mode 100644
index 0000000..fc6ea07
--- /dev/null
+++ b/drivers/clk/davinci/da8xx-usb-phy-clk.c
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * da8xx-usb-phy-clk - TI DaVinci DA8xx USB PHY clocks driver
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ *
+ * This driver exposes the USB PHY clocks on DA8xx/AM18xx/OMAP-L13x SoCs.
+ * The clocks consist of two muxes and a PLL. The USB 2.0 PHY mux and PLL are
+ * combined into a single clock in Linux. The USB 1.0 PHY clock just consists
+ * of a mux. These clocks are controlled through CFGCHIP2, which is accessed
+ * as a syscon regmap since it is shared with other devices.
+ */
+
+#include <linux/clk.h>
+#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>
+
+/* --- USB 2.0 PHY clock --- */
+
+struct da8xx_usb0_phy_clk {
+ struct clk_hw hw;
+ struct clk *clk;
+ struct regmap *regmap;
+};
+
+enum da8xx_usb0_phy_clk_parent {
+ DA8XX_USB0_PHY_CLK_PARENT_USB_REFCLKIN,
+ DA8XX_USB0_PHY_CLK_PARENT_PLL0_AUXCLK,
+};
+
+#define to_da8xx_usb0_phy_clk(_hw) \
+ container_of((_hw), struct da8xx_usb0_phy_clk, hw)
+
+static int da8xx_usb0_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+
+ /* The USB 2.0 PSC clock is only needed temporarily during the USB 2.0
+ * PHY clock enable, but since clk_prepare() can't be called in an
+ * atomic context (i.e. in clk_enable()), we have to prepare it here.
+ */
+ return clk_prepare(clk->clk);
+}
+
+static void da8xx_usb0_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+
+ clk_unprepare(clk->clk);
+}
+
+static int da8xx_usb0_phy_clk_enable(struct clk_hw *hw)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+ unsigned int mask, val;
+ int ret;
+
+ /* Locking the USB 2.O PLL requires that the USB 2.O PSC is enabled
+ * temporaily. It can be turned back off once the PLL is locked.
+ */
+ clk_enable(clk->clk);
+
+ /* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
+ * PHY may use the USB 2.0 PLL clock without USB 2.0 OTG being used.
+ */
+ mask = CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_PHY_PLLON;
+ val = CFGCHIP2_PHY_PLLON;
+
+ regmap_write_bits(clk->regmap, CFGCHIP(2), mask, val);
+ ret = regmap_read_poll_timeout(clk->regmap, CFGCHIP(2), val,
+ val & CFGCHIP2_PHYCLKGD, 0, 500000);
+
+ clk_disable(clk->clk);
+
+ return ret;
+}
+
+static void da8xx_usb0_phy_clk_disable(struct clk_hw *hw)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+ unsigned int val;
+
+ val = CFGCHIP2_PHYPWRDN;
+ regmap_write_bits(clk->regmap, CFGCHIP(2), val, val);
+}
+
+static int da8xx_usb0_phy_clk_is_enabled(struct clk_hw *hw)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+ unsigned int val;
+
+ regmap_read(clk->regmap, CFGCHIP(2), &val);
+
+ return !!(val & CFGCHIP2_PHYCLKGD);
+}
+
+static unsigned long da8xx_usb0_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+ unsigned int mask, val;
+
+ /* The parent clock rate must be one of the following */
+ mask = CFGCHIP2_REFFREQ_MASK;
+ switch (parent_rate) {
+ case 12000000:
+ val = CFGCHIP2_REFFREQ_12MHZ;
+ break;
+ case 13000000:
+ val = CFGCHIP2_REFFREQ_13MHZ;
+ break;
+ case 19200000:
+ val = CFGCHIP2_REFFREQ_19_2MHZ;
+ break;
+ case 20000000:
+ val = CFGCHIP2_REFFREQ_20MHZ;
+ break;
+ case 24000000:
+ val = CFGCHIP2_REFFREQ_24MHZ;
+ break;
+ case 26000000:
+ val = CFGCHIP2_REFFREQ_26MHZ;
+ break;
+ case 38400000:
+ val = CFGCHIP2_REFFREQ_38_4MHZ;
+ break;
+ case 40000000:
+ val = CFGCHIP2_REFFREQ_40MHZ;
+ break;
+ case 48000000:
+ val = CFGCHIP2_REFFREQ_48MHZ;
+ break;
+ default:
+ return 0;
+ }
+
+ regmap_write_bits(clk->regmap, CFGCHIP(2), mask, val);
+
+ /* USB 2.0 PLL always supplies 48MHz */
+ return 48000000;
+}
+
+static long da8xx_usb0_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return 48000000;
+}
+
+static int da8xx_usb0_phy_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+ unsigned int mask, val;
+
+ /* Set the mux depending on the parent clock. */
+ mask = CFGCHIP2_USB2PHYCLKMUX;
+ switch (index) {
+ case DA8XX_USB0_PHY_CLK_PARENT_USB_REFCLKIN:
+ val = 0;
+ break;
+ case DA8XX_USB0_PHY_CLK_PARENT_PLL0_AUXCLK:
+ val = CFGCHIP2_USB2PHYCLKMUX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_write_bits(clk->regmap, CFGCHIP(2), mask, val);
+
+ return 0;
+}
+
+static u8 da8xx_usb0_phy_clk_get_parent(struct clk_hw *hw)
+{
+ struct da8xx_usb0_phy_clk *clk = to_da8xx_usb0_phy_clk(hw);
+ unsigned int val;
+
+ regmap_read(clk->regmap, CFGCHIP(2), &val);
+
+ if (val & CFGCHIP2_USB2PHYCLKMUX)
+ return DA8XX_USB0_PHY_CLK_PARENT_PLL0_AUXCLK;
+
+ return DA8XX_USB0_PHY_CLK_PARENT_USB_REFCLKIN;
+}
+
+static const struct clk_ops da8xx_usb0_phy_clk_ops = {
+ .prepare = da8xx_usb0_phy_clk_prepare,
+ .unprepare = da8xx_usb0_phy_clk_unprepare,
+ .enable = da8xx_usb0_phy_clk_enable,
+ .disable = da8xx_usb0_phy_clk_disable,
+ .is_enabled = da8xx_usb0_phy_clk_is_enabled,
+ .recalc_rate = da8xx_usb0_phy_clk_recalc_rate,
+ .round_rate = da8xx_usb0_phy_clk_round_rate,
+ .set_parent = da8xx_usb0_phy_clk_set_parent,
+ .get_parent = da8xx_usb0_phy_clk_get_parent,
+};
+
+/**
+ * da8xx_usb0_phy_clk_register - Register a new USB 2.0 PHY clock
+ * @name: The clock name
+ * @parent0: The name of the USB_REFCLKIN clock
+ * @parent1: The name of the PLL0 AUXCLK
+ * @usb0_psc_clk: The USB 2.0 PSC clock
+ * @regmap: The CFGCHIP regmap
+ */
+struct clk *da8xx_usb0_phy_clk_register(const char *name,
+ const char *parent0,
+ const char *parent1,
+ struct clk *usb0_psc_clk,
+ struct regmap *regmap)
+{
+ const char * const parent_names[] = {
+ [DA8XX_USB0_PHY_CLK_PARENT_USB_REFCLKIN] = parent0,
+ [DA8XX_USB0_PHY_CLK_PARENT_PLL0_AUXCLK] = parent1,
+ };
+ struct da8xx_usb0_phy_clk *clk;
+ struct clk_init_data init;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &da8xx_usb0_phy_clk_ops;
+ init.parent_names = parent_names;
+ init.num_parents = 2;
+
+ clk->hw.init = &init;
+ clk->clk = usb0_psc_clk;
+ clk->regmap = regmap;
+
+ return clk_register(NULL, &clk->hw);
+}
+
+/* --- USB 1.1 PHY clock --- */
+
+struct da8xx_usb1_phy_clk {
+ struct clk_hw hw;
+ struct regmap *regmap;
+};
+
+enum usb1_phy_clk_parent {
+ DA8XX_USB1_PHY_CLK_PARENT_USB0_PHY_PLL,
+ DA8XX_USB1_PHY_CLK_PARENT_USB_REFCLKIN,
+};
+
+#define to_da8xx_usb1_phy_clk(_hw) \
+ container_of((_hw), struct da8xx_usb1_phy_clk, hw)
+
+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);
+
+ return 0;
+}
+
+static u8 da8xx_usb1_phy_clk_get_parent(struct clk_hw *hw)
+{
+ struct da8xx_usb1_phy_clk *clk = to_da8xx_usb1_phy_clk(hw);
+ unsigned int val;
+
+ regmap_read(clk->regmap, CFGCHIP(2), &val);
+
+ if (val & CFGCHIP2_USB1PHYCLKMUX)
+ return DA8XX_USB1_PHY_CLK_PARENT_USB_REFCLKIN;
+
+ return DA8XX_USB1_PHY_CLK_PARENT_USB0_PHY_PLL;
+}
+
+static const struct clk_ops da8xx_usb1_phy_clk_ops = {
+ .set_parent = da8xx_usb1_phy_clk_set_parent,
+ .get_parent = da8xx_usb1_phy_clk_get_parent,
+};
+
+/**
+ * da8xx_usb1_phy_clk_register - Register a new USB 1.1 PHY clock
+ * @name: The clock name
+ * @parent0: The name of the USB 2.0 PHY clock
+ * @parent1: The name of the USB_REFCLKIN clock
+ * @regmap: The CFGCHIP regmap
+ */
+struct clk *da8xx_usb1_phy_clk_register(const char *name,
+ const char *parent0,
+ const char *parent1,
+ struct regmap *regmap)
+{
+ const char * const parent_names[] = {
+ [DA8XX_USB1_PHY_CLK_PARENT_USB0_PHY_PLL] = parent0,
+ [DA8XX_USB1_PHY_CLK_PARENT_USB_REFCLKIN] = parent1,
+ };
+ struct da8xx_usb1_phy_clk *clk;
+ struct clk_init_data init;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &da8xx_usb1_phy_clk_ops;
+ init.parent_names = parent_names;
+ init.num_parents = 2;
+
+ clk->hw.init = &init;
+ clk->regmap = regmap;
+
+ return clk_register(NULL, &clk->hw);
+}
+
+#ifdef CONFIG_OF
+static void da8xx_usb0_phy_clk_init(struct device_node *np)
+{
+ const char *name = np->name;
+ const char *parent0, *parent1;
+ struct regmap *regmap;
+ struct clk *usb0_psc_clk, *clk;
+ int ret;
+
+ 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));
+ return;
+ }
+
+ ret = of_property_match_string(np, "clock-names", "usb_refclkin");
+ parent0 = of_clk_get_parent_name(np, ret);
+ if (!parent0) {
+ pr_err("%s: Could not get usb_refclkin (%d)\n", __func__, ret);
+ return;
+ }
+
+ ret = of_property_match_string(np, "clock-names", "auxclk");
+ parent1 = of_clk_get_parent_name(np, ret);
+ if (!parent1) {
+ pr_err("%s: Could not get auxclk (%d)\n", __func__, ret);
+ return;
+ }
+
+ usb0_psc_clk = of_clk_get_by_name(np, "usb0_lpsc");
+ if (IS_ERR(usb0_psc_clk)) {
+ pr_err("%s: Could not get usb0_lpsc (%ld)\n", __func__,
+ PTR_ERR(usb0_psc_clk));
+ return;
+ }
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ clk = da8xx_usb0_phy_clk_register(name, parent0, parent1, usb0_psc_clk,
+ regmap);
+ if (IS_ERR(clk)) {
+ pr_err("%s: Failed to register clock %s (%ld)\n", __func__,
+ np->full_name, PTR_ERR(clk));
+ clk_put(usb0_psc_clk);
+ return;
+ }
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+CLK_OF_DECLARE(da8xx_usb0_phy_clk, "ti,da830-usb0-phy-clock",
+ da8xx_usb0_phy_clk_init);
+
+static void da8xx_usb1_phy_clk_init(struct device_node *np)
+{
+ const char *name = np->name;
+ const char *parent0, *parent1;
+ struct regmap *regmap;
+ struct clk *clk;
+ int ret;
+
+ 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));
+ return;
+ }
+
+ ret = of_property_match_string(np, "clock-names", "usb0_phy");
+ parent0 = of_clk_get_parent_name(np, ret);
+ if (!parent0) {
+ pr_err("%s: Could not get usb0_phy (%d)\n", __func__, ret);
+ return;
+ }
+
+ ret = of_property_match_string(np, "clock-names", "usb_refclkin");
+ parent1 = of_clk_get_parent_name(np, ret);
+ if (!parent1) {
+ pr_err("%s: Could not get usb_refclkin (%d)\n", __func__, ret);
+ return;
+ }
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ clk = da8xx_usb1_phy_clk_register(name, parent0, parent1, regmap);
+ if (IS_ERR(clk)) {
+ pr_err("%s: Failed to register clock %s (%ld)\n",
+ __func__, np->full_name, PTR_ERR(clk));
+ return;
+ }
+
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+CLK_OF_DECLARE(da8xx_usb1_phy_clk, "ti,da830-usb1-phy-clock",
+ da8xx_usb1_phy_clk_init);
+#endif
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 3810ea3..ec7403e 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -9,6 +9,9 @@

#include <linux/types.h>

+struct clk;
+struct regmap;
+
void da830_pll_clk_init(void __iomem *pll);
void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1);
void dm355_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
@@ -23,4 +26,14 @@ void dm365_psc_clk_init(void __iomem *psc);
void dm644x_psc_clk_init(void __iomem *psc);
void dm646x_psc_clk_init(void __iomem *psc);

+struct clk *da8xx_usb0_phy_clk_register(const char *name,
+ const char *parent0,
+ const char *parent1,
+ struct clk *usb0_psc_clk,
+ struct regmap *regmap);
+struct clk *da8xx_usb1_phy_clk_register(const char *name,
+ const char *parent0,
+ const char *parent1,
+ struct regmap *regmap);
+
#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:22:11

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 17/44] dt-bindings: clock: Add bindings for DA8XX CFGCHIP gate clocks

This adds a new binding for the gate clocks present in the CFGCHIP syscon
registers in TI DA8XX SoCs. There are actually other gate clocks in this
block that could be added in the future, but TBCLK is currently the only
one being used.

Signed-off-by: David Lechner <[email protected]>
---
.../clock/ti/davinci/da8xx-cfgchip-gate.txt | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt

diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt
new file mode 100644
index 0000000..55821b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt
@@ -0,0 +1,38 @@
+Binding for TI DA8XX/OMAP-L13X/AM17XX/AM18XX CFGCHIP gate clocks
+
+TI DA8XX/OMAP-L13X/AM17XX/AM18XX SoCs contain a general purpose set of
+registers call CFGCHIPn. Some of these registers function as clock
+gates. This document describes the bindings for those clocks.
+
+Required properties:
+- compatible: shall be "ti,da830-tbclk".
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandle to the parent clock
+
+Optional properties:
+- clock-output-names: from common clock binding.
+
+Parent:
+This node must be a child of a "ti,da830-cfgchip" node.
+
+Assignment:
+The assigned-clocks and assigned-clock-parents from the common clock bindings
+can be used to indicate which parent clock should be used.
+
+Examples:
+
+ cfgchip: syscon@1417c {
+ compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+ reg = <0x1417c 0x14>;
+
+ ehrpwm_tbclk: tbclk {
+ compatible = "ti,da830-tbclk";
+ #clock-cells = <0>;
+ clocks = <&psc1 17>;
+ clock-output-names = "ehrpwm_tbclk";
+ };
+ };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
+
--
2.7.4

2018-01-08 02:23:01

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 16/44] clk: davinci: Add platform information for TI DM646x PSC

This adds platform-specific declarations for the PSC clocks on TI
DaVinci 646x based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/psc-dm646x.c | 68 ++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 70 insertions(+)
create mode 100644 drivers/clk/davinci/psc-dm646x.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index a20e379..6c388d4 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -15,4 +15,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DA850) += psc-da850.o
obj-$(CONFIG_ARCH_DAVINCI_DM355) += psc-dm355.o
obj-$(CONFIG_ARCH_DAVINCI_DM365) += psc-dm365.o
obj-$(CONFIG_ARCH_DAVINCI_DM644x) += psc-dm644x.o
+obj-$(CONFIG_ARCH_DAVINCI_DM646x) += psc-dm646x.o
endif
diff --git a/drivers/clk/davinci/psc-dm646x.c b/drivers/clk/davinci/psc-dm646x.c
new file mode 100644
index 0000000..cbc3976
--- /dev/null
+++ b/drivers/clk/davinci/psc-dm646x.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM646x
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#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 dm646x_psc_info[] __initconst = {
+ LPSC(0, 0, arm, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ /* REVISIT how to disable? */
+ LPSC(1, 0, dsp, pll1_sysclk1, LPSC_ALWAYS_ENABLED),
+ LPSC(4, 0, edma_cc, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(5, 0, edma_tc0, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(6, 0, edma_tc1, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(7, 0, edma_tc2, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(8, 0, edma_tc3, pll1_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(10, 0, ide, pll1_sysclk4, 0),
+ LPSC(14, 0, emac, pll1_sysclk3, 0),
+ LPSC(16, 0, vpif0, ref_clk, LPSC_ALWAYS_ENABLED),
+ LPSC(17, 0, vpif1, ref_clk, LPSC_ALWAYS_ENABLED),
+ LPSC(21, 0, aemif, pll1_sysclk3, LPSC_ALWAYS_ENABLED),
+ LPSC(22, 0, mcasp0, pll1_sysclk3, 0),
+ LPSC(23, 0, mcasp1, pll1_sysclk3, 0),
+ LPSC(26, 0, uart0, aux_clkin, 0),
+ LPSC(27, 0, uart1, aux_clkin, 0),
+ LPSC(28, 0, uart2, aux_clkin, 0),
+ /* REVIST: disabling hangs system */
+ LPSC(29, 0, pwm0, pll1_sysclk3, LPSC_ALWAYS_ENABLED),
+ /* REVIST: disabling hangs system */
+ LPSC(30, 0, pwm1, pll1_sysclk3, LPSC_ALWAYS_ENABLED),
+ LPSC(31, 0, i2c, pll1_sysclk3, 0),
+ LPSC(33, 0, gpio, pll1_sysclk3, 0),
+ LPSC(34, 0, timer0, pll1_sysclk3, 0),
+ LPSC(35, 0, timer1, pll1_sysclk3, 0),
+ { }
+};
+
+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);
+ clk_register_clkdev(clk_data->clks[10], NULL, "palm_bk3710");
+ clk_register_clkdev(clk_data->clks[14], NULL, "davinci_emac.1");
+ clk_register_clkdev(clk_data->clks[14], "fck", "davinci_mdio.0");
+ clk_register_clkdev(clk_data->clks[21], "aemif", NULL);
+ clk_register_clkdev(clk_data->clks[22], NULL, "davinci-mcasp.0");
+ clk_register_clkdev(clk_data->clks[23], NULL, "davinci-mcasp.1");
+ clk_register_clkdev(clk_data->clks[26], NULL, "serial8250.0");
+ clk_register_clkdev(clk_data->clks[27], NULL, "serial8250.1");
+ clk_register_clkdev(clk_data->clks[28], NULL, "serial8250.2");
+ clk_register_clkdev(clk_data->clks[31], NULL, "i2c_davinci.1");
+ clk_register_clkdev(clk_data->clks[33], "gpio", NULL);
+ clk_register_clkdev(clk_data->clks[34], "timer0", NULL);
+
+ clk_free_onecell_data(clk_data);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 6d2896d..3810ea3 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -21,5 +21,6 @@ void da850_psc_clk_init(void __iomem *psc0, void __iomem *psc1);
void dm355_psc_clk_init(void __iomem *psc);
void dm365_psc_clk_init(void __iomem *psc);
void dm644x_psc_clk_init(void __iomem *psc);
+void dm646x_psc_clk_init(void __iomem *psc);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:23:19

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 14/44] clk: davinci: Add platform information for TI DM365 PSC

This adds platform-specific declarations for the PSC clocks on TI
DaVinci 365 based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/psc-dm365.c | 83 +++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 85 insertions(+)
create mode 100644 drivers/clk/davinci/psc-dm365.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index e0da5c3..78dc1eb 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -13,4 +13,5 @@ obj-y += psc.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += psc-da830.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += psc-da850.o
obj-$(CONFIG_ARCH_DAVINCI_DM355) += psc-dm355.o
+obj-$(CONFIG_ARCH_DAVINCI_DM365) += psc-dm365.o
endif
diff --git a/drivers/clk/davinci/psc-dm365.c b/drivers/clk/davinci/psc-dm365.c
new file mode 100644
index 0000000..0232832
--- /dev/null
+++ b/drivers/clk/davinci/psc-dm365.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM365
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#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 dm365_psc_info[] __initconst = {
+ LPSC(1, 0, vpss_slave, pll1_sysclk5, 0),
+ LPSC(5, 0, timer3, pll1_aux_clk, 0),
+ LPSC(6, 0, spi1, pll1_sysclk4, 0),
+ LPSC(7, 0, mmcsd1, pll1_sysclk4, 0),
+ LPSC(8, 0, asp0, pll1_sysclk4, 0),
+ LPSC(9, 0, usb, pll1_aux_clk, 0),
+ LPSC(10, 0, pwm3, ref_clk, 0),
+ LPSC(11, 0, spi2, pll1_sysclk4, 0),
+ LPSC(12, 0, rto, pll1_sysclk4, 0),
+ LPSC(14, 0, aemif, pll1_sysclk4, 0),
+ LPSC(15, 0, mmcsd0, pll1_sysclk8, 0),
+ LPSC(18, 0, i2c, pll1_aux_clk, 0),
+ LPSC(19, 0, uart0, pll1_aux_clk, 0),
+ LPSC(20, 0, uart1, pll1_sysclk4, 0),
+ LPSC(22, 0, spi0, pll1_sysclk4, 0),
+ LPSC(23, 0, pwm0, pll1_aux_clk, 0),
+ LPSC(24, 0, pwm1, pll1_aux_clk, 0),
+ LPSC(25, 0, pwm2, pll1_aux_clk, 0),
+ LPSC(26, 0, gpio, pll1_sysclk4, 0),
+ LPSC(27, 0, timer0, pll1_aux_clk, 0),
+ LPSC(28, 0, timer1, pll1_aux_clk, 0),
+ /* REVISIT: why can't this be disabled? */
+ LPSC(29, 0, timer2, pll1_aux_clk, LPSC_ALWAYS_ENABLED),
+ LPSC(31, 0, arm, pll2_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(38, 0, spi3, pll1_sysclk4, 0),
+ LPSC(39, 0, spi4, pll1_aux_clk, 0),
+ LPSC(40, 0, emac, pll2_sysclk4, 0),
+ LPSC(44, 1, voice_codec, pll1_sysclk3, 0),
+ LPSC(46, 1, vpss_dac, pll1_sysclk3, 0),
+ LPSC(47, 0, vpss_master, pll1_sysclk5, 0),
+ LPSC(50, 0, mjcp, pll1_sysclk3, 0),
+ { }
+};
+
+void __init dm365_psc_clk_init(void __iomem *psc)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = davinci_psc_register_clocks(psc, dm365_psc_info, 52);
+ if (!clk_data)
+ return;
+
+ clk_register_clkdev(clk_data->clks[1], "slave", "vpss");
+ clk_register_clkdev(clk_data->clks[6], NULL, "spi_davinci.1");
+ clk_register_clkdev(clk_data->clks[7], NULL, "da830-mmc.1");
+ clk_register_clkdev(clk_data->clks[8], NULL, "davinci-mcbsp");
+ clk_register_clkdev(clk_data->clks[9], "usb", NULL);
+ clk_register_clkdev(clk_data->clks[11], NULL, "spi_davinci.2");
+ clk_register_clkdev(clk_data->clks[14], "aemif", NULL);
+ clk_register_clkdev(clk_data->clks[15], NULL, "da830-mmc.0");
+ clk_register_clkdev(clk_data->clks[18], NULL, "i2c_davinci.1");
+ clk_register_clkdev(clk_data->clks[19], NULL, "serial8250.0");
+ clk_register_clkdev(clk_data->clks[20], NULL, "serial8250.1");
+ clk_register_clkdev(clk_data->clks[22], NULL, "spi_davinci.0");
+ clk_register_clkdev(clk_data->clks[26], "gpio", NULL);
+ clk_register_clkdev(clk_data->clks[27], "timer0", NULL);
+ clk_register_clkdev(clk_data->clks[29], NULL, "davinci-wdt");
+ clk_register_clkdev(clk_data->clks[31], "arm", NULL);
+ clk_register_clkdev(clk_data->clks[38], NULL, "spi_davinci.3");
+ clk_register_clkdev(clk_data->clks[39], NULL, "spi_davinci.4");
+ clk_register_clkdev(clk_data->clks[40], NULL, "davinci_emac.1");
+ clk_register_clkdev(clk_data->clks[40], "fck", "davinci_mdio.0");
+ clk_register_clkdev(clk_data->clks[44], NULL, "davinci_voicecodec");
+ clk_register_clkdev(clk_data->clks[46], "vpss_dac", NULL);
+ clk_register_clkdev(clk_data->clks[47], "master", "vpss");
+
+ clk_free_onecell_data(clk_data);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index dc09177..c7d8c5f 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -19,5 +19,6 @@ 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);
void dm355_psc_clk_init(void __iomem *psc);
+void dm365_psc_clk_init(void __iomem *psc);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:23:42

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 13/44] clk: davinci: Add platform information for TI DM355 PSC

This adds platform-specific declarations for the PSC clocks on TI
DaVinci 355 based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/psc-dm355.c | 78 +++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 80 insertions(+)
create mode 100644 drivers/clk/davinci/psc-dm355.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index aef0390..e0da5c3 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -12,4 +12,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
+obj-$(CONFIG_ARCH_DAVINCI_DM355) += psc-dm355.o
endif
diff --git a/drivers/clk/davinci/psc-dm355.c b/drivers/clk/davinci/psc-dm355.c
new file mode 100644
index 0000000..09075ed
--- /dev/null
+++ b/drivers/clk/davinci/psc-dm355.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM355
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#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 dm355_psc_info[] __initconst = {
+ LPSC(0, 0, vpss_master, pll1_sysclk4, 0),
+ LPSC(1, 0, vpss_slave, pll1_sysclk4, 0),
+ LPSC(5, 0, timer3, pll1_aux_clk, 0),
+ LPSC(6, 0, spi1, pll1_sysclk2, 0),
+ LPSC(7, 0, mmcsd1, pll1_sysclk2, 0),
+ LPSC(8, 0, asp1, pll1_sysclk2, 0),
+ LPSC(9, 0, usb, pll1_sysclk2, 0),
+ LPSC(10, 0, pwm3, pll1_aux_clk, 0),
+ LPSC(11, 0, spi2, pll1_sysclk2, 0),
+ LPSC(12, 0, rto, pll1_aux_clk, 0),
+ LPSC(14, 0, aemif, pll1_sysclk2, 0),
+ LPSC(15, 0, mmcsd0, pll1_sysclk2, 0),
+ LPSC(17, 0, asp0, pll1_sysclk2, 0),
+ LPSC(18, 0, i2c, pll1_aux_clk, 0),
+ LPSC(19, 0, uart0, pll1_aux_clk, 0),
+ LPSC(20, 0, uart1, pll1_aux_clk, 0),
+ LPSC(21, 0, uart2, pll1_sysclk2, 0),
+ LPSC(22, 0, spi0, pll1_sysclk2, 0),
+ LPSC(23, 0, pwm0, pll1_aux_clk, 0),
+ LPSC(24, 0, pwm1, pll1_aux_clk, 0),
+ LPSC(25, 0, pwm2, pll1_aux_clk, 0),
+ LPSC(26, 0, gpio, pll1_sysclk2, 0),
+ LPSC(27, 0, timer0, pll1_aux_clk, 0),
+ LPSC(28, 0, timer1, pll1_aux_clk, 0),
+ /* REVISIT: why can't this be disabled? */
+ LPSC(29, 0, timer2, pll1_aux_clk, LPSC_ALWAYS_ENABLED),
+ LPSC(31, 0, arm, pll1_sysclk1, LPSC_ALWAYS_ENABLED),
+ LPSC(40, 0, mjcp, pll1_sysclk1, 0),
+ LPSC(41, 0, vpss_dac, pll1_sysclk3, 0),
+ { }
+};
+
+void __init dm355_psc_clk_init(void __iomem *psc)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = davinci_psc_register_clocks(psc, dm355_psc_info, 42);
+ if (!clk_data)
+ return;
+
+ clk_register_clkdev(clk_data->clks[0], "master", "vpss");
+ clk_register_clkdev(clk_data->clks[1], "slave", "vpss");
+ clk_register_clkdev(clk_data->clks[6], NULL, "spi_davinci.1");
+ clk_register_clkdev(clk_data->clks[7], NULL, "dm6441-mmc.1");
+ clk_register_clkdev(clk_data->clks[8], NULL, "davinci-mcbsp.1");
+ clk_register_clkdev(clk_data->clks[9], "usb", NULL);
+ clk_register_clkdev(clk_data->clks[11], NULL, "spi_davinci.2");
+ clk_register_clkdev(clk_data->clks[14], "aemif", NULL);
+ clk_register_clkdev(clk_data->clks[15], NULL, "dm6441-mmc.0");
+ clk_register_clkdev(clk_data->clks[17], NULL, "davinci-mcbsp.0");
+ clk_register_clkdev(clk_data->clks[18], NULL, "i2c_davinci.1");
+ clk_register_clkdev(clk_data->clks[19], NULL, "serial8250.0");
+ clk_register_clkdev(clk_data->clks[20], NULL, "serial8250.1");
+ clk_register_clkdev(clk_data->clks[21], NULL, "serial8250.2");
+ clk_register_clkdev(clk_data->clks[22], NULL, "spi_davinci.0");
+ clk_register_clkdev(clk_data->clks[26], "gpio", NULL);
+ clk_register_clkdev(clk_data->clks[27], "timer0", NULL);
+ clk_register_clkdev(clk_data->clks[29], NULL, "davinci-wdt");
+ clk_register_clkdev(clk_data->clks[31], "arm", NULL);
+ clk_register_clkdev(clk_data->clks[41], "vpss_dac", NULL);
+
+ clk_free_onecell_data(clk_data);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 3d8bdfa..dc09177 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -18,5 +18,6 @@ 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);
+void dm355_psc_clk_init(void __iomem *psc);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:28:39

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 11/44] clk: davinci: Add platform information for TI DA830 PSC

This adds platform-specific declarations for the PSC clocks on TI DA830/
OMAP-L137/AM17XX SoCs.

Signed-off-by: David Lechner <[email protected]>
---
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 <[email protected]>
+ */
+
+#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),
+ LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
+ { }
+};
+
+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),
+ 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);
+ 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");
+
+ clk_free_onecell_data(clk_data);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index d495de7..3ec8100 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -16,4 +16,6 @@ void dm365_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
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);
+
#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:18:36

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 05/44] clk: davinci: Add platform information for TI DM355 PLL

This adds platform-specific declarations for the PLL clocks on TI
DaVinci 355 based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/pll-dm355.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 42 insertions(+)
create mode 100644 drivers/clk/davinci/pll-dm355.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index 13049d4..6720bd0 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -4,4 +4,5 @@ ifeq ($(CONFIG_COMMON_CLK), y)
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
endif
diff --git a/drivers/clk/davinci/pll-dm355.c b/drivers/clk/davinci/pll-dm355.c
new file mode 100644
index 0000000..972fd2b
--- /dev/null
+++ b/drivers/clk/davinci/pll-dm355.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM355
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_divclk_info dm355_pll1_divclk_info[] __initconst = {
+ DIVCLK(1, pll1_sysclk1, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(2, pll1_sysclk2, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(3, pll1_sysclk3, pll1, 0),
+ DIVCLK(4, pll1_sysclk4, pll1, 0),
+ { }
+};
+
+static const struct davinci_pll_divclk_info dm355_pll2_divclk_info[] __initconst = {
+ DIVCLK(1, pll2_sysclk1, pll2, DIVCLK_FIXED_DIV),
+ { }
+};
+
+void __init dm355_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 = dm355_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 = dm355_pll2_divclk_info; info->name; info++)
+ davinci_pll_divclk_register(info, pll2);
+ davinci_pll_bpdiv_clk_register("pll2_sysclkbp", "ref_clk", pll2);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 7b08fe0..95333fe 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -11,5 +11,6 @@

void da830_pll_clk_init(void __iomem *pll);
void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1);
+void dm355_pll_clk_init(void __iomem *pll1, void __iomem *pll2);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:28:56

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 10/44] clk: davinci: New driver for davinci PSC clocks

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 <[email protected]>
---
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 <[email protected]>
+ *
+ * Based on: drivers/clk/keystone/gate.c
+ * Copyright (C) 2013 Texas Instruments.
+ * Murali Karicheri <[email protected]>
+ * Santosh Shilimkar <[email protected]>
+ *
+ * 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
+#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);
+
+ 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);
+
+ 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);
+}
+
+static int davinci_psc_clk_enable(struct clk_hw *hw)
+{
+ struct davinci_psc_clk *psc = to_davinci_psc_clk(hw);
+
+ psc_config(psc, PSC_STATE_ENABLE);
+
+ return 0;
+}
+
+static void davinci_psc_clk_disable(struct clk_hw *hw)
+{
+ struct davinci_psc_clk *psc = to_davinci_psc_clk(hw);
+
+ psc_config(psc, PSC_STATE_DISABLE);
+}
+
+static int davinci_psc_clk_is_enabled(struct clk_hw *hw)
+{
+ struct davinci_psc_clk *psc = to_davinci_psc_clk(hw);
+ u32 mdstat;
+
+ regmap_read(psc->regmap, MDSTAT(psc->lpsc), &mdstat);
+
+ return (mdstat & MDSTAT_MCKOUT) ? 1 : 0;
+}
+
+static const struct clk_ops davinci_psc_clk_ops = {
+ .enable = davinci_psc_clk_enable,
+ .disable = davinci_psc_clk_disable,
+ .is_enabled = davinci_psc_clk_is_enabled,
+};
+
+/**
+ * davinci_psc_clk_register - register psc clock
+ * @dev: device that is registering this clock
+ * @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;
+
+ 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.
+ */
+
+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);
+
+static const struct regmap_config davinci_psc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+};
+
+struct clk_onecell_data *
+davinci_psc_register_clocks(void __iomem *base,
+ const struct davinci_psc_clk_info *info,
+ u8 num_clks)
+{
+ struct clk_onecell_data *clk_data;
+ struct regmap *regmap;
+
+ clk_data = clk_alloc_onecell_data(num_clks);
+ if (!clk_data) {
+ pr_err("%s: Out of memory\n", __func__);
+ return NULL;
+ }
+
+ regmap = regmap_init_mmio(NULL, base, &davinci_psc_regmap_config);
+ if (IS_ERR(regmap)) {
+ pr_err("%s: regmap_init_mmio failed (%ld)\n", __func__,
+ PTR_ERR(regmap));
+ clk_free_onecell_data(clk_data);
+ return NULL;
+ }
+
+ for (; info->name; info++) {
+ struct clk *clk;
+
+ clk = davinci_psc_clk_register(info->name, info->parent, regmap,
+ info->lpsc, info->pd, info->flags);
+ if (IS_ERR(clk)) {
+ pr_warn("%s: Failed to register %s (%ld)\n", __func__,
+ info->name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_data->clks[info->lpsc] = clk;
+ }
+
+ return clk_data;
+}
+
+#ifdef CONFIG_OF
+void of_davinci_psc_clk_init(struct device_node *node,
+ const struct davinci_psc_clk_info *info,
+ u8 num_clks)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s: ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = davinci_psc_register_clocks(base, info, num_clks);
+ if (!clk_data)
+ return;
+
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+#endif
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 <[email protected]>
+ */
+
+#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;
+
+struct davinci_psc_clk_info {
+ const char *name;
+ const char *parent;
+ u32 lpsc;
+ u32 pd;
+ unsigned long flags;
+ bool has_reset;
+};
+
+#define LPSC(l, d, n, p, f) \
+{ \
+ .name = #n, \
+ .parent = #p, \
+ .lpsc = (l), \
+ .pd = (d), \
+ .flags = (f), \
+}
+
+struct clk_onecell_data *
+davinci_psc_register_clocks(void __iomem *base,
+ const struct davinci_psc_clk_info *info,
+ u8 num_clks);
+
+#ifdef CONFIG_OF
+void of_davinci_psc_clk_init(struct device_node *node,
+ const struct davinci_psc_clk_info *info,
+ u8 num_clks);
+#endif
+
+#endif /* __CLK_DAVINCI_PSC_H__ */
--
2.7.4

2018-01-08 02:18:35

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 06/44] clk: davinci: Add platform information for TI DM365 PLL

This adds platform-specific declarations for the PLL clocks on TI
DaVinci 365 based systems.

Signed-off-by: David Lechner <[email protected]>
---
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 <[email protected]>
+ */
+
+#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,
+};
+
+static const struct davinci_pll_divclk_info dm365_pll1_divclk_info[] __initconst = {
+ DIVCLK(1, pll1_sysclk1, pll1, 0),
+ DIVCLK(2, pll1_sysclk2, pll1, 0),
+ DIVCLK(3, pll1_sysclk3, pll1, 0),
+ DIVCLK(4, pll1_sysclk4, pll1, 0),
+ DIVCLK(5, pll1_sysclk5, pll1, 0),
+ DIVCLK(6, pll1_sysclk6, pll1, 0),
+ DIVCLK(7, pll1_sysclk7, pll1, 0),
+ DIVCLK(8, pll1_sysclk8, pll1, 0),
+ DIVCLK(9, pll1_sysclk9, pll1, 0),
+ { }
+};
+
+static const struct davinci_pll_divclk_info dm365_pll2_divclk_info[] __initconst = {
+ DIVCLK(1, pll2_sysclk1, pll2, 0),
+ DIVCLK(2, pll2_sysclk2, pll2, 0),
+ DIVCLK(3, pll2_sysclk3, pll2, 0),
+ DIVCLK(4, pll2_sysclk4, pll2, 0),
+ DIVCLK(5, pll2_sysclk5, pll2, 0),
+ { }
+};
+
+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);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 95333fe..5bf60a7 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -12,5 +12,6 @@
void da830_pll_clk_init(void __iomem *pll);
void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1);
void dm355_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
+void dm365_pll_clk_init(void __iomem *pll1, void __iomem *pll2);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:29:23

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 09/44] dt-bindings: clock: New bindings for TI Davinci PSC

This adds a new binding for the Power Sleep Controller (PSC) for the
mach-davinci family of processors.

Note: Although TI Keystone has a very similar PSC, we are not using the
existing bindings. Keystone is using a legacy one-node-per-clock binding
(actually two nodes if you count the separate reset binding for the same
IP block). Also, some davinci LPSCs have quirks that aren't handled by
the keystone bindings, so we would be adding one compatible string per
clock with quirks instead of just a new compatible string for each
controller.

Signed-off-by: David Lechner <[email protected]>
---
.../devicetree/bindings/clock/ti/davinci/psc.txt | 47 ++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/psc.txt

diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/psc.txt b/Documentation/devicetree/bindings/clock/ti/davinci/psc.txt
new file mode 100644
index 0000000..83a9da5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/davinci/psc.txt
@@ -0,0 +1,47 @@
+Binding for TI DaVinci Power Sleep Controller (PSC)
+
+The PSC provides power management, clock gating and reset functionality. It is
+primarily used for clocking.
+
+Required properties:
+- compatible: shall be one of:
+ - "ti,da850-psc0" for PSC0 on DA850/OMAP-L138/AM18XX
+ - "ti,da850-psc1" for PSC1 on DA850/OMAP-L138/AM18XX
+- reg: physical base address and size of the controller's register area.
+- #clock-cells: from common clock binding; shall be set to 1.
+- #reset-cells: from reset binding; shall be set to 1.
+
+Consumers:
+
+ Clock and reset consumers shall use the local power domain module ID
+ (LPSC) as the index corresponding to the clock cell. Refer to the
+ device-specific datasheet to find these numbers. NB: Most local domains
+ only provide a clock and not a reset.
+
+Examples:
+
+ psc0: clock-controller@10000 {
+ compatible = "ti,da850-psc0";
+ reg = <0x10000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ /* consumer */
+ dsp: dsp@11800000 {
+ compatible = "ti,da850-dsp";
+ reg = <0x11800000 0x40000>,
+ <0x11e00000 0x8000>,
+ <0x11f00000 0x8000>,
+ <0x01c14044 0x4>,
+ <0x01c14174 0x8>;
+ reg-names = "l2sram", "l1pram", "l1dram", "host1cfg", "chipsig";
+ interrupt-parent = <&intc>;
+ interrupts = <28>;
+ clocks = <&psc0 15>;
+ resets = <&psc0 15>;
+ };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
+- Documentation/devicetree/bindings/reset/reset.txt
--
2.7.4

2018-01-08 02:29:44

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 08/44] clk: davinci: Add platform information for TI DM646x PLL

This adds platform-specific declarations for the PLL clocks on TI
DaVinci 646x based systems.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/pll-dm646x.c | 44 ++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 46 insertions(+)
create mode 100644 drivers/clk/davinci/pll-dm646x.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index 59d8ab6..d471386 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_ARCH_DAVINCI_DA850) += pll-da850.o
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
endif
diff --git a/drivers/clk/davinci/pll-dm646x.c b/drivers/clk/davinci/pll-dm646x.c
new file mode 100644
index 0000000..9d5bdaf
--- /dev/null
+++ b/drivers/clk/davinci/pll-dm646x.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM646X
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_divclk_info dm646x_pll1_divclk_info[] __initconst = {
+ DIVCLK(1, pll1_sysclk1, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(2, pll1_sysclk2, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(3, pll1_sysclk3, pll1, DIVCLK_FIXED_DIV),
+ DIVCLK(4, pll1_sysclk4, pll1, 0),
+ DIVCLK(5, pll1_sysclk5, pll1, 0),
+ DIVCLK(6, pll1_sysclk6, pll1, 0),
+ DIVCLK(7, pll1_sysclk7, pll1, 0),
+ DIVCLK(8, pll1_sysclk8, pll1, 0),
+ DIVCLK(9, pll1_sysclk9, pll1, 0),
+ { }
+};
+
+static const struct davinci_pll_divclk_info dm646x_pll2_divclk_info[] __initconst = {
+ DIVCLK(1, pll2_sysclk1, pll2, 0),
+ { }
+};
+
+void __init dm646x_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 = dm646x_pll1_divclk_info; info->name; info++)
+ davinci_pll_divclk_register(info, pll1);
+ davinci_pll_bpdiv_clk_register("pll1_sysclkbp", "ref_clk", pll1);
+ davinci_pll_aux_clk_register("pll1_aux_clk", "ref_clk", pll1);
+
+ davinci_pll_clk_register("pll2_clk", "ref_clk", pll2);
+ for (info = dm646x_pll2_divclk_info; info->name; info++)
+ davinci_pll_divclk_register(info, pll2);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 535990a..d495de7 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -14,5 +14,6 @@ void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1);
void dm355_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
void dm365_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
void dm644x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);
+void dm646x_pll_clk_init(void __iomem *pll1, void __iomem *pll2);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:30:12

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 04/44] clk: davinci: Add platform information for TI DA850 PLL

This adds platform-specific declarations for the PLL clocks on TI DA850/
OMAP-L138/AM18XX SoCs.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/pll-da850.c | 67 +++++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 1 +
3 files changed, 69 insertions(+)
create mode 100644 drivers/clk/davinci/pll-da850.c

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index 9061e19..13049d4 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -3,4 +3,5 @@
ifeq ($(CONFIG_COMMON_CLK), y)
obj-y += pll.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += pll-da830.o
+obj-$(CONFIG_ARCH_DAVINCI_DA850) += pll-da850.o
endif
diff --git a/drivers/clk/davinci/pll-da850.c b/drivers/clk/davinci/pll-da850.c
new file mode 100644
index 0000000..2f00f3d
--- /dev/null
+++ b/drivers/clk/davinci/pll-da850.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DA850/OMAP-L138/AM18XX
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+/*
+ * NB: Technically, the clocks flagged as DIVCLK_FIXED_DIV are "fixed ratio",
+ * meaning that we could change the divider as long as we keep the correct
+ * ratio between all of the clocks, but we don't support that because there is
+ * currently not a need for it.
+ */
+
+static const struct davinci_pll_divclk_info da850_pll0_divclk_info[] __initconst = {
+ DIVCLK(1, pll0_sysclk1, pll0, DIVCLK_FIXED_DIV),
+ DIVCLK(2, pll0_sysclk2, pll0, DIVCLK_FIXED_DIV),
+ DIVCLK(3, pll0_sysclk3, pll0, 0),
+ DIVCLK(4, pll0_sysclk4, pll0, DIVCLK_FIXED_DIV),
+ DIVCLK(5, pll0_sysclk5, pll0, 0),
+ DIVCLK(6, pll0_sysclk6, pll0, DIVCLK_ARM_RATE | DIVCLK_FIXED_DIV),
+ DIVCLK(7, pll0_sysclk7, pll0, 0),
+ { }
+};
+
+static const struct davinci_pll_divclk_info da850_pll1_divclk_info[] __initconst = {
+ DIVCLK(1, pll1_sysclk1, pll1, DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(2, pll1_sysclk2, pll1, 0),
+ DIVCLK(3, pll1_sysclk3, pll1, 0),
+ { }
+};
+
+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);
+ davinci_pll_aux_clk_register("pll0_aux_clk", "ref_clk", pll0);
+ for (info = da850_pll0_divclk_info; info->name; info++)
+ davinci_pll_divclk_register(info, pll0);
+
+ davinci_pll_clk_register("pll1", "ref_clk", pll1);
+ for (info = da850_pll1_divclk_info; info->name; info++)
+ davinci_pll_divclk_register(info, pll1);
+}
+
+#ifdef CONFIG_OF
+static void __init of_da850_pll0_auxclk_init(struct device_node *node)
+{
+ of_davinci_pll_init(node, "pll0", da850_pll0_divclk_info, 7);
+}
+CLK_OF_DECLARE(da850_pll0_auxclk, "ti,da850-pll0", of_da850_pll0_auxclk_init);
+
+static void __init of_da850_pll1_auxclk_init(struct device_node *node)
+{
+ of_davinci_pll_init(node, "pll1", da850_pll1_divclk_info, 3);
+}
+CLK_OF_DECLARE(da850_pll1_auxclk, "ti,da850-pll1", of_da850_pll1_auxclk_init);
+#endif
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 4f4d60d..7b08fe0 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -10,5 +10,6 @@
#include <linux/types.h>

void da830_pll_clk_init(void __iomem *pll);
+void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1);

#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:30:37

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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 <[email protected]>
---
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 <[email protected]>
+S: Maintained
+F: Documentation/devicetree/bindings/clock/ti/davinci/
+F: drivers/clk/davinci/
+
TI DAVINCI SERIES GPIO DRIVER
M: Keerthy <[email protected]>
L: [email protected]
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 <[email protected]>
+ *
+ * Based on drivers/clk/keystone/pll.c
+ * Copyright (C) 2013 Texas Instruments Inc.
+ * Murali Karicheri <[email protected]>
+ * Santosh Shilimkar <[email protected]>
+ *
+ * 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
+#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 */
+#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
+ */
+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;
+
+ 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;
+}
+
+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;
+ }
+ 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);
+}
+
+static int davinci_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+ u32 mult, postdiv;
+
+ davinci_pll_get_best_rate(rate, parent_rate, &mult, &postdiv);
+ __davinci_pll_set_rate(pll, 1, mult, postdiv);
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+
+#define DEBUG_REG(n) \
+{ \
+ .name = #n, \
+ .offset = n, \
+}
+
+static const struct debugfs_reg32 davinci_pll_regs[] = {
+ DEBUG_REG(REVID),
+ DEBUG_REG(PLLCTL),
+ DEBUG_REG(OCSEL),
+ DEBUG_REG(PLLSECCTL),
+ DEBUG_REG(PLLM),
+ DEBUG_REG(PREDIV),
+ DEBUG_REG(PLLDIV1),
+ DEBUG_REG(PLLDIV2),
+ DEBUG_REG(PLLDIV3),
+ DEBUG_REG(OSCDIV),
+ DEBUG_REG(POSTDIV),
+ DEBUG_REG(BPDIV),
+ DEBUG_REG(PLLCMD),
+ DEBUG_REG(PLLSTAT),
+ DEBUG_REG(ALNCTL),
+ DEBUG_REG(DCHANGE),
+ DEBUG_REG(CKEN),
+ DEBUG_REG(CKSTAT),
+ DEBUG_REG(SYSTAT),
+ DEBUG_REG(PLLDIV4),
+ DEBUG_REG(PLLDIV5),
+ DEBUG_REG(PLLDIV6),
+ DEBUG_REG(PLLDIV7),
+ DEBUG_REG(PLLDIV8),
+ DEBUG_REG(PLLDIV9),
+};
+
+static int davinci_pll_debug_init(struct clk_hw *hw, struct dentry *dentry)
+{
+ struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+ struct debugfs_regset32 *regset;
+ struct dentry *d;
+
+ regset = kzalloc(sizeof(regset), GFP_KERNEL);
+ if (!regset)
+ return -ENOMEM;
+
+ regset->regs = davinci_pll_regs;
+ regset->nregs = ARRAY_SIZE(davinci_pll_regs);
+ regset->base = pll->base;
+
+ d = debugfs_create_regset32("registers", 0400, dentry, regset);
+ if (IS_ERR(d)) {
+ kfree(regset);
+ return PTR_ERR(d);
+ }
+
+ return 0;
+}
+#else
+#define davinci_pll_debug_init NULL
+#endif
+
+static const struct clk_ops davinci_pll_clk_ops = {
+ .recalc_rate = davinci_pll_clk_recalc,
+ .round_rate = davinci_pll_round_rate,
+ .set_rate = davinci_pll_set_rate,
+ .debug_init = davinci_pll_debug_init,
+};
+
+/**
+ * davinci_pll_clk_register - Register a PLL clock
+ * @name: The clock name
+ * @parent_name: The parent clock name
+ * @base: The PLL's memory region
+ */
+struct clk *davinci_pll_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ struct clk_init_data init;
+ struct davinci_pll_clk *pll;
+ struct clk *clk;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &davinci_pll_clk_ops;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+ init.flags = 0;
+
+ pll->base = base;
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk))
+ kfree(pll);
+
+ return clk;
+}
+
+struct davinci_pll_aux_clk {
+ struct clk_hw hw;
+ struct davinci_pll_clk *pll;
+};
+
+/**
+ * davinci_pll_aux_clk_register - Register bypass clock (AUXCLK)
+ * @name: The clock name
+ * @parent_name: The parent clock name (usually "ref_clk" since this bypasses
+ * the PLL)
+ * @base: The PLL memory region
+ */
+struct clk *davinci_pll_aux_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ return clk_register_gate(NULL, name, parent_name, 0, base + CKEN,
+ CKEN_AUXEN_SHIFT, 0, NULL);
+}
+
+/**
+ * davinci_pll_bpdiv_clk_register - Register bypass divider clock (SYSCLKBP)
+ * @name: The clock name
+ * @parent_name: The parent clock name (usually "ref_clk" since this bypasses
+ * the PLL)
+ * @base: The PLL memory region
+ */
+struct clk *davinci_pll_bpdiv_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base)
+{
+ return clk_register_divider(NULL, name, parent_name, 0, base + BPDIV,
+ BPDIV_RATIO_SHIFT, BPDIV_RATIO_WIDTH,
+ CLK_DIVIDER_READ_ONLY, NULL);
+}
+
+/**
+ * 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;
+
+ 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;
+ 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));
+ 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);
+ }
+ of_node_put(child);
+}
+#endif
diff --git a/drivers/clk/davinci/pll.h b/drivers/clk/davinci/pll.h
new file mode 100644
index 0000000..259678b
--- /dev/null
+++ b/drivers/clk/davinci/pll.h
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for TI Davinci PSC controllers
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#ifndef __CLK_DAVINCI_PLL_H___
+#define __CLK_DAVINCI_PLL_H___
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+#define DIVCLK_ARM_RATE BIT(0) /* Controls ARM rate */
+#define DIVCLK_FIXED_DIV BIT(1) /* Fixed divider */
+#define DIVCLK_ALWAYS_ENABLED BIT(2) /* Or bad things happen */
+
+struct davinci_pll_divclk_info {
+ const char *name;
+ const char *parent_name;
+ u32 id;
+ u32 flags;
+};
+
+#define DIVCLK(i, n, p, f) \
+{ \
+ .name = #n, \
+ .parent_name = #p, \
+ .id = (i), \
+ .flags = (f), \
+}
+
+struct clk;
+
+struct clk *davinci_pll_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base);
+struct clk *davinci_pll_aux_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base);
+struct clk *davinci_pll_bpdiv_clk_register(const char *name,
+ const char *parent_name,
+ void __iomem *base);
+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 *
+davinci_pll_divclk_register(const struct davinci_pll_divclk_info *info,
+ void __iomem *base);
+
+#ifdef CONFIG_OF
+struct device_node;
+
+void of_davinci_pll_init(struct device_node *node, const char *name,
+ const struct davinci_pll_divclk_info *info,
+ u8 max_divclk_id);
+#endif
+
+#endif /* __CLK_DAVINCI_PLL_H___ */
--
2.7.4

2018-01-08 02:30:35

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 03/44] clk: davinci: Add platform information for TI DA830 PLL

This adds platform-specific declarations for the PLL clocks on TI DA830/
OMAP-L137/AM17XX SoCs.

Signed-off-by: David Lechner <[email protected]>
---
drivers/clk/davinci/Makefile | 1 +
drivers/clk/davinci/pll-da830.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/clk/davinci.h | 14 ++++++++++++++
3 files changed, 53 insertions(+)
create mode 100644 drivers/clk/davinci/pll-da830.c
create mode 100644 include/linux/clk/davinci.h

diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
index d9673bd..9061e19 100644
--- a/drivers/clk/davinci/Makefile
+++ b/drivers/clk/davinci/Makefile
@@ -2,4 +2,5 @@

ifeq ($(CONFIG_COMMON_CLK), y)
obj-y += pll.o
+obj-$(CONFIG_ARCH_DAVINCI_DA830) += pll-da830.o
endif
diff --git a/drivers/clk/davinci/pll-da830.c b/drivers/clk/davinci/pll-da830.c
new file mode 100644
index 0000000..369db59
--- /dev/null
+++ b/drivers/clk/davinci/pll-da830.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DA830/OMAP-L137/AM17XX
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+/*
+ * NB: Technically, the clocks flagged as DIVCLK_FIXED_DIV are "fixed ratio",
+ * meaning that we could change the divider as long as we keep the correct
+ * ratio between all of the clocks, but we don't support that because there is
+ * currently not a need for it.
+ */
+
+static const struct davinci_pll_divclk_info da830_pll_divclk_info[] __initconst = {
+ DIVCLK(2, pll0_sysclk2, pll0, DIVCLK_FIXED_DIV),
+ DIVCLK(3, pll0_sysclk3, pll0, 0),
+ DIVCLK(4, pll0_sysclk4, pll0, DIVCLK_FIXED_DIV),
+ DIVCLK(5, pll0_sysclk5, pll0, 0),
+ DIVCLK(6, pll0_sysclk6, pll0, DIVCLK_FIXED_DIV),
+ DIVCLK(7, pll0_sysclk7, pll0, 0),
+ { }
+};
+
+void __init da830_pll_clk_init(void __iomem *pll)
+{
+ const struct davinci_pll_divclk_info *info;
+
+ davinci_pll_clk_register("pll0", "ref_clk", pll);
+ davinci_pll_aux_clk_register("pll0_aux_clk", "ref_clk", pll);
+ for (info = da830_pll_divclk_info; info->name; info++)
+ davinci_pll_divclk_register(info, pll);
+}
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
new file mode 100644
index 0000000..4f4d60d
--- /dev/null
+++ b/include/linux/clk/davinci.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI Davinci clocks
+ *
+ * Copyright (C) 2017 David Lechner <[email protected]>
+ */
+#ifndef __LINUX_CLK_DAVINCI_H__
+#define __LINUX_CLK_DAVINCI_H__
+
+#include <linux/types.h>
+
+void da830_pll_clk_init(void __iomem *pll);
+
+#endif /* __LINUX_CLK_DAVINCI_H__ */
--
2.7.4

2018-01-08 02:43:06

by David Lechner

[permalink] [raw]
Subject: [PATCH v5 35/44] ARM: da850: Remove legacy clock init

This removes the unused legacy clock init code from
arch/arm/mach-davinci/da850.c.

Signed-off-by: David Lechner <[email protected]>
---
arch/arm/mach-davinci/da850.c | 638 +-----------------------------------------
1 file changed, 1 insertion(+), 637 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 4804096..a482026 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -37,559 +37,12 @@

#include "mux.h"

-#ifndef CONFIG_COMMON_CLK
-#include "clock.h"
-#include "psc.h"
-#endif
-
#define DA850_PLL1_BASE 0x01e1a000
#define DA850_TIMER64P2_BASE 0x01f0c000
#define DA850_TIMER64P3_BASE 0x01f0d000

#define DA850_REF_FREQ 24000000

-#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);
-
-static struct pll_data pll0_data = {
- .num = 1,
- .phys_base = DA8XX_PLL0_BASE,
- .flags = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
-};
-
-static struct clk ref_clk = {
- .name = "ref_clk",
- .rate = DA850_REF_FREQ,
- .set_rate = davinci_simple_set_rate,
-};
-
-static struct clk pll0_clk = {
- .name = "pll0",
- .parent = &ref_clk,
- .pll_data = &pll0_data,
- .flags = CLK_PLL,
- .set_rate = da850_set_pll0rate,
-};
-
-static struct clk pll0_aux_clk = {
- .name = "pll0_aux_clk",
- .parent = &pll0_clk,
- .flags = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll0_sysclk1 = {
- .name = "pll0_sysclk1",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV1,
-};
-
-static struct clk pll0_sysclk2 = {
- .name = "pll0_sysclk2",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV2,
-};
-
-static struct clk pll0_sysclk3 = {
- .name = "pll0_sysclk3",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV3,
- .set_rate = davinci_set_sysclk_rate,
- .maxrate = 100000000,
-};
-
-static struct clk pll0_sysclk4 = {
- .name = "pll0_sysclk4",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV4,
-};
-
-static struct clk pll0_sysclk5 = {
- .name = "pll0_sysclk5",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV5,
-};
-
-static struct clk pll0_sysclk6 = {
- .name = "pll0_sysclk6",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV6,
-};
-
-static struct clk pll0_sysclk7 = {
- .name = "pll0_sysclk7",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV7,
-};
-
-static struct pll_data pll1_data = {
- .num = 2,
- .phys_base = DA850_PLL1_BASE,
- .flags = PLL_HAS_POSTDIV,
-};
-
-static struct clk pll1_clk = {
- .name = "pll1",
- .parent = &ref_clk,
- .pll_data = &pll1_data,
- .flags = CLK_PLL,
-};
-
-static struct clk pll1_aux_clk = {
- .name = "pll1_aux_clk",
- .parent = &pll1_clk,
- .flags = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll1_sysclk2 = {
- .name = "pll1_sysclk2",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV2,
-};
-
-static struct clk pll1_sysclk3 = {
- .name = "pll1_sysclk3",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV3,
-};
-
-static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 val;
-
- val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-
- if (parent == &pll0_sysclk2) {
- val &= ~CFGCHIP3_ASYNC3_CLKSRC;
- } else if (parent == &pll1_sysclk2) {
- val |= CFGCHIP3_ASYNC3_CLKSRC;
- } else {
- pr_err("Bad parent on async3 clock mux\n");
- return -EINVAL;
- }
-
- writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-
- return 0;
-}
-
-static struct clk async3_clk = {
- .name = "async3",
- .parent = &pll1_sysclk2,
- .set_parent = da850_async3_set_parent,
-};
-
-static struct clk i2c0_clk = {
- .name = "i2c0",
- .parent = &pll0_aux_clk,
-};
-
-static struct clk timerp64_0_clk = {
- .name = "timer0",
- .parent = &pll0_aux_clk,
-};
-
-static struct clk timerp64_1_clk = {
- .name = "timer1",
- .parent = &pll0_aux_clk,
-};
-
-static struct clk arm_rom_clk = {
- .name = "arm_rom",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_ARM_RAM_ROM,
- .flags = ALWAYS_ENABLED,
-};
-
-static struct clk tpcc0_clk = {
- .name = "tpcc0",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_TPCC,
- .flags = ALWAYS_ENABLED | CLK_PSC,
-};
-
-static struct clk tptc0_clk = {
- .name = "tptc0",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_TPTC0,
- .flags = ALWAYS_ENABLED,
-};
-
-static struct clk tptc1_clk = {
- .name = "tptc1",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_TPTC1,
- .flags = ALWAYS_ENABLED,
-};
-
-static struct clk tpcc1_clk = {
- .name = "tpcc1",
- .parent = &pll0_sysclk2,
- .lpsc = DA850_LPSC1_TPCC1,
- .gpsc = 1,
- .flags = CLK_PSC | ALWAYS_ENABLED,
-};
-
-static struct clk tptc2_clk = {
- .name = "tptc2",
- .parent = &pll0_sysclk2,
- .lpsc = DA850_LPSC1_TPTC2,
- .gpsc = 1,
- .flags = ALWAYS_ENABLED,
-};
-
-static struct clk pruss_clk = {
- .name = "pruss",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_PRUSS,
-};
-
-static struct clk uart0_clk = {
- .name = "uart0",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_UART0,
-};
-
-static struct clk uart1_clk = {
- .name = "uart1",
- .parent = &async3_clk,
- .lpsc = DA8XX_LPSC1_UART1,
- .gpsc = 1,
-};
-
-static struct clk uart2_clk = {
- .name = "uart2",
- .parent = &async3_clk,
- .lpsc = DA8XX_LPSC1_UART2,
- .gpsc = 1,
-};
-
-static struct clk aintc_clk = {
- .name = "aintc",
- .parent = &pll0_sysclk4,
- .lpsc = DA8XX_LPSC0_AINTC,
- .flags = ALWAYS_ENABLED,
-};
-
-static struct clk gpio_clk = {
- .name = "gpio",
- .parent = &pll0_sysclk4,
- .lpsc = DA8XX_LPSC1_GPIO,
- .gpsc = 1,
-};
-
-static struct clk i2c1_clk = {
- .name = "i2c1",
- .parent = &pll0_sysclk4,
- .lpsc = DA8XX_LPSC1_I2C,
- .gpsc = 1,
-};
-
-static struct clk emif3_clk = {
- .name = "emif3",
- .parent = &pll0_sysclk5,
- .lpsc = DA8XX_LPSC1_EMIF3C,
- .gpsc = 1,
- .flags = ALWAYS_ENABLED,
-};
-
-static struct clk arm_clk = {
- .name = "arm",
- .parent = &pll0_sysclk6,
- .lpsc = DA8XX_LPSC0_ARM,
- .flags = ALWAYS_ENABLED,
- .set_rate = da850_set_armrate,
- .round_rate = da850_round_armrate,
-};
-
-static struct clk rmii_clk = {
- .name = "rmii",
- .parent = &pll0_sysclk7,
-};
-
-static struct clk emac_clk = {
- .name = "emac",
- .parent = &pll0_sysclk4,
- .lpsc = DA8XX_LPSC1_CPGMAC,
- .gpsc = 1,
-};
-
-/*
- * In order to avoid adding the emac_clk to the clock lookup table twice (and
- * screwing up the linked list in the process) create a separate clock for
- * mdio inheriting the rate from emac_clk.
- */
-static struct clk mdio_clk = {
- .name = "mdio",
- .parent = &emac_clk,
-};
-
-static struct clk mcasp_clk = {
- .name = "mcasp",
- .parent = &async3_clk,
- .lpsc = DA8XX_LPSC1_McASP0,
- .gpsc = 1,
-};
-
-static struct clk mcbsp0_clk = {
- .name = "mcbsp0",
- .parent = &async3_clk,
- .lpsc = DA850_LPSC1_McBSP0,
- .gpsc = 1,
-};
-
-static struct clk mcbsp1_clk = {
- .name = "mcbsp1",
- .parent = &async3_clk,
- .lpsc = DA850_LPSC1_McBSP1,
- .gpsc = 1,
-};
-
-static struct clk lcdc_clk = {
- .name = "lcdc",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC1_LCDC,
- .gpsc = 1,
-};
-
-static struct clk mmcsd0_clk = {
- .name = "mmcsd0",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_MMC_SD,
-};
-
-static struct clk mmcsd1_clk = {
- .name = "mmcsd1",
- .parent = &pll0_sysclk2,
- .lpsc = DA850_LPSC1_MMC_SD1,
- .gpsc = 1,
-};
-
-static struct clk aemif_clk = {
- .name = "aemif",
- .parent = &pll0_sysclk3,
- .lpsc = DA8XX_LPSC0_EMIF25,
- .flags = ALWAYS_ENABLED,
-};
-
-/*
- * In order to avoid adding the aemif_clk to the clock lookup table twice (and
- * screwing up the linked list in the process) create a separate clock for
- * nand inheriting the rate from aemif_clk.
- */
-static struct clk aemif_nand_clk = {
- .name = "nand",
- .parent = &aemif_clk,
-};
-
-static struct clk usb11_clk = {
- .name = "usb11",
- .parent = &pll0_sysclk4,
- .lpsc = DA8XX_LPSC1_USB11,
- .gpsc = 1,
-};
-
-static struct clk usb20_clk = {
- .name = "usb20",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC1_USB20,
- .gpsc = 1,
-};
-
-static struct clk cppi41_clk = {
- .name = "cppi41",
- .parent = &usb20_clk,
-};
-
-static struct clk spi0_clk = {
- .name = "spi0",
- .parent = &pll0_sysclk2,
- .lpsc = DA8XX_LPSC0_SPI0,
-};
-
-static struct clk spi1_clk = {
- .name = "spi1",
- .parent = &async3_clk,
- .lpsc = DA8XX_LPSC1_SPI1,
- .gpsc = 1,
-};
-
-static struct clk vpif_clk = {
- .name = "vpif",
- .parent = &pll0_sysclk2,
- .lpsc = DA850_LPSC1_VPIF,
- .gpsc = 1,
-};
-
-static struct clk sata_clk = {
- .name = "sata",
- .parent = &pll0_sysclk2,
- .lpsc = DA850_LPSC1_SATA,
- .gpsc = 1,
- .flags = PSC_FORCE,
-};
-
-static struct clk dsp_clk = {
- .name = "dsp",
- .parent = &pll0_sysclk1,
- .domain = DAVINCI_GPSC_DSPDOMAIN,
- .lpsc = DA8XX_LPSC0_GEM,
- .flags = PSC_LRST | PSC_FORCE,
-};
-
-static struct clk ehrpwm_clk = {
- .name = "ehrpwm",
- .parent = &async3_clk,
- .lpsc = DA8XX_LPSC1_PWM,
- .gpsc = 1,
-};
-
-static struct clk ehrpwm0_clk = {
- .name = "ehrpwm0",
- .parent = &ehrpwm_clk,
-};
-
-static struct clk ehrpwm1_clk = {
- .name = "ehrpwm1",
- .parent = &ehrpwm_clk,
-};
-
-#define DA8XX_EHRPWM_TBCLKSYNC BIT(12)
-
-static void ehrpwm_tblck_enable(struct clk *clk)
-{
- u32 val;
-
- val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
- val |= DA8XX_EHRPWM_TBCLKSYNC;
- writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
-}
-
-static void ehrpwm_tblck_disable(struct clk *clk)
-{
- u32 val;
-
- val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
- val &= ~DA8XX_EHRPWM_TBCLKSYNC;
- writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
-}
-
-static struct clk ehrpwm_tbclk = {
- .name = "ehrpwm_tbclk",
- .parent = &ehrpwm_clk,
- .clk_enable = ehrpwm_tblck_enable,
- .clk_disable = ehrpwm_tblck_disable,
-};
-
-static struct clk ehrpwm0_tbclk = {
- .name = "ehrpwm0_tbclk",
- .parent = &ehrpwm_tbclk,
-};
-
-static struct clk ehrpwm1_tbclk = {
- .name = "ehrpwm1_tbclk",
- .parent = &ehrpwm_tbclk,
-};
-
-static struct clk ecap_clk = {
- .name = "ecap",
- .parent = &async3_clk,
- .lpsc = DA8XX_LPSC1_ECAP,
- .gpsc = 1,
-};
-
-static struct clk ecap0_clk = {
- .name = "ecap0_clk",
- .parent = &ecap_clk,
-};
-
-static struct clk ecap1_clk = {
- .name = "ecap1_clk",
- .parent = &ecap_clk,
-};
-
-static struct clk ecap2_clk = {
- .name = "ecap2_clk",
- .parent = &ecap_clk,
-};
-
-static struct clk_lookup da850_clks[] = {
- CLK(NULL, "ref", &ref_clk),
- CLK(NULL, "pll0", &pll0_clk),
- CLK(NULL, "pll0_aux", &pll0_aux_clk),
- CLK(NULL, "pll0_sysclk1", &pll0_sysclk1),
- CLK(NULL, "pll0_sysclk2", &pll0_sysclk2),
- CLK(NULL, "pll0_sysclk3", &pll0_sysclk3),
- CLK(NULL, "pll0_sysclk4", &pll0_sysclk4),
- CLK(NULL, "pll0_sysclk5", &pll0_sysclk5),
- CLK(NULL, "pll0_sysclk6", &pll0_sysclk6),
- CLK(NULL, "pll0_sysclk7", &pll0_sysclk7),
- CLK(NULL, "pll1", &pll1_clk),
- CLK(NULL, "pll1_aux", &pll1_aux_clk),
- CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
- CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
- CLK(NULL, "async3", &async3_clk),
- CLK("i2c_davinci.1", NULL, &i2c0_clk),
- CLK(NULL, "timer0", &timerp64_0_clk),
- CLK("davinci-wdt", NULL, &timerp64_1_clk),
- CLK(NULL, "arm_rom", &arm_rom_clk),
- CLK(NULL, "tpcc0", &tpcc0_clk),
- CLK(NULL, "tptc0", &tptc0_clk),
- CLK(NULL, "tptc1", &tptc1_clk),
- CLK(NULL, "tpcc1", &tpcc1_clk),
- CLK(NULL, "tptc2", &tptc2_clk),
- CLK("pruss_uio", "pruss", &pruss_clk),
- CLK("serial8250.0", NULL, &uart0_clk),
- CLK("serial8250.1", NULL, &uart1_clk),
- CLK("serial8250.2", NULL, &uart2_clk),
- CLK(NULL, "aintc", &aintc_clk),
- CLK(NULL, "gpio", &gpio_clk),
- CLK("i2c_davinci.2", NULL, &i2c1_clk),
- CLK(NULL, "emif3", &emif3_clk),
- CLK(NULL, "arm", &arm_clk),
- CLK(NULL, "rmii", &rmii_clk),
- CLK("davinci_emac.1", NULL, &emac_clk),
- CLK("davinci_mdio.0", "fck", &mdio_clk),
- CLK("davinci-mcasp.0", NULL, &mcasp_clk),
- CLK("davinci-mcbsp.0", NULL, &mcbsp0_clk),
- CLK("davinci-mcbsp.1", NULL, &mcbsp1_clk),
- CLK("da8xx_lcdc.0", "fck", &lcdc_clk),
- CLK("da830-mmc.0", NULL, &mmcsd0_clk),
- CLK("da830-mmc.1", NULL, &mmcsd1_clk),
- CLK("ti-aemif", NULL, &aemif_clk),
- CLK("davinci-nand.0", "aemif", &aemif_nand_clk),
- CLK("ohci-da8xx", NULL, &usb11_clk),
- CLK("musb-da8xx", NULL, &usb20_clk),
- CLK("cppi41-dmaengine", NULL, &cppi41_clk),
- CLK("spi_davinci.0", NULL, &spi0_clk),
- CLK("spi_davinci.1", NULL, &spi1_clk),
- CLK("vpif", NULL, &vpif_clk),
- CLK("ahci_da850", "fck", &sata_clk),
- CLK("davinci-rproc.0", NULL, &dsp_clk),
- CLK(NULL, NULL, &ehrpwm_clk),
- CLK("ehrpwm.0", "fck", &ehrpwm0_clk),
- CLK("ehrpwm.1", "fck", &ehrpwm1_clk),
- CLK(NULL, NULL, &ehrpwm_tbclk),
- CLK("ehrpwm.0", "tbclk", &ehrpwm0_tbclk),
- CLK("ehrpwm.1", "tbclk", &ehrpwm1_tbclk),
- CLK(NULL, NULL, &ecap_clk),
- CLK("ecap.0", "fck", &ecap0_clk),
- CLK("ecap.1", "fck", &ecap1_clk),
- CLK("ecap.2", "fck", &ecap2_clk),
- CLK(NULL, NULL, NULL),
-};
-#endif
-
/*
* Device specific mux setup
*
@@ -964,8 +417,6 @@ static struct map_desc da850_io_desc[] = {
},
};

-static u32 da850_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE };
-
/* Contents of JTAG ID register used to identify exact cpu type */
static struct davinci_id da850_ids[] = {
{
@@ -1175,93 +626,11 @@ int da850_register_cpufreq(char *async_clk)

return platform_device_register(&da850_cpufreq_device);
}
-
-#ifndef CONFIG_COMMON_CLK
-static int da850_round_armrate(struct clk *clk, unsigned long rate)
-{
- int ret = 0, diff;
- unsigned int best = (unsigned int) -1;
- struct cpufreq_frequency_table *table = cpufreq_info.freq_table;
- struct cpufreq_frequency_table *pos;
-
- rate /= 1000; /* convert to kHz */
-
- cpufreq_for_each_entry(pos, table) {
- diff = pos->frequency - rate;
- if (diff < 0)
- diff = -diff;
-
- if (diff < best) {
- best = diff;
- ret = pos->frequency;
- }
- }
-
- return ret * 1000;
-}
-
-static int da850_set_armrate(struct clk *clk, unsigned long index)
-{
- struct clk *pllclk = &pll0_clk;
-
- return clk_set_rate(pllclk, index);
-}
-
-static int da850_set_pll0rate(struct clk *clk, unsigned long rate)
-{
- struct pll_data *pll = clk->pll_data;
- struct cpufreq_frequency_table *freq;
- unsigned int prediv, mult, postdiv;
- struct da850_opp *opp = NULL;
- int ret;
-
- rate /= 1000;
-
- for (freq = da850_freq_table;
- freq->frequency != CPUFREQ_TABLE_END; freq++) {
- /* rate is in Hz, freq->frequency is in KHz */
- if (freq->frequency == rate) {
- opp = (struct da850_opp *)freq->driver_data;
- break;
- }
- }
-
- if (!opp)
- return -EINVAL;
-
- prediv = opp->prediv;
- mult = opp->mult;
- postdiv = opp->postdiv;
-
- ret = davinci_set_pllrate(pll, prediv, mult, postdiv);
- if (WARN_ON(ret))
- return ret;
-
- return 0;
-}
-#endif /* CONFIG_COMMON_CLK */
#else
int __init da850_register_cpufreq(char *async_clk)
{
return 0;
}
-
-#ifndef CONFIG_COMMON_CLK
-static int da850_set_armrate(struct clk *clk, unsigned long rate)
-{
- return -EINVAL;
-}
-
-static int da850_set_pll0rate(struct clk *clk, unsigned long armrate)
-{
- return -EINVAL;
-}
-
-static int da850_round_armrate(struct clk *clk, unsigned long rate)
-{
- return clk->rate;
-}
-#endif /* CONFIG_COMMON_CLK */
#endif

/* VPIF resource, platform data */
@@ -1363,8 +732,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = {
.jtag_id_reg = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG,
.ids = da850_ids,
.ids_num = ARRAY_SIZE(da850_ids),
- .psc_bases = da850_psc_bases,
- .psc_bases_num = ARRAY_SIZE(da850_psc_bases),
.pinmux_base = DA8XX_SYSCFG0_BASE + 0x120,
.pinmux_pins = da850_pins,
.pinmux_pins_num = ARRAY_SIZE(da850_pins),
@@ -1405,7 +772,6 @@ void __init da850_init(void)

void __init da850_init_time(void)
{
-#ifdef CONFIG_COMMON_CLK
void __iomem *pll0, *pll1, *psc0, *psc1;
struct clk *clk;
struct clk_hw *parent;
@@ -1441,8 +807,6 @@ void __init da850_init_time(void)
ilog2(CFGCHIP1_TBCLKSYNC), 0, NULL);
clk_register_clkdev(clk, "tbclk", "ehrpwm.0");
clk_register_clkdev(clk, "tbclk", "ehrpwm.1");
-#else
- davinci_clk_init(da850_clks);
-#endif
+
davinci_timer_init();
}
--
2.7.4

2018-01-08 14:01:30

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new binding for the PLL IP blocks in the mach-davinci family
> of processors. Currently, only the SYSCLKn and AUXCLK outputs are needed,
> but in the future additional child nodes could be added for OBSCLK and
> BPDIV.
>
> Note: Although these PLL controllers are very similar to the TI Keystone
> SoCs, we are not re-using those bindings. The Keystone bindings use a
> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs

Not sure what is meant by "legacy one-node-per-clock binding"

> have a slightly different PLL register layout and a number of quirks that
> can't be handled by the existing bindings, so the keystone bindings could
> not be used as-is anyway.

Right, I think different register layout between the processors is the
main reason for a new driver. This should be sufficient reason IMO.

>
> Signed-off-by: David Lechner <[email protected]>
> ---
> .../devicetree/bindings/clock/ti/davinci/pll.txt | 47 ++++++++++++++++++++++
> 1 file changed, 47 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> new file mode 100644
> index 0000000..99bf5da
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> @@ -0,0 +1,47 @@
> +Binding for TI DaVinci PLL Controllers
> +
> +The PLL provides clocks to most of the components on the SoC. In addition
> +to the PLL itself, this controller also contains bypasses, gates, dividers,
> +an multiplexers for various clock signals.
> +
> +Required properties:
> +- compatible: shall be one of:
> + - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
> + - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX

These PLLs are same IP so they should use the same compatible. You can
initialize both PLLs for DA850 based on the same compatible.

Thanks,
Sekhar

2018-01-08 16:29:14

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/08/2018 08:00 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds a new binding for the PLL IP blocks in the mach-davinci family
>> of processors. Currently, only the SYSCLKn and AUXCLK outputs are needed,
>> but in the future additional child nodes could be added for OBSCLK and
>> BPDIV.
>>
>> Note: Although these PLL controllers are very similar to the TI Keystone
>> SoCs, we are not re-using those bindings. The Keystone bindings use a
>> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs
>
> Not sure what is meant by "legacy one-node-per-clock binding"

It's a term I picked up from of_clk_detect_critical()

* Do not use this function. It exists only for legacy Device Tree
* bindings, such as the one-clock-per-node style that are outdated.
* Those bindings typically put all clock data into .dts and the Linux
* driver has no clock data, thus making it impossible to set this flag
* correctly from the driver. Only those drivers may call
* of_clk_detect_critical from their setup functions.

>
>> have a slightly different PLL register layout and a number of quirks that
>> can't be handled by the existing bindings, so the keystone bindings could
>> not be used as-is anyway.
>
> Right, I think different register layout between the processors is the
> main reason for a new driver. This should be sufficient reason IMO.
>
>>
>> Signed-off-by: David Lechner <[email protected]>
>> ---
>> .../devicetree/bindings/clock/ti/davinci/pll.txt | 47 ++++++++++++++++++++++
>> 1 file changed, 47 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>> new file mode 100644
>> index 0000000..99bf5da
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>> @@ -0,0 +1,47 @@
>> +Binding for TI DaVinci PLL Controllers
>> +
>> +The PLL provides clocks to most of the components on the SoC. In addition
>> +to the PLL itself, this controller also contains bypasses, gates, dividers,
>> +an multiplexers for various clock signals.
>> +
>> +Required properties:
>> +- compatible: shall be one of:
>> + - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>> + - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
>
> These PLLs are same IP so they should use the same compatible. You can
> initialize both PLLs for DA850 based on the same compatible.
>

But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks while
PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain SYSCLKs
that are fixed-ratio but PLL1 does not have any of these. There are even more
differences, but these are the ones we are actually using.

So, if we use the same compatible, we either have to come up with device tree
bindings to describe all of this (yuck) or I suppose we can look at the REVID
register to electronically determine exactly what we have. I went with the
simpler option of just creating two different compatible strings.


2018-01-09 12:36:42

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Monday 08 January 2018 09:59 PM, David Lechner wrote:
> On 01/08/2018 08:00 AM, Sekhar Nori wrote:
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>> This adds a new binding for the PLL IP blocks in the mach-davinci family
>>> of processors. Currently, only the SYSCLKn and AUXCLK outputs are
>>> needed,
>>> but in the future additional child nodes could be added for OBSCLK and
>>> BPDIV.
>>>
>>> Note: Although these PLL controllers are very similar to the TI Keystone
>>> SoCs, we are not re-using those bindings. The Keystone bindings use a
>>> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs
>>
>> Not sure what is meant by "legacy one-node-per-clock binding"
>
> It's a term I picked up from of_clk_detect_critical()
>
>  * Do not use this function. It exists only for legacy Device Tree
>  * bindings, such as the one-clock-per-node style that are outdated.
>  * Those bindings typically put all clock data into .dts and the Linux
>  * driver has no clock data, thus making it impossible to set this flag
>  * correctly from the driver. Only those drivers may call
>  * of_clk_detect_critical from their setup functions.

Okay, I still don't understand the outdated style. I looked at clocks
defined in arch/arm/boot/dts/stih407-clock.dtsi which is the only file
that uses clock-critical and don't particularly see anything wrong with
the way clocks are defined there.

Anyway, I guess we digress. As long as this patch series is not using
the "legacy style", we are good :)

>>> have a slightly different PLL register layout and a number of quirks
>>> that
>>> can't be handled by the existing bindings, so the keystone bindings
>>> could
>>> not be used as-is anyway.
>>
>> Right, I think different register layout between the processors is the
>> main reason for a new driver. This should be sufficient reason IMO.
>>
>>>
>>> Signed-off-by: David Lechner <[email protected]>
>>> ---
>>>   .../devicetree/bindings/clock/ti/davinci/pll.txt   | 47
>>> ++++++++++++++++++++++
>>>   1 file changed, 47 insertions(+)
>>>   create mode 100644
>>> Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>
>>> diff --git
>>> a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>> b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>> new file mode 100644
>>> index 0000000..99bf5da
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>> @@ -0,0 +1,47 @@
>>> +Binding for TI DaVinci PLL Controllers
>>> +
>>> +The PLL provides clocks to most of the components on the SoC. In
>>> addition
>>> +to the PLL itself, this controller also contains bypasses, gates,
>>> dividers,
>>> +an multiplexers for various clock signals.
>>> +
>>> +Required properties:
>>> +- compatible: shall be one of:
>>> +    - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>>> +    - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
>>
>> These PLLs are same IP so they should use the same compatible. You can
>> initialize both PLLs for DA850 based on the same compatible.
>>
>
> But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks
> while
> PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain
> SYSCLKs
> that are fixed-ratio but PLL1 does not have any of these. There are even
> more
> differences, but these are the ones we are actually using.

We need each element of the PLLC to be modeled individually as a clock
node. That is, PLL should only model the multiplier, the dividers
including post and prediv should be modeled as divider clocks (hopefully
being able to use the clk-divider.c library). The sysclks can be
fixed-factor-clock type clocks.

Without this flexible mechanism, we cannot (at least later) model things
like DIV4.5 clock which is the only clock which derives from the output
of PLL multiplier before the post divider is applied.

Since with DT there are are no retakes, we need to get this right the
first time and modifying later will not be an option.

>
> So, if we use the same compatible, we either have to come up with device
> tree
> bindings to describe all of this (yuck) or I suppose we can look at the
> REVID
> register to electronically determine exactly what we have. I went with the
> simpler option of just creating two different compatible strings.

Thanks,
Sekhar

2018-01-10 03:01:35

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/09/2018 06:35 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 09:59 PM, David Lechner wrote:
>> On 01/08/2018 08:00 AM, Sekhar Nori wrote:
>>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>>> This adds a new binding for the PLL IP blocks in the mach-davinci family
>>>> of processors. Currently, only the SYSCLKn and AUXCLK outputs are
>>>> needed,
>>>> but in the future additional child nodes could be added for OBSCLK and
>>>> BPDIV.
>>>>
>>>> Note: Although these PLL controllers are very similar to the TI Keystone
>>>> SoCs, we are not re-using those bindings. The Keystone bindings use a
>>>> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs
>>>
>>> Not sure what is meant by "legacy one-node-per-clock binding"
>>
>> It's a term I picked up from of_clk_detect_critical()
>>
>>  * Do not use this function. It exists only for legacy Device Tree
>>  * bindings, such as the one-clock-per-node style that are outdated.
>>  * Those bindings typically put all clock data into .dts and the Linux
>>  * driver has no clock data, thus making it impossible to set this flag
>>  * correctly from the driver. Only those drivers may call
>>  * of_clk_detect_critical from their setup functions.
>
> Okay, I still don't understand the outdated style. I looked at clocks
> defined in arch/arm/boot/dts/stih407-clock.dtsi which is the only file
> that uses clock-critical and don't particularly see anything wrong with
> the way clocks are defined there.
>
> Anyway, I guess we digress. As long as this patch series is not using
> the "legacy style", we are good :)
>
>>>> have a slightly different PLL register layout and a number of quirks
>>>> that
>>>> can't be handled by the existing bindings, so the keystone bindings
>>>> could
>>>> not be used as-is anyway.
>>>
>>> Right, I think different register layout between the processors is the
>>> main reason for a new driver. This should be sufficient reason IMO.
>>>
>>>>
>>>> Signed-off-by: David Lechner <[email protected]>
>>>> ---
>>>>   .../devicetree/bindings/clock/ti/davinci/pll.txt   | 47
>>>> ++++++++++++++++++++++
>>>>   1 file changed, 47 insertions(+)
>>>>   create mode 100644
>>>> Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>
>>>> diff --git
>>>> a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>> b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>> new file mode 100644
>>>> index 0000000..99bf5da
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>> @@ -0,0 +1,47 @@
>>>> +Binding for TI DaVinci PLL Controllers
>>>> +
>>>> +The PLL provides clocks to most of the components on the SoC. In
>>>> addition
>>>> +to the PLL itself, this controller also contains bypasses, gates,
>>>> dividers,
>>>> +an multiplexers for various clock signals.
>>>> +
>>>> +Required properties:
>>>> +- compatible: shall be one of:
>>>> +    - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>>>> +    - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
>>>
>>> These PLLs are same IP so they should use the same compatible. You can
>>> initialize both PLLs for DA850 based on the same compatible.
>>>
>>
>> But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks
>> while
>> PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain
>> SYSCLKs
>> that are fixed-ratio but PLL1 does not have any of these. There are even
>> more
>> differences, but these are the ones we are actually using.
>
> We need each element of the PLLC to be modeled individually as a clock
> node.

I gave this a good think while I have been working on this series
and I came to the conclusion that we really don't need to do this.
These components are all internal to the PLL IP block, so the
compatible string is enough to tell us what we have. They only
thing we need really in the device tree bindings are the connections
that are external to the IP block.


> That is, PLL should only model the multiplier, the dividers
> including post and prediv should be modeled as divider clocks (hopefully
> being able to use the clk-divider.c library). The sysclks can be
> fixed-factor-clock type clocks.
>
> Without this flexible mechanism, we cannot (at least later) model things
> like DIV4.5 clock which is the only clock which derives from the output
> of PLL multiplier before the post divider is applied.
>
> Since with DT there are are no retakes, we need to get this right the
> first time and modifying later will not be an option.
>

So, the full device tree binding would look something like this:

+
+ pll0: clock-controller@11000 {
+ compatible = "ti,da850-pll0";
+ reg = <0x11000 0x1000>;
+ clocks = <&ref_clk>, <&pll1_sysclk 3>, <&pll1_obsclk>;
+ clock-names = "oscin", pll1_sysclk3", "pll1_osbclk";
+ oscin-square-wave;
+
+ pll0_sysclk: sysclk {
+ #clock-cells = <1>;
+ };
+
+ pll0_auxclk: auxclk {
+ #clock-cells = <0>;
+ };
+
+ pll0_div45: div4.5 {
+ #clock-cells = <0>;
+ };
+
+ pll0_obsclk: obsclk {
+ #clock-cells = <0>;
+ assigned-clocks = <&pll0_sysclk 1>;
+ assigned-clock-names = "ocsrc";
+ };
+ };

There are three clocks coming into the IP block and there are 11 clocks
going out (sysclk is 7 clocks). And you can specify the board-specific
configuration, like having the "oscin-square-wave" flag when a square wave
is used instead of a crystal oscillator and you can assign the multiplexer
input that will be used by obsclk. (And, this binding is totally compatible
with the binding I have already proposed - although, I see now it would
be better to go ahead and add the clocks-names property.)

How everything connects together is all implemented in the driver and the
driver will be able to know what to do just by looking at the compatible
string.

Part of my motivation for doing things this way comes from my recent
experience with writing some bindings for some LCD panels. These
device tree bindings were notorious for trying to be one-size-fits
all will lots of properties to try to describe all of the internal
workings. And it turns out that just having a new compatible string
for each device or variant and pushing all of details of the quirks
into the driver is much simpler and cleaner and will make it easier
for other projects to reuse the bindings.

2018-01-10 18:54:02

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Wednesday 10 January 2018 08:31 AM, David Lechner wrote:
> On 01/09/2018 06:35 AM, Sekhar Nori wrote:
>> On Monday 08 January 2018 09:59 PM, David Lechner wrote:
>>> On 01/08/2018 08:00 AM, Sekhar Nori wrote:
>>>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:

>>>>> diff --git
>>>>> a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>> b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>> new file mode 100644
>>>>> index 0000000..99bf5da
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>> @@ -0,0 +1,47 @@
>>>>> +Binding for TI DaVinci PLL Controllers
>>>>> +
>>>>> +The PLL provides clocks to most of the components on the SoC. In
>>>>> addition
>>>>> +to the PLL itself, this controller also contains bypasses, gates,
>>>>> dividers,
>>>>> +an multiplexers for various clock signals.
>>>>> +
>>>>> +Required properties:
>>>>> +- compatible: shall be one of:
>>>>> +    - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>>>>> +    - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
>>>>
>>>> These PLLs are same IP so they should use the same compatible. You can
>>>> initialize both PLLs for DA850 based on the same compatible.
>>>>
>>>
>>> But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks
>>> while
>>> PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain
>>> SYSCLKs
>>> that are fixed-ratio but PLL1 does not have any of these. There are even
>>> more
>>> differences, but these are the ones we are actually using.
>>
>> We need each element of the PLLC to be modeled individually as a clock
>> node.
>
> I gave this a good think while I have been working on this series
> and I came to the conclusion that we really don't need to do this.
> These components are all internal to the PLL IP block, so the
> compatible string is enough to tell us what we have. They only
> thing we need really in the device tree bindings are the connections
> that are external to the IP block.
>
>
>> That is, PLL should only model the multiplier, the dividers
>> including post and prediv should be modeled as divider clocks (hopefully
>> being able to use the clk-divider.c library). The sysclks can be
>> fixed-factor-clock type clocks.
>>
>> Without this flexible mechanism, we cannot (at least later) model things
>> like DIV4.5 clock which is the only clock which derives from the output
>> of PLL multiplier before the post divider is applied.
>>
>> Since with DT there are are no retakes, we need to get this right the
>> first time and modifying later will not be an option.
>>
>
> So, the full device tree binding would look something like this:
>
> +
> +    pll0: clock-controller@11000 {
> +        compatible = "ti,da850-pll0";
> +        reg = <0x11000 0x1000>;
> +        clocks = <&ref_clk>, <&pll1_sysclk 3>, <&pll1_obsclk>;
> +        clock-names = "oscin", pll1_sysclk3", "pll1_osbclk";
> +        oscin-square-wave;
> +
> +        pll0_sysclk: sysclk {
> +            #clock-cells = <1>;
> +        };
> +
> +        pll0_auxclk: auxclk {
> +            #clock-cells = <0>;
> +        };
> +
> +        pll0_div45: div4.5 {
> +            #clock-cells = <0>;
> +        };
> +
> +        pll0_obsclk: obsclk {
> +            #clock-cells = <0>;
> +            assigned-clocks = <&pll0_sysclk 1>;
> +            assigned-clock-names = "ocsrc";
> +        };
> +    };

Well, I guess this will work as well. And I am probably biased towards
the style I mentioned because AM335x and other TI OMAP processors
follow that.

To make it easy to review that we have all bases covered, can you model
the all PLLC0 and PLLC1 (input and output) clocks for the next version?

>
> There are three clocks coming into the IP block and there are 11 clocks
> going out (sysclk is 7 clocks). And you can specify the board-specific
> configuration, like having the "oscin-square-wave" flag when a square wave
> is used instead of a crystal oscillator and you can assign the multiplexer

Ideally the OSCIN vs CLKIN selection should be another clock mux whose
output is one of the input clocks to PLL controller. But I can see the
difficulty in handling that as the mux itself is controlled by the PLL
controller.

> input that will be used by obsclk. (And, this binding is totally compatible
> with the binding I have already proposed - although, I see now it would
> be better to go ahead and add the clocks-names property.)

Also, please add the oscin-square-wave to the binding definition too.

For the benefit of others reviewing and not familiar with the hardware,
the users guide for DA850 is here:
http://www.ti.com/lit/ug/spruh77c/spruh77c.pdf

and the PLL block diagram is on page 143 (Figure 8-1).

Thanks,
Sekhar

2018-01-10 22:24:28

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Wed, Jan 10, 2018 at 12:52 PM, Sekhar Nori <[email protected]> wrote:
> On Wednesday 10 January 2018 08:31 AM, David Lechner wrote:
>> On 01/09/2018 06:35 AM, Sekhar Nori wrote:
>>> On Monday 08 January 2018 09:59 PM, David Lechner wrote:
>>>> On 01/08/2018 08:00 AM, Sekhar Nori wrote:
>>>>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>
>>>>>> diff --git
>>>>>> a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>>> b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>>> new file mode 100644
>>>>>> index 0000000..99bf5da
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>>> @@ -0,0 +1,47 @@
>>>>>> +Binding for TI DaVinci PLL Controllers
>>>>>> +
>>>>>> +The PLL provides clocks to most of the components on the SoC. In
>>>>>> addition
>>>>>> +to the PLL itself, this controller also contains bypasses, gates,
>>>>>> dividers,
>>>>>> +an multiplexers for various clock signals.
>>>>>> +
>>>>>> +Required properties:
>>>>>> +- compatible: shall be one of:
>>>>>> + - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>>>>>> + - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
>>>>>
>>>>> These PLLs are same IP so they should use the same compatible. You can
>>>>> initialize both PLLs for DA850 based on the same compatible.
>>>>>
>>>>
>>>> But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks
>>>> while
>>>> PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain
>>>> SYSCLKs
>>>> that are fixed-ratio but PLL1 does not have any of these. There are even
>>>> more
>>>> differences, but these are the ones we are actually using.
>>>
>>> We need each element of the PLLC to be modeled individually as a clock
>>> node.
>>
>> I gave this a good think while I have been working on this series
>> and I came to the conclusion that we really don't need to do this.
>> These components are all internal to the PLL IP block, so the
>> compatible string is enough to tell us what we have. They only
>> thing we need really in the device tree bindings are the connections
>> that are external to the IP block.
>>
>>
>>> That is, PLL should only model the multiplier, the dividers
>>> including post and prediv should be modeled as divider clocks (hopefully
>>> being able to use the clk-divider.c library). The sysclks can be
>>> fixed-factor-clock type clocks.
>>>
>>> Without this flexible mechanism, we cannot (at least later) model things
>>> like DIV4.5 clock which is the only clock which derives from the output
>>> of PLL multiplier before the post divider is applied.
>>>
>>> Since with DT there are are no retakes, we need to get this right the
>>> first time and modifying later will not be an option.
>>>
>>
>> So, the full device tree binding would look something like this:
>>
>> +
>> + pll0: clock-controller@11000 {
>> + compatible = "ti,da850-pll0";
>> + reg = <0x11000 0x1000>;
>> + clocks = <&ref_clk>, <&pll1_sysclk 3>, <&pll1_obsclk>;
>> + clock-names = "oscin", pll1_sysclk3", "pll1_osbclk";
>> + oscin-square-wave;
>> +
>> + pll0_sysclk: sysclk {
>> + #clock-cells = <1>;
>> + };
>> +
>> + pll0_auxclk: auxclk {
>> + #clock-cells = <0>;
>> + };
>> +
>> + pll0_div45: div4.5 {
>> + #clock-cells = <0>;
>> + };
>> +
>> + pll0_obsclk: obsclk {
>> + #clock-cells = <0>;
>> + assigned-clocks = <&pll0_sysclk 1>;
>> + assigned-clock-names = "ocsrc";
>> + };
>> + };
>
> Well, I guess this will work as well. And I am probably biased towards
> the style I mentioned because AM335x and other TI OMAP processors
> follow that.
>
> To make it easy to review that we have all bases covered, can you model
> the all PLLC0 and PLLC1 (input and output) clocks for the next version?
>
>>
>> There are three clocks coming into the IP block and there are 11 clocks
>> going out (sysclk is 7 clocks). And you can specify the board-specific
>> configuration, like having the "oscin-square-wave" flag when a square wave
>> is used instead of a crystal oscillator and you can assign the multiplexer
>
> Ideally the OSCIN vs CLKIN selection should be another clock mux whose
> output is one of the input clocks to PLL controller. But I can see the
> difficulty in handling that as the mux itself is controlled by the PLL
> controller.
>
>> input that will be used by obsclk. (And, this binding is totally compatible
>> with the binding I have already proposed - although, I see now it would
>> be better to go ahead and add the clocks-names property.)
>
> Also, please add the oscin-square-wave to the binding definition too.
>
> For the benefit of others reviewing and not familiar with the hardware,
> the users guide for DA850 is here:
> http://www.ti.com/lit/ug/spruh77c/spruh77c.pdf
>

I am available tomorrow to build and test patches against the
da850-evm. I just need to know which version(s) to test.

adam

> and the PLL block diagram is on page 143 (Figure 8-1).
>
> Thanks,
> Sekhar

2018-01-11 02:50:28

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/10/2018 04:24 PM, Adam Ford wrote:
>
> I am available tomorrow to build and test patches against the
> da850-evm. I just need to know which version(s) to test.

Great. As per the cover letter:

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

2018-01-11 02:54:15

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/10/2018 12:52 PM, Sekhar Nori wrote:
> On Wednesday 10 January 2018 08:31 AM, David Lechner wrote:
>> On 01/09/2018 06:35 AM, Sekhar Nori wrote:
>>> On Monday 08 January 2018 09:59 PM, David Lechner wrote:
>>>> On 01/08/2018 08:00 AM, Sekhar Nori wrote:
>>>>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>
>>>>>> diff --git
>>>>>> a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>>> b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>>> new file mode 100644
>>>>>> index 0000000..99bf5da
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>>>>> @@ -0,0 +1,47 @@
>>>>>> +Binding for TI DaVinci PLL Controllers
>>>>>> +
>>>>>> +The PLL provides clocks to most of the components on the SoC. In
>>>>>> addition
>>>>>> +to the PLL itself, this controller also contains bypasses, gates,
>>>>>> dividers,
>>>>>> +an multiplexers for various clock signals.
>>>>>> +
>>>>>> +Required properties:
>>>>>> +- compatible: shall be one of:
>>>>>> +    - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>>>>>> +    - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
>>>>>
>>>>> These PLLs are same IP so they should use the same compatible. You can
>>>>> initialize both PLLs for DA850 based on the same compatible.
>>>>>
>>>>
>>>> But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks
>>>> while
>>>> PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain
>>>> SYSCLKs
>>>> that are fixed-ratio but PLL1 does not have any of these. There are even
>>>> more
>>>> differences, but these are the ones we are actually using.
>>>
>>> We need each element of the PLLC to be modeled individually as a clock
>>> node.
>>
>> I gave this a good think while I have been working on this series
>> and I came to the conclusion that we really don't need to do this.
>> These components are all internal to the PLL IP block, so the
>> compatible string is enough to tell us what we have. They only
>> thing we need really in the device tree bindings are the connections
>> that are external to the IP block.
>>
>>
>>> That is, PLL should only model the multiplier, the dividers
>>> including post and prediv should be modeled as divider clocks (hopefully
>>> being able to use the clk-divider.c library). The sysclks can be
>>> fixed-factor-clock type clocks.
>>>
>>> Without this flexible mechanism, we cannot (at least later) model things
>>> like DIV4.5 clock which is the only clock which derives from the output
>>> of PLL multiplier before the post divider is applied.
>>>
>>> Since with DT there are are no retakes, we need to get this right the
>>> first time and modifying later will not be an option.
>>>
>>
>> So, the full device tree binding would look something like this:
>>
>> +
>> +    pll0: clock-controller@11000 {
>> +        compatible = "ti,da850-pll0";
>> +        reg = <0x11000 0x1000>;
>> +        clocks = <&ref_clk>, <&pll1_sysclk 3>, <&pll1_obsclk>;
>> +        clock-names = "oscin", pll1_sysclk3", "pll1_osbclk";
>> +        oscin-square-wave;
>> +
>> +        pll0_sysclk: sysclk {
>> +            #clock-cells = <1>;
>> +        };
>> +
>> +        pll0_auxclk: auxclk {
>> +            #clock-cells = <0>;
>> +        };
>> +
>> +        pll0_div45: div4.5 {
>> +            #clock-cells = <0>;
>> +        };
>> +
>> +        pll0_obsclk: obsclk {
>> +            #clock-cells = <0>;
>> +            assigned-clocks = <&pll0_sysclk 1>;
>> +            assigned-clock-names = "ocsrc";
>> +        };
>> +    };
>
> Well, I guess this will work as well. And I am probably biased towards
> the style I mentioned because AM335x and other TI OMAP processors
> follow that.
>
> To make it easy to review that we have all bases covered, can you model
> the all PLLC0 and PLLC1 (input and output) clocks for the next version?

Sure thing.

>
>>
>> There are three clocks coming into the IP block and there are 11 clocks
>> going out (sysclk is 7 clocks). And you can specify the board-specific
>> configuration, like having the "oscin-square-wave" flag when a square wave
>> is used instead of a crystal oscillator and you can assign the multiplexer
>
> Ideally the OSCIN vs CLKIN selection should be another clock mux whose
> output is one of the input clocks to PLL controller. But I can see the
> difficulty in handling that as the mux itself is controlled by the PLL
> controller.
>
>> input that will be used by obsclk. (And, this binding is totally compatible
>> with the binding I have already proposed - although, I see now it would
>> be better to go ahead and add the clocks-names property.)
>
> Also, please add the oscin-square-wave to the binding definition too.
>
> For the benefit of others reviewing and not familiar with the hardware,
> the users guide for DA850 is here:
> http://www.ti.com/lit/ug/spruh77c/spruh77c.pdf
>
> and the PLL block diagram is on page 143 (Figure 8-1).
>
> Thanks,
> Sekhar
>

2018-01-11 12:45:16

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]> wrote:
> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>
>>
>> I am available tomorrow to build and test patches against the
>> da850-evm. I just need to know which version(s) to test.
>
>
> Great. As per the cover letter:
>
> You can find a working branch with everything included in the
> "common-clk-v5"
> branch of https://github.com/dlech/ev3dev-kernel.git.

I wasn't sure if things had changed after some of the dialog about the
bindings and device tree.

Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
(Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
CST 2018
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
CPU: VIVT data cache, VIVT instruction cache
OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
Memory policy: Data cache writethrough
cma: Reserved 16 MiB at 0xc2c00000
DaVinci da850/omap-l138 variant 0x0
random: fast init done
Built 1 zonelists, mobility grouping on. Total pages: 16256
Kernel command line: console=ttyS2,115200n8 root=PARTUUID= rw
rootfstype=ext4 rootwait
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 42164K/65536K available (4548K kernel code, 280K rwdata, 1044K
rodata, 232K init, 143K bss, 6988K reserved, 16384K cma-reserved)
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
vmalloc : 0xc4800000 - 0xff800000 ( 944 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0x(ptrval) - 0x(ptrval) (4550 kB)
.init : 0x(ptrval) - 0x(ptrval) ( 232 kB)
.data : 0x(ptrval) - 0x(ptrval) ( 281 kB)
.bss : 0x(ptrval) - 0x(ptrval) ( 144 kB)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Preemptible hierarchical RCU implementation.
Tasks RCU enabled.
NR_IRQS: 245
clocksource: timer0_1: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 79635851949 ns
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every
89478484971ns
Console: colour dummy device 80x30
Calibrating delay loop... 148.88 BogoMIPS (lpj=744448)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0xc0008400 - 0xc0008458
Hierarchical SRCU implementation.
devtmpfs: initialized
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: -1, 3072 bytes)
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor menu
mux: initialized RTC_ALARM
mux: Setting register RTC_ALARM
mux: PINMUX0 (0x00000000) = 0x44080000 -> 0x24080000
edma 1c00000.edma: memcpy is disabled
edma 1c00000.edma: TI EDMA DMA engine driver
edma 1e30000.edma: memcpy is disabled
edma 1e30000.edma: TI EDMA DMA engine driver
i2c_davinci 1c22000.i2c: could not find pctldev for node
/soc@1c00000/pinmux@14120/pinmux_i2c0_pins, deferring probe
clocksource: Switched to clocksource timer0_1
NET: Registered protocol family 2
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Initialise system trusted keyrings
workingset: timestamp_bits=30 max_order=14 bucket_order=0
Key type asymmetric registered
Asymmetric key parser 'x509' registered
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
io scheduler noop registered (default)
io scheduler mq-deadline registered
io scheduler kyber registered
pinctrl-single 1c14120.pinmux: 160 pins at pa fdfe34a6 size 80
Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
1c42000.serial: ttyS0 at MMIO 0x1c42000 (irq = 25, base_baud =
9375000) is a TI DA8xx/66AK2x
1d0c000.serial: ttyS1 at MMIO 0x1d0c000 (irq = 53, base_baud =
8250000) is a TI DA8xx/66AK2x
1d0d000.serial: ttyS2 at MMIO 0x1d0d000 (irq = 61, base_baud =
8250000) is a TI DA8xx/66AK2x
console [ttyS2] enabled
brd: module loaded
libphy: Fixed MDIO Bus: probed
davinci_mdio 1e24000.mdio: failed to get device clock
davinci_mdio: probe of 1e24000.mdio failed with error -2
i2c /dev entries driver
davinci_mmc 1c40000.mmc: Using DMA, 4-bit mode
NET: Registered protocol family 10
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
Loading compiled-in X.509 certificates
mmc0: host does not support reading read-only switch, assuming
write-enable
mmc0: new high speed SDHC card at address b368
mmcblk0: mmc0:b368 00000 3.75 GiB
mmcblk0: p1 p2
pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
pca953x 0-0020: failed reading register
pca953x: probe of 0-0020 failed with error -121
console [netcon0] enabled
netconsole: network logging started
davinci_emac 1e20000.ethernet: incompatible machine/device type for
reading mac address
hctosys: unable to open rtc device (rtc0)

>

2018-01-11 15:49:25

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Thursday 11 January 2018 06:15 PM, Adam Ford wrote:
> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]> wrote:
>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>
>>>
>>> I am available tomorrow to build and test patches against the
>>> da850-evm. I just need to know which version(s) to test.
>>
>>
>> Great. As per the cover letter:
>>
>> You can find a working branch with everything included in the
>> "common-clk-v5"
>> branch of https://github.com/dlech/ev3dev-kernel.git.
>
> I wasn't sure if things had changed after some of the dialog about the
> bindings and device tree.
>
> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>
> Starting kernel ...
>
> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0x0
> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
> CST 2018
> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
> CPU: VIVT data cache, VIVT instruction cache
> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
> Memory policy: Data cache writethrough
> cma: Reserved 16 MiB at 0xc2c00000
> DaVinci da850/omap-l138 variant 0x0
> random: fast init done
> Built 1 zonelists, mobility grouping on. Total pages: 16256
> Kernel command line: console=ttyS2,115200n8 root=PARTUUID= rw

Pretty sure an actual UUID is missing here.

Thanks,
Sekhar

2018-01-11 16:14:23

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Thu, Jan 11, 2018 at 9:47 AM, Sekhar Nori <[email protected]> wrote:
> On Thursday 11 January 2018 06:15 PM, Adam Ford wrote:
>> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]> wrote:
>>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>>
>>>>
>>>> I am available tomorrow to build and test patches against the
>>>> da850-evm. I just need to know which version(s) to test.
>>>
>>>
>>> Great. As per the cover letter:
>>>
>>> You can find a working branch with everything included in the
>>> "common-clk-v5"
>>> branch of https://github.com/dlech/ev3dev-kernel.git.
>>
>> I wasn't sure if things had changed after some of the dialog about the
>> bindings and device tree.
>>
>> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>>
>> Starting kernel ...
>>
>> Uncompressing Linux... done, booting the kernel.
>> Booting Linux on physical CPU 0x0
>> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
>> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
>> CST 2018
>> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
>> CPU: VIVT data cache, VIVT instruction cache
>> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
>> Memory policy: Data cache writethrough
>> cma: Reserved 16 MiB at 0xc2c00000
>> DaVinci da850/omap-l138 variant 0x0
>> random: fast init done
>> Built 1 zonelists, mobility grouping on. Total pages: 16256
>> Kernel command line: console=ttyS2,115200n8 root=PARTUUID= rw
>
> Pretty sure an actual UUID is missing here.
>

When I setup root to be on the /dev/mmcblk0, I get the same result.
The kernel still hangs. It doesn't hang using the mainline kernel
without this patch series

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
(Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
CST 2018
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
CPU: VIVT data cache, VIVT instruction cache
OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
Memory policy: Data cache writethrough
cma: Reserved 16 MiB at 0xc2c00000
DaVinci da850/omap-l138 variant 0x0
random: fast init done
Built 1 zonelists, mobility grouping on. Total pages: 16256
Kernel command line: console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw
rootfstype=ext4 rootwait
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 42164K/65536K available (4548K kernel code, 280K rwdata, 1044K
rodata, 232K init, 143K bss, 6988K reserved, 16384K cma-reserved)
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
vmalloc : 0xc4800000 - 0xff800000 ( 944 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0x(ptrval) - 0x(ptrval) (4550 kB)
.init : 0x(ptrval) - 0x(ptrval) ( 232 kB)
.data : 0x(ptrval) - 0x(ptrval) ( 281 kB)
.bss : 0x(ptrval) - 0x(ptrval) ( 144 kB)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Preemptible hierarchical RCU implementation.
Tasks RCU enabled.
NR_IRQS: 245
clocksource: timer0_1: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 79635851949 ns
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
Console: colour dummy device 80x30
Calibrating delay loop... 148.88 BogoMIPS (lpj=744448)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0xc0008400 - 0xc0008458
Hierarchical SRCU implementation.
devtmpfs: initialized
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: -1, 3072 bytes)
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor menu
mux: initialized RTC_ALARM
mux: Setting register RTC_ALARM
mux: PINMUX0 (0x00000000) = 0x44080000 -> 0x24080000
edma 1c00000.edma: memcpy is disabled
edma 1c00000.edma: TI EDMA DMA engine driver
edma 1e30000.edma: memcpy is disabled
edma 1e30000.edma: TI EDMA DMA engine driver
i2c_davinci 1c22000.i2c: could not find pctldev for node
/soc@1c00000/pinmux@14120/pinmux_i2c0_pins, deferring probe
clocksource: Switched to clocksource timer0_1
NET: Registered protocol family 2
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Initialise system trusted keyrings
workingset: timestamp_bits=30 max_order=14 bucket_order=0
Key type asymmetric registered
Asymmetric key parser 'x509' registered
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
io scheduler noop registered (default)
io scheduler mq-deadline registered
io scheduler kyber registered
pinctrl-single 1c14120.pinmux: 160 pins at pa fdfe34a6 size 80
Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
1c42000.serial: ttyS0 at MMIO 0x1c42000 (irq = 25, base_baud =
9375000) is a TI DA8xx/66AK2x
1d0c000.serial: ttyS1 at MMIO 0x1d0c000 (irq = 53, base_baud =
8250000) is a TI DA8xx/66AK2x
1d0d000.serial: ttyS2 at MMIO 0x1d0d000 (irq = 61, base_baud =
8250000) is a TI DA8xx/66AK2x
console [ttyS2] enabled
brd: module loaded
libphy: Fixed MDIO Bus: probed
davinci_mdio 1e24000.mdio: failed to get device clock
davinci_mdio: probe of 1e24000.mdio failed with error -2
i2c /dev entries driver
davinci_mmc 1c40000.mmc: Using DMA, 4-bit mode
NET: Registered protocol family 10
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
Loading compiled-in X.509 certificates
mmc0: host does not support reading read-only switch, assuming write-enable
mmc0: new high speed SDHC card at address b368
mmcblk0: mmc0:b368 00000 3.75 GiB
mmcblk0: p1 p2
pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
pca953x 0-0020: failed reading register
pca953x: probe of 0-0020 failed with error -121
console [netcon0] enabled
netconsole: network logging started
davinci_emac 1e20000.ethernet: incompatible machine/device type for
reading mac address
hctosys: unable to open rtc device (rtc0)



> Thanks,
> Sekhar

2018-01-11 17:22:37

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/11/2018 06:45 AM, Adam Ford wrote:
> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]> wrote:
>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>
>>>
>>> I am available tomorrow to build and test patches against the
>>> da850-evm. I just need to know which version(s) to test.
>>
>>
>> Great. As per the cover letter:
>>
>> You can find a working branch with everything included in the
>> "common-clk-v5"
>> branch of https://github.com/dlech/ev3dev-kernel.git.
>
> I wasn't sure if things had changed after some of the dialog about the
> bindings and device tree.

Not yet. ;-)

>
> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>
> Starting kernel ...
>
> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0x0
> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
> CST 2018
> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
> CPU: VIVT data cache, VIVT instruction cache
> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM

OK, using device tree...

> Memory policy: Data cache writethrough
> cma: Reserved 16 MiB at 0xc2c00000
> DaVinci da850/omap-l138 variant 0x0
> random: fast init done
> Built 1 zonelists, mobility grouping on. Total pages: 16256
> Kernel command line: console=ttyS2,115200n8 root=PARTUUID= rw
> rootfstype=ext4 rootwait
> Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
> Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
> Memory: 42164K/65536K available (4548K kernel code, 280K rwdata, 1044K
> rodata, 232K init, 143K bss, 6988K reserved, 16384K cma-reserved)
> Virtual kernel memory layout:
> vector : 0xffff0000 - 0xffff1000 ( 4 kB)
> fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
> vmalloc : 0xc4800000 - 0xff800000 ( 944 MB)
> lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
> modules : 0xbf000000 - 0xc0000000 ( 16 MB)
> .text : 0x(ptrval) - 0x(ptrval) (4550 kB)
> .init : 0x(ptrval) - 0x(ptrval) ( 232 kB)
> .data : 0x(ptrval) - 0x(ptrval) ( 281 kB)
> .bss : 0x(ptrval) - 0x(ptrval) ( 144 kB)
> SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> Preemptible hierarchical RCU implementation.
> Tasks RCU enabled.
> NR_IRQS: 245
> clocksource: timer0_1: mask: 0xffffffff max_cycles: 0xffffffff,
> max_idle_ns: 79635851949 ns
> sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every
> 89478484971ns
> Console: colour dummy device 80x30
> Calibrating delay loop... 148.88 BogoMIPS (lpj=744448)
> pid_max: default: 32768 minimum: 301
> Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
> Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
> CPU: Testing write buffer coherency: ok
> Setting up static identity map for 0xc0008400 - 0xc0008458
> Hierarchical SRCU implementation.
> devtmpfs: initialized
> clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
> max_idle_ns: 19112604462750000 ns
> futex hash table entries: 256 (order: -1, 3072 bytes)
> pinctrl core: initialized pinctrl subsystem
> NET: Registered protocol family 16
> DMA: preallocated 256 KiB pool for atomic coherent allocations
> cpuidle: using governor menu
> mux: initialized RTC_ALARM
> mux: Setting register RTC_ALARM
> mux: PINMUX0 (0x00000000) = 0x44080000 -> 0x24080000
> edma 1c00000.edma: memcpy is disabled
> edma 1c00000.edma: TI EDMA DMA engine driver
> edma 1e30000.edma: memcpy is disabled
> edma 1e30000.edma: TI EDMA DMA engine driver
> i2c_davinci 1c22000.i2c: could not find pctldev for node
> /soc@1c00000/pinmux@14120/pinmux_i2c0_pins, deferring probe
> clocksource: Switched to clocksource timer0_1
> NET: Registered protocol family 2
> TCP established hash table entries: 1024 (order: 0, 4096 bytes)
> TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
> TCP: Hash tables configured (established 1024 bind 1024)
> UDP hash table entries: 256 (order: 0, 4096 bytes)
> UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
> NET: Registered protocol family 1
> RPC: Registered named UNIX socket transport module.
> RPC: Registered udp transport module.
> RPC: Registered tcp transport module.
> RPC: Registered tcp NFSv4.1 backchannel transport module.
> Initialise system trusted keyrings
> workingset: timestamp_bits=30 max_order=14 bucket_order=0
> Key type asymmetric registered
> Asymmetric key parser 'x509' registered
> Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
> io scheduler noop registered (default)
> io scheduler mq-deadline registered
> io scheduler kyber registered
> pinctrl-single 1c14120.pinmux: 160 pins at pa fdfe34a6 size 80
> Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
> 1c42000.serial: ttyS0 at MMIO 0x1c42000 (irq = 25, base_baud =
> 9375000) is a TI DA8xx/66AK2x
> 1d0c000.serial: ttyS1 at MMIO 0x1d0c000 (irq = 53, base_baud =
> 8250000) is a TI DA8xx/66AK2x
> 1d0d000.serial: ttyS2 at MMIO 0x1d0d000 (irq = 61, base_baud =
> 8250000) is a TI DA8xx/66AK2x
> console [ttyS2] enabled

If you are getting to this point, you probably don't need DEBUG_LL.
It looks like "earlyprint" is not being passed to the command line
anyway, so CONFIG_EARLY_PRINTK is not actually doing anything.

> brd: module loaded
> libphy: Fixed MDIO Bus: probed
> davinci_mdio 1e24000.mdio: failed to get device clock
> davinci_mdio: probe of 1e24000.mdio failed with error -2

It looks like this needs a clock-names property in the device tree.
Please make this change and try again:

diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 08a9817..fd3e316 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -713,6 +713,7 @@
#size-cells = <0>;
reg = <0x224000 0x1000>;
clocks = <&psc1 5>;
+ clock-names = "fck";
status = "disabled";
};
eth0: ethernet@220000 {


> i2c /dev entries driver
> davinci_mmc 1c40000.mmc: Using DMA, 4-bit mode
> NET: Registered protocol family 10
> Segment Routing with IPv6
> sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> NET: Registered protocol family 17
> Loading compiled-in X.509 certificates
> mmc0: host does not support reading read-only switch, assuming
> write-enable
> mmc0: new high speed SDHC card at address b368
> mmcblk0: mmc0:b368 00000 3.75 GiB
> mmcblk0: p1 p2
> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
> pca953x 0-0020: failed reading register
> pca953x: probe of 0-0020 failed with error -121

I'm not sure why there is an error here. I'm using I2C0 on my board,
so I am fairly confident that it is not a problem introduced by this
series.

> console [netcon0] enabled
> netconsole: network logging started
> davinci_emac 1e20000.ethernet: incompatible machine/device type for
> reading mac address
> hctosys: unable to open rtc device (rtc0)
>

What is normally the next line after this in a working boot?

Also please try passing "clk_ignore_unused" to the kernel command line.

2018-01-11 18:09:47

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Thu, Jan 11, 2018 at 11:22 AM, David Lechner <[email protected]> wrote:
> On 01/11/2018 06:45 AM, Adam Ford wrote:
>>
>> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]>
>> wrote:
>>>
>>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>>
>>>>
>>>>
>>>> I am available tomorrow to build and test patches against the
>>>> da850-evm. I just need to know which version(s) to test.
>>>
>>>
>>>
>>> Great. As per the cover letter:
>>>
>>> You can find a working branch with everything included in the
>>> "common-clk-v5"
>>> branch of https://github.com/dlech/ev3dev-kernel.git.
>>
>>
>> I wasn't sure if things had changed after some of the dialog about the
>> bindings and device tree.
>
>
> Not yet. ;-)
>
>>
>> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>>
>> Starting kernel ...
>>
>> Uncompressing Linux... done, booting the kernel.
>> Booting Linux on physical CPU 0x0
>> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
>> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
>> CST 2018
>> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
>> CPU: VIVT data cache, VIVT instruction cache
>> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
>
>
> OK, using device tree...

Sorry, I thought I was supposed to. I retested using the board file,
but it also resulted in a hang.

>
>
[snip]
>
>
> If you are getting to this point, you probably don't need DEBUG_LL.
> It looks like "earlyprint" is not being passed to the command line
> anyway, so CONFIG_EARLY_PRINTK is not actually doing anything.
>
>> brd: module loaded
>> libphy: Fixed MDIO Bus: probed
>> davinci_mdio 1e24000.mdio: failed to get device clock
>> davinci_mdio: probe of 1e24000.mdio failed with error -2
>
>
> It looks like this needs a clock-names property in the device tree.
> Please make this change and try again:
>
> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
> index 08a9817..fd3e316 100644
> --- a/arch/arm/boot/dts/da850.dtsi
> +++ b/arch/arm/boot/dts/da850.dtsi
> @@ -713,6 +713,7 @@
> #size-cells = <0>;
> reg = <0x224000 0x1000>;
> clocks = <&psc1 5>;
> + clock-names = "fck";
> status = "disabled";
> };
> eth0: ethernet@220000 {
>
>
[snip]

I added your copy-names entry to my device tree and we get a login prompt. :-)

> I'm not sure why there is an error here. I'm using I2C0 on my board,
> so I am fairly confident that it is not a problem introduced by this
> series.
>
>> console [netcon0] enabled
>> netconsole: network logging started
>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>> reading mac address
>> hctosys: unable to open rtc device (rtc0)
>>
>
> What is normally the next line after this in a working boot?
>
> Also please try passing "clk_ignore_unused" to the kernel command line.

Here is the log. There seems to be some garbled characters that don't
seem to appear. I'm going to double check those against the stock
kernel.


Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
(Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
CST 2018
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
CPU: VIVT data cache, VIVT instruction cache
OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
debug: ignoring loglevel setting.
bootconsole [earlycon0] enabled
Memory policy: Data cache writethrough
cma: Reserved 16 MiB at 0xc2c00000
DaVinci da850/omap-l138 variant 0x0
On node 0 totalpages: 16384
DMA zone: 128 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 16384 pages, LIFO batch:3
random: fast init done
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists, mobility grouping on. Total pages: 16256
Kernel command line: console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw
rootfstype=ext4 rootwait ignore_loglevel earlyprintk clk_ignore_unused
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 42164K/65536K available (4548K kernel code, 280K rwdata, 1044K
rodata, 232K init, 143K bss, 6988K reserved, 16384K cma-reserved)
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
vmalloc : 0xc4800000 - 0xff800000 ( 944 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0x(ptrval) - 0x(ptrval) (4550 kB)
.init : 0x(ptrval) - 0x(ptrval) ( 232 kB)
.data : 0x(ptrval) -&�p`� rval) Qm^�`} b � $\���� �! �
"V � ���@ B- d�����}bf ʒf� i�console [ttyS2] enabled
console [ttyS2] enabled��F 0x(ptrval) ( 144 kB)
bootconsole [earlycon0] disabledObjects=0, CP&�p^�-�Mdes=1
bootconsole [earlycon0] disabledb ʒf� i�a �F $\����
brd: module loaded��} ��B
libphy: Fixed MDIO Bus: probed &�p^�-�I
davinci_mdio 1e24000.mdio: davinci mdio revision 1.5, bus freq 2200000
a- R� /^���� ���v@a��.���� ^\�`&�`l��f ����͍Mֈ�� �E ����э�)�)! �}�y
ya bK����� ֈ��
davinci_mdio 1e24000.mdio: detected phy mask
fffffffe ��I ")=M��-�)!iD����mi-��I �k��
���)� r��.��э�i2� �v� �k$^��э�-�-!mD��q} ] �K���� 6m�R�`� q)�M ���^��
��
libphy: 1e24000.mdio:
probed&��߉��a I�j�`�a�I���} 2/�p� bv VK,�q� 6M�- � ֈ�� �I ��f��a�I҈��}
2 A-!�a-� �K����!aMq- ")=I��-�-!mD��} 2 A-!�a-� �K -� &-=M��-�-!mD�
davinci_mdio 1e24000.mdio: phy[0]: device 1e24000.mdio:00, driver SMSC
LAN8710/LAN8720ݕ�� I�Sm��aM�-! &��P-4RhR�
Ε�-� �K�^t@�
i2c /dev entries driver
davinci_mmc 1c40000.mmc: Using DMA, 4-bit mode
NET: Registered protocol family 10
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
Loading compiled-in X.509 certificates
mmc0: host does not support reading read-only switch, assuming write-enable
mmc0: new high speed SDHC card at address b368
mmcblk0: mmc0:b368 00000 3.75 GiB
mmcblk0: p1 p2
pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
pca953x 0-0020: failed reading register
pca953x: probe of 0-0020 failed with error -121
console [netcon0] enabled
netconsole: network logging started
davinci_emac 1e20000.ethernet: incompatible machine/device type for
reading mac address
hctosys: unable to open rtc device (rtc0)
clk: Not disabling unused clocks
vbat: disabling
EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) on device 179:2.
devtmpfs: mounted
Freeing unused kernel memory: 232K
This architecture does not have kernel memory protection.
EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
Starting logging: OK
Initializing random number generator... done.
Starting network: OK

Welcome to Buildroot
buildroot login:


>

However, I get a reboot failure:

umount: devtmpfs busy - remounted read-only
EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system reboot

reboot: Restarting system
Reboot failed -- System halted

I'll run more tests on a stock kernel to look at the reboot failure
and the uart noise.

adam

2018-01-11 18:29:33

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/11/2018 12:09 PM, Adam Ford wrote:
> On Thu, Jan 11, 2018 at 11:22 AM, David Lechner <[email protected]> wrote:
>> On 01/11/2018 06:45 AM, Adam Ford wrote:
>>>
>>> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]>
>>> wrote:
>>>>
>>>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>>>
>>>>>
>>>>>
>>>>> I am available tomorrow to build and test patches against the
>>>>> da850-evm. I just need to know which version(s) to test.
>>>>
>>>>
>>>>
>>>> Great. As per the cover letter:
>>>>
>>>> You can find a working branch with everything included in the
>>>> "common-clk-v5"
>>>> branch of https://github.com/dlech/ev3dev-kernel.git.
>>>
>>>
>>> I wasn't sure if things had changed after some of the dialog about the
>>> bindings and device tree.
>>
>>
>> Not yet. ;-)
>>
>>>
>>> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>>>
>>> Starting kernel ...
>>>
>>> Uncompressing Linux... done, booting the kernel.
>>> Booting Linux on physical CPU 0x0
>>> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
>>> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
>>> CST 2018
>>> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
>>> CPU: VIVT data cache, VIVT instruction cache
>>> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
>>
>>
>> OK, using device tree...
>
> Sorry, I thought I was supposed to. I retested using the board file,
> but it also resulted in a hang.

This was just intended as a note to self. But we do need to test both.
Let's stick with the device tree boot first.

>
>>
>>
> [snip]
>>
>>
>> If you are getting to this point, you probably don't need DEBUG_LL.
>> It looks like "earlyprint" is not being passed to the command line
>> anyway, so CONFIG_EARLY_PRINTK is not actually doing anything.
>>
>>> brd: module loaded
>>> libphy: Fixed MDIO Bus: probed
>>> davinci_mdio 1e24000.mdio: failed to get device clock
>>> davinci_mdio: probe of 1e24000.mdio failed with error -2
>>
>>
>> It looks like this needs a clock-names property in the device tree.
>> Please make this change and try again:
>>
>> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
>> index 08a9817..fd3e316 100644
>> --- a/arch/arm/boot/dts/da850.dtsi
>> +++ b/arch/arm/boot/dts/da850.dtsi
>> @@ -713,6 +713,7 @@
>> #size-cells = <0>;
>> reg = <0x224000 0x1000>;
>> clocks = <&psc1 5>;
>> + clock-names = "fck";
>> status = "disabled";
>> };
>> eth0: ethernet@220000 {
>>
>>
> [snip]
>
> I added your copy-names entry to my device tree and we get a login prompt. :-)

OK, great! It sounds like device tree is working after this change. I guess
we can move on to non-device-tree.

>
>> I'm not sure why there is an error here. I'm using I2C0 on my board,
>> so I am fairly confident that it is not a problem introduced by this
>> series.
>>
>>> console [netcon0] enabled
>>> netconsole: network logging started
>>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>>> reading mac address
>>> hctosys: unable to open rtc device (rtc0)
>>>
>>
>> What is normally the next line after this in a working boot?
>>
>> Also please try passing "clk_ignore_unused" to the kernel command line.
>
> Here is the log. There seems to be some garbled characters that don't
> seem to appear. I'm going to double check those against the stock
> kernel.
>
>
> Starting kernel ...
>
> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0x0
> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
> CST 2018
> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
> CPU: VIVT data cache, VIVT instruction cache
> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
> debug: ignoring loglevel setting.
> bootconsole [earlycon0] enabled
> Memory policy: Data cache writethrough
> cma: Reserved 16 MiB at 0xc2c00000
> DaVinci da850/omap-l138 variant 0x0
> On node 0 totalpages: 16384
> DMA zone: 128 pages used for memmap
> DMA zone: 0 pages reserved
> DMA zone: 16384 pages, LIFO batch:3
> random: fast init done
> pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
> pcpu-alloc: [0] 0
> Built 1 zonelists, mobility grouping on. Total pages: 16256
> Kernel command line: console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw
> rootfstype=ext4 rootwait ignore_loglevel earlyprintk clk_ignore_unused
> Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
> Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
> Memory: 42164K/65536K available (4548K kernel code, 280K rwdata, 1044K
> rodata, 232K init, 143K bss, 6988K reserved, 16384K cma-reserved)
> Virtual kernel memory layout:
> vector : 0xffff0000 - 0xffff1000 ( 4 kB)
> fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
> vmalloc : 0xc4800000 - 0xff800000 ( 944 MB)
> lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
> modules : 0xbf000000 - 0xc0000000 ( 16 MB)
> .text : 0x(ptrval) - 0x(ptrval) (4550 kB)
> .init : 0x(ptrval) - 0x(ptrval) ( 232 kB)
> .data : 0x(ptrval) -&�p`� rval) Qm^�`} b � $\���� �! �
> "V � ���@ B- d�����}bf ʒf� i�console [ttyS2] enabled
> console [ttyS2] enabled��F 0x(ptrval) ( 144 kB)
> bootconsole [earlycon0] disabledObjects=0, CP&�p^�-�Mdes=1
> bootconsole [earlycon0] disabledb ʒf� i�a �F $\����
> brd: module loaded��} ��B
> libphy: Fixed MDIO Bus: probed &�p^�-�I
> davinci_mdio 1e24000.mdio: davinci mdio revision 1.5, bus freq 2200000
> a- R� /^���� ���v@a��.���� ^\�`&�`l��f ����͍Mֈ�� �E ����э�)�)! �}�y
> ya bK����� ֈ��
> davinci_mdio 1e24000.mdio: detected phy mask
> fffffffe ��I ")=M��-�)!iD����mi-��I �k��
> ���)� r��.��э�i2� �v� �k$^��э�-�-!mD��q} ] �K���� 6m�R�`� q)�M ���^��
> ��
> libphy: 1e24000.mdio:
> probed&��߉��a I�j�`�a�I���} 2/�p� bv VK,�q� 6M�- � ֈ�� �I ��f��a�I҈��}
> 2 A-!�a-� �K����!aMq- ")=I��-�-!mD��} 2 A-!�a-� �K -� &-=M��-�-!mD�
> davinci_mdio 1e24000.mdio: phy[0]: device 1e24000.mdio:00, driver SMSC
> LAN8710/LAN8720ݕ�� I�Sm��aM�-! &��P-4RhR�
> Ε�-� �K�^t@�
> i2c /dev entries driver
> davinci_mmc 1c40000.mmc: Using DMA, 4-bit mode
> NET: Registered protocol family 10
> Segment Routing with IPv6
> sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> NET: Registered protocol family 17
> Loading compiled-in X.509 certificates
> mmc0: host does not support reading read-only switch, assuming write-enable
> mmc0: new high speed SDHC card at address b368
> mmcblk0: mmc0:b368 00000 3.75 GiB
> mmcblk0: p1 p2
> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
> pca953x 0-0020: failed reading register
> pca953x: probe of 0-0020 failed with error -121
> console [netcon0] enabled
> netconsole: network logging started
> davinci_emac 1e20000.ethernet: incompatible machine/device type for
> reading mac address
> hctosys: unable to open rtc device (rtc0)
> clk: Not disabling unused clocks

If removing the "clk_ignore_unused" option causes the board to not boot,
then we still have problems that need to be fixed, so please also test
without this option.

> vbat: disabling
> EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
> VFS: Mounted root (ext4 filesystem) on device 179:2.
> devtmpfs: mounted
> Freeing unused kernel memory: 232K
> This architecture does not have kernel memory protection.
> EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
> Starting logging: OK
> Initializing random number generator... done.
> Starting network: OK
>
> Welcome to Buildroot
> buildroot login:
>
>
>>
>
> However, I get a reboot failure:
>
> umount: devtmpfs busy - remounted read-only
> EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
> The system is going down NOW!
> Sent SIGTERM to all processes
> Sent SIGKILL to all processes
> Requesting system reboot
>
> reboot: Restarting system
> Reboot failed -- System halted
>
> I'll run more tests on a stock kernel to look at the reboot failure
> and the uart noise.
>
> adam
>

The reboot failure probably has to do with the watchdog patches that
are dependencies of this series.


Also, see the cover letter about how to avoid garbled output. Either
disable low level debugging or disable switching the parent of the
async3 clock.

2018-01-11 18:50:46

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Thu, Jan 11, 2018 at 12:29 PM, David Lechner <[email protected]> wrote:
> On 01/11/2018 12:09 PM, Adam Ford wrote:
>>
>> On Thu, Jan 11, 2018 at 11:22 AM, David Lechner <[email protected]>
>> wrote:
>>>
>>> On 01/11/2018 06:45 AM, Adam Ford wrote:
>>>>
>>>>
>>>> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I am available tomorrow to build and test patches against the
>>>>>> da850-evm. I just need to know which version(s) to test.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Great. As per the cover letter:
>>>>>
>>>>> You can find a working branch with everything included in the
>>>>> "common-clk-v5"
>>>>> branch of https://github.com/dlech/ev3dev-kernel.git.
>>>>
>>>>
>>>>
>>>> I wasn't sure if things had changed after some of the dialog about the
>>>> bindings and device tree.
>>>
>>>
>>>
>>> Not yet. ;-)
>>>
>>>>
>>>> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>>>>
>>>> Starting kernel ...
>>>>
>>>> Uncompressing Linux... done, booting the kernel.
>>>> Booting Linux on physical CPU 0x0
>>>> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
>>>> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
>>>> CST 2018
>>>> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
>>>> CPU: VIVT data cache, VIVT instruction cache
>>>> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
>>>
>>>
>>>
>>> OK, using device tree...
>>
>>
>> Sorry, I thought I was supposed to. I retested using the board file,
>> but it also resulted in a hang.
>
>
> This was just intended as a note to self. But we do need to test both.
> Let's stick with the device tree boot first.
>
>>
>>>
>>>
>> [snip]
>>>
>>>
>>>
>>> If you are getting to this point, you probably don't need DEBUG_LL.
>>> It looks like "earlyprint" is not being passed to the command line
>>> anyway, so CONFIG_EARLY_PRINTK is not actually doing anything.
>>>
>>>> brd: module loaded
>>>> libphy: Fixed MDIO Bus: probed
>>>> davinci_mdio 1e24000.mdio: failed to get device clock
>>>> davinci_mdio: probe of 1e24000.mdio failed with error -2
>>>
>>>
>>>
>>> It looks like this needs a clock-names property in the device tree.
>>> Please make this change and try again:
>>>
>>> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
>>> index 08a9817..fd3e316 100644
>>> --- a/arch/arm/boot/dts/da850.dtsi
>>> +++ b/arch/arm/boot/dts/da850.dtsi
>>> @@ -713,6 +713,7 @@
>>> #size-cells = <0>;
>>> reg = <0x224000 0x1000>;
>>> clocks = <&psc1 5>;
>>> + clock-names = "fck";
>>> status = "disabled";
>>> };
>>> eth0: ethernet@220000 {
>>>
>>>
>> [snip]
>>
>> I added your copy-names entry to my device tree and we get a login prompt.
>> :-)
>
>
> OK, great! It sounds like device tree is working after this change. I guess
> we can move on to non-device-tree.
>
>
>>
>>> I'm not sure why there is an error here. I'm using I2C0 on my board,
>>> so I am fairly confident that it is not a problem introduced by this
>>> series.
>>>
>>>> console [netcon0] enabled
>>>> netconsole: network logging started
>>>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>>>> reading mac address
>>>> hctosys: unable to open rtc device (rtc0)
>>>>
>>>
>>> What is normally the next line after this in a working boot?
>>>
>>> Also please try passing "clk_ignore_unused" to the kernel command line.
>>
>>
>> Here is the log. There seems to be some garbled characters that don't
>> seem to appear. I'm going to double check those against the stock
>> kernel.
>>
>>

[snip]

>
>
> If removing the "clk_ignore_unused" option causes the board to not boot,
> then we still have problems that need to be fixed, so please also test
> without this option.

Without this option, it still does not boot. Without device tree it
hangs after:

[snip]

NET: Registered protocol family 17
Loading compiled-in X.509 certificates
console [netcon0] enabled
netconsole: network logging started
davinci_emac davinci_emac.1: using random MAC addr: 5e:38:1a:1f:4f:77
mmc0: host does not support reading read-only switch, assuming write-enable
hctosys: unable to open rtc device (rtc0)
mmc0: new high speed SDHC card at address b368


With device tree it hangs after:

[snip]
mmc0: host does not support reading read-only switch, assuming write-enable
mmc0: new high speed SDHC card at address b368
mmcblk0: mmc0:b368 00000 3.75 GiB
mmcblk0: p1 p2
pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
pca953x 0-0020: failed reading register
pca953x: probe of 0-0020 failed with error -121
console [netcon0] enabled
netconsole: network logging started
davinci_emac 1e20000.ethernet: incompatible machine/device type for
reading mac address
hctosys: unable to open rtc device (rtc0)


>
>> vbat: disabling
>> EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts:
>> (null)
>> VFS: Mounted root (ext4 filesystem) on device 179:2.
>> devtmpfs: mounted
>> Freeing unused kernel memory: 232K
>> This architecture does not have kernel memory protection.
>> EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
>> Starting logging: OK
>> Initializing random number generator... done.
>> Starting network: OK
>>
>> Welcome to Buildroot
>> buildroot login:
>>
>>
>>>
>>
>> However, I get a reboot failure:
>>
>> umount: devtmpfs busy - remounted read-only
>> EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
>> The system is going down NOW!
>> Sent SIGTERM to all processes
>> Sent SIGKILL to all processes
>> Requesting system reboot
>>
>> reboot: Restarting system
>> Reboot failed -- System halted
>>
>> I'll run more tests on a stock kernel to look at the reboot failure
>> and the uart noise.
>>
>> adam
>>
>
> The reboot failure probably has to do with the watchdog patches that
> are dependencies of this series.
>
>
> Also, see the cover letter about how to avoid garbled output. Either
> disable low level debugging or disable switching the parent of the
> async3 clock.

Disabling the low-level debugging eliminated the garbage.

If/when you have more to me to test, feel free to e-mail me. I am
available today and tomorrow to test.
>

2018-01-11 20:04:47

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/11/2018 12:50 PM, Adam Ford wrote:
> On Thu, Jan 11, 2018 at 12:29 PM, David Lechner <[email protected]> wrote:
>> If removing the "clk_ignore_unused" option causes the board to not boot,
>> then we still have problems that need to be fixed, so please also test
>> without this option.
>
> Without this option, it still does not boot. Without device tree it
> hangs after:
>
> [snip]
>
> NET: Registered protocol family 17
> Loading compiled-in X.509 certificates
> console [netcon0] enabled
> netconsole: network logging started
> davinci_emac davinci_emac.1: using random MAC addr: 5e:38:1a:1f:4f:77
> mmc0: host does not support reading read-only switch, assuming write-enable
> hctosys: unable to open rtc device (rtc0)
> mmc0: new high speed SDHC card at address b368
>
>
> With device tree it hangs after:
>
> [snip]
> mmc0: host does not support reading read-only switch, assuming write-enable
> mmc0: new high speed SDHC card at address b368
> mmcblk0: mmc0:b368 00000 3.75 GiB
> mmcblk0: p1 p2
> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
> pca953x 0-0020: failed reading register
> pca953x: probe of 0-0020 failed with error -121
> console [netcon0] enabled
> netconsole: network logging started
> davinci_emac 1e20000.ethernet: incompatible machine/device type for
> reading mac address
> hctosys: unable to open rtc device (rtc0)
>
>

Please try this change:

diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
index 3fd6b49..a526cc2 100644
--- a/drivers/clk/davinci/psc-da850.c
+++ b/drivers/clk/davinci/psc-da850.c
@@ -17,7 +17,7 @@ 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(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
LPSC(4, 0, spi0, pll0_sysclk2, 0),
LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),



If that does not work, try adding LPSC_ALWAYS_ENABLED to all of the clocks
in this file and then eliminate them one by one until you find which one is
preventing boot.

If it still does not boot, there is a similar DIVCLK_ALWAYS_ENABLED flag in
drivers/clk/davinci/pll-da850.c that you can repeat the exercise with. Add
DIVCLK_ALWAYS_ENABLED to all of the clocks there and then eliminate it one
by one until you find the clock that is causing the problem.

2018-01-11 20:58:21

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Thu, Jan 11, 2018 at 2:04 PM, David Lechner <[email protected]> wrote:
> On 01/11/2018 12:50 PM, Adam Ford wrote:
>>
>> On Thu, Jan 11, 2018 at 12:29 PM, David Lechner <[email protected]>
>> wrote:
>>>
>>> If removing the "clk_ignore_unused" option causes the board to not boot,
>>> then we still have problems that need to be fixed, so please also test
>>> without this option.
>>
>>
>> Without this option, it still does not boot. Without device tree it
>> hangs after:
>>
>> [snip]
>>
>> NET: Registered protocol family 17
>> Loading compiled-in X.509 certificates
>> console [netcon0] enabled
>> netconsole: network logging started
>> davinci_emac davinci_emac.1: using random MAC addr: 5e:38:1a:1f:4f:77
>> mmc0: host does not support reading read-only switch, assuming
>> write-enable
>> hctosys: unable to open rtc device (rtc0)
>> mmc0: new high speed SDHC card at address b368
>>
>>
>> With device tree it hangs after:
>>
>> [snip]
>> mmc0: host does not support reading read-only switch, assuming
>> write-enable
>> mmc0: new high speed SDHC card at address b368
>> mmcblk0: mmc0:b368 00000 3.75 GiB
>> mmcblk0: p1 p2
>> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
>> pca953x 0-0020: failed reading register
>> pca953x: probe of 0-0020 failed with error -121
>> console [netcon0] enabled
>> netconsole: network logging started
>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>> reading mac address
>> hctosys: unable to open rtc device (rtc0)
>>
>>
>
> Please try this change:
>
> diff --git a/drivers/clk/davinci/psc-da850.c
> b/drivers/clk/davinci/psc-da850.c
> index 3fd6b49..a526cc2 100644
> --- a/drivers/clk/davinci/psc-da850.c
> +++ b/drivers/clk/davinci/psc-da850.c
> @@ -17,7 +17,7 @@ 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(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
> LPSC(4, 0, spi0, pll0_sysclk2, 0),
> LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
> LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>
>
>
> If that does not work, try adding LPSC_ALWAYS_ENABLED to all of the clocks
> in this file and then eliminate them one by one until you find which one is
> preventing boot.
>
Unfortunately, that didn't work. I switch all the entries in both
tables that had a 0 to LPSC_ALWAYS_ENABLED, but no luck booting.

> If it still does not boot, there is a similar DIVCLK_ALWAYS_ENABLED flag in
> drivers/clk/davinci/pll-da850.c that you can repeat the exercise with. Add
> DIVCLK_ALWAYS_ENABLED to all of the clocks there and then eliminate it one
> by one until you find the clock that is causing the problem.

Still no good news. I switched all the entries with a 0 to
DIVCLK_ALWAYS_ENABLED and it still didn't finish booting.

I wonder if Sekhar Nori might have some suggestions. I didn't look at
the code or try to understand it. I just changed the settings.
>

adam

2018-01-11 21:04:32

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/11/2018 02:58 PM, Adam Ford wrote:
> On Thu, Jan 11, 2018 at 2:04 PM, David Lechner <[email protected]> wrote:
>> On 01/11/2018 12:50 PM, Adam Ford wrote:
>>>
>>> On Thu, Jan 11, 2018 at 12:29 PM, David Lechner <[email protected]>
>>> wrote:
>>>>
>>>> If removing the "clk_ignore_unused" option causes the board to not boot,
>>>> then we still have problems that need to be fixed, so please also test
>>>> without this option.
>>>
>>>
>>> Without this option, it still does not boot. Without device tree it
>>> hangs after:
>>>
>>> [snip]
>>>
>>> NET: Registered protocol family 17
>>> Loading compiled-in X.509 certificates
>>> console [netcon0] enabled
>>> netconsole: network logging started
>>> davinci_emac davinci_emac.1: using random MAC addr: 5e:38:1a:1f:4f:77
>>> mmc0: host does not support reading read-only switch, assuming
>>> write-enable
>>> hctosys: unable to open rtc device (rtc0)
>>> mmc0: new high speed SDHC card at address b368
>>>
>>>
>>> With device tree it hangs after:
>>>
>>> [snip]
>>> mmc0: host does not support reading read-only switch, assuming
>>> write-enable
>>> mmc0: new high speed SDHC card at address b368
>>> mmcblk0: mmc0:b368 00000 3.75 GiB
>>> mmcblk0: p1 p2
>>> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
>>> pca953x 0-0020: failed reading register
>>> pca953x: probe of 0-0020 failed with error -121
>>> console [netcon0] enabled
>>> netconsole: network logging started
>>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>>> reading mac address
>>> hctosys: unable to open rtc device (rtc0)
>>>
>>>
>>
>> Please try this change:
>>
>> diff --git a/drivers/clk/davinci/psc-da850.c
>> b/drivers/clk/davinci/psc-da850.c
>> index 3fd6b49..a526cc2 100644
>> --- a/drivers/clk/davinci/psc-da850.c
>> +++ b/drivers/clk/davinci/psc-da850.c
>> @@ -17,7 +17,7 @@ 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(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
>> LPSC(4, 0, spi0, pll0_sysclk2, 0),
>> LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
>> LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>
>>
>>
>> If that does not work, try adding LPSC_ALWAYS_ENABLED to all of the clocks
>> in this file and then eliminate them one by one until you find which one is
>> preventing boot.
>>
> Unfortunately, that didn't work. I switch all the entries in both
> tables that had a 0 to LPSC_ALWAYS_ENABLED, but no luck booting.
>
>> If it still does not boot, there is a similar DIVCLK_ALWAYS_ENABLED flag in
>> drivers/clk/davinci/pll-da850.c that you can repeat the exercise with. Add
>> DIVCLK_ALWAYS_ENABLED to all of the clocks there and then eliminate it one
>> by one until you find the clock that is causing the problem.
>
> Still no good news. I switched all the entries with a 0 to
> DIVCLK_ALWAYS_ENABLED and it still didn't finish booting.
>
> I wonder if Sekhar Nori might have some suggestions. I didn't look at
> the code or try to understand it. I just changed the settings.
>>

Even if a clock had another flag besides zero, you will need to add
LPSC_ALWAYS_ENABLED by or-ing it with the other flag.

diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
index 3fd6b49..3375df6a1 100644
--- a/drivers/clk/davinci/psc-da850.c
+++ b/drivers/clk/davinci/psc-da850.c
@@ -17,38 +17,38 @@ 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(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
+ LPSC(4, 0, spi0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(5, 0, mmcsd0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
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(9, 0, uart0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(13, 0, pruss, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
LPSC(14, 0, arm, pll0_sysclk6, LPSC_ALWAYS_ENABLED),
- LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET),
+ LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET | LPSC_ALWAYS_ENABLED),
{ }
};

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(1, 0, usb0, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(2, 0, usb1, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
+ LPSC(3, 0, gpio, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
+ LPSC(5, 0, emac, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
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(7, 0, mcasp0, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(8, 0, sata, pll0_sysclk2, LPSC_FORCE | LPSC_ALWAYS_ENABLED),
+ LPSC(9, 0, vpif, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(10, 0, spi1, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(11, 0, i2c1, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
+ LPSC(12, 0, uart1, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(13, 0, uart2, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(14, 0, mcbsp0, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(15, 0, mcbsp1, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(16, 0, lcdc, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(17, 0, ehrpwm, async3, LPSC_ALWAYS_ENABLED),
+ LPSC(18, 0, mmcsd1, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
+ LPSC(20, 0, ecap, async3, LPSC_ALWAYS_ENABLED),
LPSC(21, 0, tptc2, pll0_sysclk2, LPSC_ALWAYS_ENABLED),
{ }
};


diff --git a/drivers/clk/davinci/pll-da850.c b/drivers/clk/davinci/pll-da850.c
index 77a7223..f334e69 100644
--- a/drivers/clk/davinci/pll-da850.c
+++ b/drivers/clk/davinci/pll-da850.c
@@ -22,21 +22,21 @@

static const struct davinci_pll_divclk_info
da850_pll0_divclk_info[] __initconst = {
- DIVCLK(1, pll0_sysclk1, pll0, DIVCLK_FIXED_DIV),
- DIVCLK(2, pll0_sysclk2, pll0, DIVCLK_FIXED_DIV),
- DIVCLK(3, pll0_sysclk3, pll0, 0),
- DIVCLK(4, pll0_sysclk4, pll0, DIVCLK_FIXED_DIV),
- DIVCLK(5, pll0_sysclk5, pll0, 0),
- DIVCLK(6, pll0_sysclk6, pll0, DIVCLK_ARM_RATE | DIVCLK_FIXED_DIV),
- DIVCLK(7, pll0_sysclk7, pll0, 0),
+ DIVCLK(1, pll0_sysclk1, pll0, DIVCLK_FIXED_DIV | DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(2, pll0_sysclk2, pll0, DIVCLK_FIXED_DIV | DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(3, pll0_sysclk3, pll0, DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(4, pll0_sysclk4, pll0, DIVCLK_FIXED_DIV | DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(5, pll0_sysclk5, pll0, DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(6, pll0_sysclk6, pll0, DIVCLK_ARM_RATE | DIVCLK_FIXED_DIV| DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(7, pll0_sysclk7, pll0, DIVCLK_ALWAYS_ENABLED),
{ }
};

static const struct davinci_pll_divclk_info
da850_pll1_divclk_info[] __initconst = {
DIVCLK(1, pll1_sysclk1, pll1, DIVCLK_ALWAYS_ENABLED),
- DIVCLK(2, pll1_sysclk2, pll1, 0),
- DIVCLK(3, pll1_sysclk3, pll1, 0),
+ DIVCLK(2, pll1_sysclk2, pll1, DIVCLK_ALWAYS_ENABLED),
+ DIVCLK(3, pll1_sysclk3, pll1, DIVCLK_ALWAYS_ENABLED),
{ }
};


2018-01-11 21:22:51

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v5 09/44] dt-bindings: clock: New bindings for TI Davinci PSC

On Sun, Jan 07, 2018 at 08:17:08PM -0600, David Lechner wrote:
> This adds a new binding for the Power Sleep Controller (PSC) for the
> mach-davinci family of processors.
>
> Note: Although TI Keystone has a very similar PSC, we are not using the
> existing bindings. Keystone is using a legacy one-node-per-clock binding
> (actually two nodes if you count the separate reset binding for the same
> IP block). Also, some davinci LPSCs have quirks that aren't handled by
> the keystone bindings, so we would be adding one compatible string per
> clock with quirks instead of just a new compatible string for each
> controller.
>
> Signed-off-by: David Lechner <[email protected]>
> ---
> .../devicetree/bindings/clock/ti/davinci/psc.txt | 47 ++++++++++++++++++++++
> 1 file changed, 47 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/psc.txt

Reviewed-by: Rob Herring <[email protected]>

2018-01-11 21:34:17

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Thu, Jan 11, 2018 at 3:04 PM, David Lechner <[email protected]> wrote:
> On 01/11/2018 02:58 PM, Adam Ford wrote:
>>
>> On Thu, Jan 11, 2018 at 2:04 PM, David Lechner <[email protected]>
>> wrote:
>>>
>>> On 01/11/2018 12:50 PM, Adam Ford wrote:
>>>>
>>>>
>>>> On Thu, Jan 11, 2018 at 12:29 PM, David Lechner <[email protected]>
>>>> wrote:
>>>>>
>>>>>
>>>>> If removing the "clk_ignore_unused" option causes the board to not
>>>>> boot,
>>>>> then we still have problems that need to be fixed, so please also test
>>>>> without this option.
>>>>
>>>>
>>>>
>>>> Without this option, it still does not boot. Without device tree it
>>>> hangs after:
>>>>
>>>> [snip]
>>>>
>>>> NET: Registered protocol family 17
>>>> Loading compiled-in X.509 certificates
>>>> console [netcon0] enabled
>>>> netconsole: network logging started
>>>> davinci_emac davinci_emac.1: using random MAC addr: 5e:38:1a:1f:4f:77
>>>> mmc0: host does not support reading read-only switch, assuming
>>>> write-enable
>>>> hctosys: unable to open rtc device (rtc0)
>>>> mmc0: new high speed SDHC card at address b368
>>>>
>>>>
>>>> With device tree it hangs after:
>>>>
>>>> [snip]
>>>> mmc0: host does not support reading read-only switch, assuming
>>>> write-enable
>>>> mmc0: new high speed SDHC card at address b368
>>>> mmcblk0: mmc0:b368 00000 3.75 GiB
>>>> mmcblk0: p1 p2
>>>> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
>>>> pca953x 0-0020: failed reading register
>>>> pca953x: probe of 0-0020 failed with error -121
>>>> console [netcon0] enabled
>>>> netconsole: network logging started
>>>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>>>> reading mac address
>>>> hctosys: unable to open rtc device (rtc0)
>>>>
>>>>
>>>
>>> Please try this change:
>>>
>>> diff --git a/drivers/clk/davinci/psc-da850.c
>>> b/drivers/clk/davinci/psc-da850.c
>>> index 3fd6b49..a526cc2 100644
>>> --- a/drivers/clk/davinci/psc-da850.c
>>> +++ b/drivers/clk/davinci/psc-da850.c
>>> @@ -17,7 +17,7 @@ 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(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
>>> LPSC(4, 0, spi0, pll0_sysclk2, 0),
>>> LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
>>> LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>>
>>>
>>>
>>> If that does not work, try adding LPSC_ALWAYS_ENABLED to all of the
>>> clocks
>>> in this file and then eliminate them one by one until you find which one
>>> is
>>> preventing boot.
>>>
>> Unfortunately, that didn't work. I switch all the entries in both
>> tables that had a 0 to LPSC_ALWAYS_ENABLED, but no luck booting.
>>
>>> If it still does not boot, there is a similar DIVCLK_ALWAYS_ENABLED flag
>>> in
>>> drivers/clk/davinci/pll-da850.c that you can repeat the exercise with.
>>> Add
>>> DIVCLK_ALWAYS_ENABLED to all of the clocks there and then eliminate it
>>> one
>>> by one until you find the clock that is causing the problem.
>>
>>
>> Still no good news. I switched all the entries with a 0 to
>> DIVCLK_ALWAYS_ENABLED and it still didn't finish booting.
>>
>> I wonder if Sekhar Nori might have some suggestions. I didn't look at
>> the code or try to understand it. I just changed the settings.
>>>
>>>
>
> Even if a clock had another flag besides zero, you will need to add
> LPSC_ALWAYS_ENABLED by or-ing it with the other flag.
>

[snip]


Thanks for clarifying. I was able to make it work with the following patch:

diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
index 3b4583d..a76b8682 100644
--- a/drivers/clk/davinci/psc-da850.c
+++ b/drivers/clk/davinci/psc-da850.c
@@ -25,7 +25,7 @@ static const struct davinci_psc_clk_info
da850_psc0_info[] __initconst = {
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),
+ LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET |
LPSC_ALWAYS_ENABLED),
{ }
};


If you have an updated patch series with those two fixes, I add my
name to the tested-by list.


>
>
[snip]
>

2018-01-11 21:45:21

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v5 17/44] dt-bindings: clock: Add bindings for DA8XX CFGCHIP gate clocks

On Sun, Jan 07, 2018 at 08:17:16PM -0600, David Lechner wrote:
> This adds a new binding for the gate clocks present in the CFGCHIP syscon
> registers in TI DA8XX SoCs. There are actually other gate clocks in this
> block that could be added in the future, but TBCLK is currently the only
> one being used.

Like how many? 2 more?, then fine. 20 more, then perhaps cfgchip should
be the clock provider.

In any case, I'd prefer to see all the cfgchip clocks documented in one
doc.

>
> Signed-off-by: David Lechner <[email protected]>
> ---
> .../clock/ti/davinci/da8xx-cfgchip-gate.txt | 38 ++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt
> new file mode 100644
> index 0000000..55821b0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip-gate.txt
> @@ -0,0 +1,38 @@
> +Binding for TI DA8XX/OMAP-L13X/AM17XX/AM18XX CFGCHIP gate clocks
> +
> +TI DA8XX/OMAP-L13X/AM17XX/AM18XX SoCs contain a general purpose set of
> +registers call CFGCHIPn. Some of these registers function as clock
> +gates. This document describes the bindings for those clocks.
> +
> +Required properties:
> +- compatible: shall be "ti,da830-tbclk".
> +- #clock-cells: from common clock binding; shall be set to 0.
> +- clocks: phandle to the parent clock
> +
> +Optional properties:
> +- clock-output-names: from common clock binding.
> +
> +Parent:
> +This node must be a child of a "ti,da830-cfgchip" node.
> +
> +Assignment:
> +The assigned-clocks and assigned-clock-parents from the common clock bindings
> +can be used to indicate which parent clock should be used.
> +
> +Examples:
> +
> + cfgchip: syscon@1417c {
> + compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
> + reg = <0x1417c 0x14>;
> +
> + ehrpwm_tbclk: tbclk {
> + compatible = "ti,da830-tbclk";
> + #clock-cells = <0>;
> + clocks = <&psc1 17>;
> + clock-output-names = "ehrpwm_tbclk";
> + };
> + };
> +
> +Also see:
> +- Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> --
> 2.7.4
>

2018-01-11 21:46:23

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/11/2018 03:34 PM, Adam Ford wrote:
> On Thu, Jan 11, 2018 at 3:04 PM, David Lechner <[email protected]> wrote:
>> On 01/11/2018 02:58 PM, Adam Ford wrote:
>>>
>>> On Thu, Jan 11, 2018 at 2:04 PM, David Lechner <[email protected]>
>>> wrote:
>>>>
>>>> On 01/11/2018 12:50 PM, Adam Ford wrote:
>>>>>
>>>>>
>>>>> On Thu, Jan 11, 2018 at 12:29 PM, David Lechner <[email protected]>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> If removing the "clk_ignore_unused" option causes the board to not
>>>>>> boot,
>>>>>> then we still have problems that need to be fixed, so please also test
>>>>>> without this option.
>>>>>
>>>>>
>>>>>
>>>>> Without this option, it still does not boot. Without device tree it
>>>>> hangs after:
>>>>>
>>>>> [snip]
>>>>>
>>>>> NET: Registered protocol family 17
>>>>> Loading compiled-in X.509 certificates
>>>>> console [netcon0] enabled
>>>>> netconsole: network logging started
>>>>> davinci_emac davinci_emac.1: using random MAC addr: 5e:38:1a:1f:4f:77
>>>>> mmc0: host does not support reading read-only switch, assuming
>>>>> write-enable
>>>>> hctosys: unable to open rtc device (rtc0)
>>>>> mmc0: new high speed SDHC card at address b368
>>>>>
>>>>>
>>>>> With device tree it hangs after:
>>>>>
>>>>> [snip]
>>>>> mmc0: host does not support reading read-only switch, assuming
>>>>> write-enable
>>>>> mmc0: new high speed SDHC card at address b368
>>>>> mmcblk0: mmc0:b368 00000 3.75 GiB
>>>>> mmcblk0: p1 p2
>>>>> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
>>>>> pca953x 0-0020: failed reading register
>>>>> pca953x: probe of 0-0020 failed with error -121
>>>>> console [netcon0] enabled
>>>>> netconsole: network logging started
>>>>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>>>>> reading mac address
>>>>> hctosys: unable to open rtc device (rtc0)
>>>>>
>>>>>
>>>>
>>>> Please try this change:
>>>>
>>>> diff --git a/drivers/clk/davinci/psc-da850.c
>>>> b/drivers/clk/davinci/psc-da850.c
>>>> index 3fd6b49..a526cc2 100644
>>>> --- a/drivers/clk/davinci/psc-da850.c
>>>> +++ b/drivers/clk/davinci/psc-da850.c
>>>> @@ -17,7 +17,7 @@ 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(3, 0, aemif, pll0_sysclk3, LPSC_ALWAYS_ENABLED),
>>>> LPSC(4, 0, spi0, pll0_sysclk2, 0),
>>>> LPSC(5, 0, mmcsd0, pll0_sysclk2, 0),
>>>> LPSC(6, 0, aintc, pll0_sysclk4, LPSC_ALWAYS_ENABLED),
>>>>
>>>>
>>>>
>>>> If that does not work, try adding LPSC_ALWAYS_ENABLED to all of the
>>>> clocks
>>>> in this file and then eliminate them one by one until you find which one
>>>> is
>>>> preventing boot.
>>>>
>>> Unfortunately, that didn't work. I switch all the entries in both
>>> tables that had a 0 to LPSC_ALWAYS_ENABLED, but no luck booting.
>>>
>>>> If it still does not boot, there is a similar DIVCLK_ALWAYS_ENABLED flag
>>>> in
>>>> drivers/clk/davinci/pll-da850.c that you can repeat the exercise with.
>>>> Add
>>>> DIVCLK_ALWAYS_ENABLED to all of the clocks there and then eliminate it
>>>> one
>>>> by one until you find the clock that is causing the problem.
>>>
>>>
>>> Still no good news. I switched all the entries with a 0 to
>>> DIVCLK_ALWAYS_ENABLED and it still didn't finish booting.
>>>
>>> I wonder if Sekhar Nori might have some suggestions. I didn't look at
>>> the code or try to understand it. I just changed the settings.
>>>>
>>>>
>>
>> Even if a clock had another flag besides zero, you will need to add
>> LPSC_ALWAYS_ENABLED by or-ing it with the other flag.
>>
>
> [snip]
>
>
> Thanks for clarifying. I was able to make it work with the following patch:
>
> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
> index 3b4583d..a76b8682 100644
> --- a/drivers/clk/davinci/psc-da850.c
> +++ b/drivers/clk/davinci/psc-da850.c
> @@ -25,7 +25,7 @@ static const struct davinci_psc_clk_info
> da850_psc0_info[] __initconst = {
> 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),
> + LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET |
> LPSC_ALWAYS_ENABLED),
> { }
> };
>
>
> If you have an updated patch series with those two fixes, I add my
> name to the tested-by list.
>
>
>>
>>
> [snip]
>>

Great! Thanks again for testing.

Sekhar, have you had a chance to look at the rest of the patches in the
series?

I'll wait a bit before I send a v6 to see if any other comments come.

2018-01-11 21:51:49

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 17/44] dt-bindings: clock: Add bindings for DA8XX CFGCHIP gate clocks

On 01/11/2018 03:45 PM, Rob Herring wrote:
> On Sun, Jan 07, 2018 at 08:17:16PM -0600, David Lechner wrote:
>> This adds a new binding for the gate clocks present in the CFGCHIP syscon
>> registers in TI DA8XX SoCs. There are actually other gate clocks in this
>> block that could be added in the future, but TBCLK is currently the only
>> one being used.
>
> Like how many? 2 more?, then fine. 20 more, then perhaps cfgchip should
> be the clock provider.

Like, one more. Same goes for the mux clock. The USB PHY clocks are also
part of the CFGCHIP.

All of these clocks are randomly spread out, so I didn't really see a logical
way to make a single clock provider with #clock-cells = <1>.

>
> In any case, I'd prefer to see all the cfgchip clocks documented in one
> doc.

I will do that.

2018-01-11 23:20:42

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/11/2018 12:09 PM, Adam Ford wrote:
> On Thu, Jan 11, 2018 at 11:22 AM, David Lechner <[email protected]> wrote:
>> On 01/11/2018 06:45 AM, Adam Ford wrote:
>>>
>>> On Wed, Jan 10, 2018 at 8:50 PM, David Lechner <[email protected]>
>>> wrote:
>>>>
>>>> On 01/10/2018 04:24 PM, Adam Ford wrote:
>>>>>
>>>>>
>>>>>
>>>>> I am available tomorrow to build and test patches against the
>>>>> da850-evm. I just need to know which version(s) to test.
>>>>
>>>>
>>>>
>>>> Great. As per the cover letter:
>>>>
>>>> You can find a working branch with everything included in the
>>>> "common-clk-v5"
>>>> branch of https://github.com/dlech/ev3dev-kernel.git.
>>>
>>>
>>> I wasn't sure if things had changed after some of the dialog about the
>>> bindings and device tree.
>>
>>
>> Not yet. ;-)
>>
>>>
>>> Here is my log with DEBUG_LL and CONFIG_EARLY_PRINTK set :
>>>
>>> Starting kernel ...
>>>
>>> Uncompressing Linux... done, booting the kernel.
>>> Booting Linux on physical CPU 0x0
>>> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
>>> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
>>> CST 2018
>>> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
>>> CPU: VIVT data cache, VIVT instruction cache
>>> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
>>
>>
>> OK, using device tree...
>
> Sorry, I thought I was supposed to. I retested using the board file,
> but it also resulted in a hang.
>
>>
>>
> [snip]
>>
>>
>> If you are getting to this point, you probably don't need DEBUG_LL.
>> It looks like "earlyprint" is not being passed to the command line
>> anyway, so CONFIG_EARLY_PRINTK is not actually doing anything.
>>
>>> brd: module loaded
>>> libphy: Fixed MDIO Bus: probed
>>> davinci_mdio 1e24000.mdio: failed to get device clock
>>> davinci_mdio: probe of 1e24000.mdio failed with error -2
>>
>>
>> It looks like this needs a clock-names property in the device tree.
>> Please make this change and try again:
>>
>> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
>> index 08a9817..fd3e316 100644
>> --- a/arch/arm/boot/dts/da850.dtsi
>> +++ b/arch/arm/boot/dts/da850.dtsi
>> @@ -713,6 +713,7 @@
>> #size-cells = <0>;
>> reg = <0x224000 0x1000>;
>> clocks = <&psc1 5>;
>> + clock-names = "fck";
>> status = "disabled";
>> };
>> eth0: ethernet@220000 {
>>
>>
> [snip]
>
> I added your copy-names entry to my device tree and we get a login prompt. :-)
>
>> I'm not sure why there is an error here. I'm using I2C0 on my board,
>> so I am fairly confident that it is not a problem introduced by this
>> series.
>>
>>> console [netcon0] enabled
>>> netconsole: network logging started
>>> davinci_emac 1e20000.ethernet: incompatible machine/device type for
>>> reading mac address
>>> hctosys: unable to open rtc device (rtc0)
>>>
>>
>> What is normally the next line after this in a working boot?
>>
>> Also please try passing "clk_ignore_unused" to the kernel command line.
>
> Here is the log. There seems to be some garbled characters that don't
> seem to appear. I'm going to double check those against the stock
> kernel.
>
>
> Starting kernel ...
>
> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0x0
> Linux version 4.15.0-rc4-g8564e0f (aford@ubuntu16) (gcc version 7.2.0
> (Buildroot 2017.11.1-00021-g7b43660)) #2 PREEMPT Thu Jan 11 06:35:29
> CST 2018
> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
> CPU: VIVT data cache, VIVT instruction cache
> OF: fdt: Machine model: DA850/AM1808/OMAP-L138 EVM
> debug: ignoring loglevel setting.
> bootconsole [earlycon0] enabled
> Memory policy: Data cache writethrough
> cma: Reserved 16 MiB at 0xc2c00000
> DaVinci da850/omap-l138 variant 0x0
> On node 0 totalpages: 16384
> DMA zone: 128 pages used for memmap
> DMA zone: 0 pages reserved
> DMA zone: 16384 pages, LIFO batch:3
> random: fast init done
> pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
> pcpu-alloc: [0] 0
> Built 1 zonelists, mobility grouping on. Total pages: 16256
> Kernel command line: console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw
> rootfstype=ext4 rootwait ignore_loglevel earlyprintk clk_ignore_unused
> Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
> Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
> Memory: 42164K/65536K available (4548K kernel code, 280K rwdata, 1044K
> rodata, 232K init, 143K bss, 6988K reserved, 16384K cma-reserved)
> Virtual kernel memory layout:
> vector : 0xffff0000 - 0xffff1000 ( 4 kB)
> fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
> vmalloc : 0xc4800000 - 0xff800000 ( 944 MB)
> lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
> modules : 0xbf000000 - 0xc0000000 ( 16 MB)
> .text : 0x(ptrval) - 0x(ptrval) (4550 kB)
> .init : 0x(ptrval) - 0x(ptrval) ( 232 kB)
> .data : 0x(ptrval) -&�p`� rval) Qm^�`} b � $\���� �! �
> "V � ���@ B- d�����}bf ʒf� i�console [ttyS2] enabled
> console [ttyS2] enabled��F 0x(ptrval) ( 144 kB)
> bootconsole [earlycon0] disabledObjects=0, CP&�p^�-�Mdes=1
> bootconsole [earlycon0] disabledb ʒf� i�a �F $\����
> brd: module loaded��} ��B
> libphy: Fixed MDIO Bus: probed &�p^�-�I
> davinci_mdio 1e24000.mdio: davinci mdio revision 1.5, bus freq 2200000
> a- R� /^���� ���v@a��.���� ^\�`&�`l��f ����͍Mֈ�� �E ����э�)�)! �}�y
> ya bK����� ֈ��
> davinci_mdio 1e24000.mdio: detected phy mask
> fffffffe ��I ")=M��-�)!iD����mi-��I �k��
> ���)� r��.��э�i2� �v� �k$^��э�-�-!mD��q} ] �K���� 6m�R�`� q)�M ���^��
> ��
> libphy: 1e24000.mdio:
> probed&��߉��a I�j�`�a�I���} 2/�p� bv VK,�q� 6M�- � ֈ�� �I ��f��a�I҈��}
> 2 A-!�a-� �K����!aMq- ")=I��-�-!mD��} 2 A-!�a-� �K -� &-=M��-�-!mD�
> davinci_mdio 1e24000.mdio: phy[0]: device 1e24000.mdio:00, driver SMSC
> LAN8710/LAN8720ݕ�� I�Sm��aM�-! &��P-4RhR�
> Ε�-� �K�^t@�
> i2c /dev entries driver
> davinci_mmc 1c40000.mmc: Using DMA, 4-bit mode
> NET: Registered protocol family 10
> Segment Routing with IPv6
> sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> NET: Registered protocol family 17
> Loading compiled-in X.509 certificates
> mmc0: host does not support reading read-only switch, assuming write-enable
> mmc0: new high speed SDHC card at address b368
> mmcblk0: mmc0:b368 00000 3.75 GiB
> mmcblk0: p1 p2
> pca953x 0-0020: 0-0020 supply vcc not found, using dummy regulator
> pca953x 0-0020: failed reading register
> pca953x: probe of 0-0020 failed with error -121
> console [netcon0] enabled
> netconsole: network logging started
> davinci_emac 1e20000.ethernet: incompatible machine/device type for
> reading mac address
> hctosys: unable to open rtc device (rtc0)
> clk: Not disabling unused clocks
> vbat: disabling
> EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
> VFS: Mounted root (ext4 filesystem) on device 179:2.
> devtmpfs: mounted
> Freeing unused kernel memory: 232K
> This architecture does not have kernel memory protection.
> EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
> Starting logging: OK
> Initializing random number generator... done.
> Starting network: OK
>
> Welcome to Buildroot
> buildroot login:
>
>
>>
>
> However, I get a reboot failure:
>
> umount: devtmpfs busy - remounted read-only
> EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
> The system is going down NOW!
> Sent SIGTERM to all processes
> Sent SIGKILL to all processes
> Requesting system reboot
>
> reboot: Restarting system
> Reboot failed -- System halted
>

Adam,

Did this reboot issue get resolved?

2018-01-12 06:04:58

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Friday 12 January 2018 03:16 AM, David Lechner wrote:
>
> Sekhar, have you had a chance to look at the rest of the patches in the
> series?

Not yet. Sorry about the slow (and piecemeal) review.

>
> I'll wait a bit before I send a v6 to see if any other comments come.

Yes. I will let you know once I am done reviewing the whole series.

Thanks,
Sekhar

2018-01-12 09:23:11

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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 <[email protected]>
> ---
> 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 <[email protected]>

Please also add:

R: Sekhar Nori <[email protected]>

> +S: Maintained
> +F: Documentation/devicetree/bindings/clock/ti/davinci/
> +F: drivers/clk/davinci/
> +
> TI DAVINCI SERIES GPIO DRIVER
> M: Keerthy <[email protected]>
> L: [email protected]
> 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 <[email protected]>
> + *
> + * Based on drivers/clk/keystone/pll.c
> + * Copyright (C) 2013 Texas Instruments Inc.
> + * Murali Karicheri <[email protected]>
> + * Santosh Shilimkar <[email protected]>
> + *
> + * 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

2018-01-12 09:42:15

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 03/44] clk: davinci: Add platform information for TI DA830 PLL

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 <[email protected]>

Reviewed-by: Sekhar Nori <[email protected]>

Thanks,
Sekhar

2018-01-12 15:25:16

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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 <[email protected]>
>> ---

>> +
>> +#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.


2018-01-12 15:30:41

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

On Fri, Jan 12, 2018 at 9:25 AM, David Lechner <[email protected]> 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 <[email protected]>
>>> ---
>
>
>>> +
>>> +#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.
>
>

2018-01-12 15:48:40

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

On 01/12/2018 09:30 AM, Adam Ford wrote:
> On Fri, Jan 12, 2018 at 9:25 AM, David Lechner <[email protected]> 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.

2018-01-12 16:20:13

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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

2018-01-13 01:11:29

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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
>

2018-01-13 02:13:43

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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.



2018-01-16 06:33:57

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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

2018-01-16 06:49:31

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks

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

2018-01-16 08:38:23

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 04/44] clk: davinci: Add platform information for TI DA850 PLL

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 <[email protected]>

Thanks,
Sekhar

2018-01-16 08:39:19

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 05/44] clk: davinci: Add platform information for TI DM355 PLL

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 <[email protected]>

Reviewed-by: Sekhar Nori <[email protected]>

Thanks,
Sekhar

2018-01-16 08:50:09

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 06/44] clk: davinci: Add platform information for TI DM365 PLL

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 <[email protected]>
> ---
> 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 <[email protected]>
> + */
> +
> +#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 <[email protected]>

Thanks,
Sekhar

2018-01-16 08:57:40

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 07/44] clk: davinci: Add platform information for TI DM644x PLL

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 <[email protected]>

> + * Copyright (C) 2017 David Lechner <[email protected]>

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 <[email protected]>

Thanks,
Sekhar

2018-01-16 09:03:02

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 08/44] clk: davinci: Add platform information for TI DM646x PLL

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 <[email protected]>

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

Reviewed-by: Sekhar Nori <[email protected]>

Thanks,
Sekhar

2018-01-16 11:04:56

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 10/44] clk: davinci: New driver for davinci PSC clocks

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 <[email protected]>
> ---
> 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 <[email protected]>

2018

> + *
> + * Based on: drivers/clk/keystone/gate.c
> + * Copyright (C) 2013 Texas Instruments.
> + * Murali Karicheri <[email protected]>
> + * Santosh Shilimkar <[email protected]>
> + *
> + * 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 <[email protected]>
> + */
> +
> +#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

2018-01-16 11:24:07

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

Hi Adam, David,

On Friday 12 January 2018 03:04 AM, Adam Ford wrote:
> Thanks for clarifying. I was able to make it work with the following patch:
>
> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
> index 3b4583d..a76b8682 100644
> --- a/drivers/clk/davinci/psc-da850.c
> +++ b/drivers/clk/davinci/psc-da850.c
> @@ -25,7 +25,7 @@ static const struct davinci_psc_clk_info
> da850_psc0_info[] __initconst = {
> 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),
> + LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET |
> LPSC_ALWAYS_ENABLED),

Keeping the DSP clock always enabled was not needed earlier AFAICS, so
this needs to be investigated.

Thanks,
Sekhar

2018-01-16 12:21:26

by Adam Ford

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On Tue, Jan 16, 2018 at 5:22 AM, Sekhar Nori <[email protected]> wrote:
> Hi Adam, David,
>
> On Friday 12 January 2018 03:04 AM, Adam Ford wrote:
>> Thanks for clarifying. I was able to make it work with the following patch:
>>
>> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
>> index 3b4583d..a76b8682 100644
>> --- a/drivers/clk/davinci/psc-da850.c
>> +++ b/drivers/clk/davinci/psc-da850.c
>> @@ -25,7 +25,7 @@ static const struct davinci_psc_clk_info
>> da850_psc0_info[] __initconst = {
>> 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),
>> + LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET |
>> LPSC_ALWAYS_ENABLED),
>
> Keeping the DSP clock always enabled was not needed earlier AFAICS, so
> this needs to be investigated.

I was testing the DA850-evm and found it was required or the DA850
wouldn't boot. I don't know enough of why to explain it. I went
through all the clocks as suggested by David, and this one-line patch
fixed the hanging problem I had. Without it the AM1808 board I have
won't boot.

adam
>
> Thanks,
> Sekhar

2018-01-16 13:40:11

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 11/44] clk: davinci: Add platform information for TI DA830 PSC

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 <[email protected]>
> ---
> 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 <[email protected]>
> + */
> +
> +#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

2018-01-16 14:01:40

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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

2018-01-16 14:16:45

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 13/44] clk: davinci: Add platform information for TI DM355 PSC

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 <[email protected]>

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

Thanks,
Sekhar

2018-01-16 14:17:14

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 14/44] clk: davinci: Add platform information for TI DM365 PSC

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 <[email protected]>

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

Thanks,
Sekhar

2018-01-16 16:41:38

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks

On 01/16/2018 06:21 AM, Adam Ford wrote:
> On Tue, Jan 16, 2018 at 5:22 AM, Sekhar Nori <[email protected]> wrote:
>> Hi Adam, David,
>>
>> On Friday 12 January 2018 03:04 AM, Adam Ford wrote:
>>> Thanks for clarifying. I was able to make it work with the following patch:
>>>
>>> diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
>>> index 3b4583d..a76b8682 100644
>>> --- a/drivers/clk/davinci/psc-da850.c
>>> +++ b/drivers/clk/davinci/psc-da850.c
>>> @@ -25,7 +25,7 @@ static const struct davinci_psc_clk_info
>>> da850_psc0_info[] __initconst = {
>>> 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),
>>> + LPSC(15, 1, dsp, pll0_sysclk1, LPSC_FORCE | LPSC_LOCAL_RESET |
>>> LPSC_ALWAYS_ENABLED),
>>
>> Keeping the DSP clock always enabled was not needed earlier AFAICS, so
>> this needs to be investigated.
>
> I was testing the DA850-evm and found it was required or the DA850
> wouldn't boot. I don't know enough of why to explain it. I went
> through all the clocks as suggested by David, and this one-line patch
> fixed the hanging problem I had. Without it the AM1808 board I have
> won't boot.

That's interesting because 1) the AM1808 does not have a DSP and 2) I
am using an AM1808 based system as well that boots without having this
always enabled (AM1808BZWT4 to be exact).

I guess I will leave this change out of the next revision so that we
don't forget that this needs to be addressed. Sekhar found a bug in
the new PSC driver with the LPSC_FORCE bit, so maybe that could be
the difference.

Adam, before the changes in this series, did you have
CONFIG_DAVINCI_RESET_CLOCKS=y in your config?

2018-01-16 16:51:51

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 10/44] clk: davinci: New driver for davinci PSC clocks

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 <[email protected]>
>> ---

>> +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.

2018-01-16 17:16:42

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 11/44] clk: davinci: Add platform information for TI DA830 PSC

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 <[email protected]>
>> ---
>> 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 <[email protected]>
>> + */
>> +
>> +#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.



2018-01-16 17:21:25

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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
>

2018-01-17 11:58:30

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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

2018-01-17 12:19:58

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 11/44] clk: davinci: Add platform information for TI DA830 PSC

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

2018-01-17 12:26:31

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 10/44] clk: davinci: New driver for davinci PSC clocks

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

2018-01-17 13:58:24

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 15/44] clk: davinci: Add platform information for TI DM644x PSC

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 <[email protected]>

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

Thanks,
Sekhar

2018-01-17 15:00:41

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 16/44] clk: davinci: Add platform information for TI DM646x PSC

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

2018-01-17 15:34:08

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 19/44] clk: davinci: New driver for TI DA8XX CFGCHIP clocks

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 <[email protected]>
> ---
> 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 <[email protected]>

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

2018-01-17 17:29:42

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 10/44] clk: davinci: New driver for davinci PSC clocks

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.

2018-01-17 17:33:50

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 11/44] clk: davinci: Add platform information for TI DA830 PSC

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.


2018-01-17 17:34:57

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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.


2018-01-17 17:36:51

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 19/44] clk: davinci: New driver for TI DA8XX CFGCHIP clocks

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 <[email protected]>
>> ---
>> 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 <[email protected]>
>
> 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)



2018-01-17 19:10:00

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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),
{ }
};

2018-01-18 06:38:55

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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

2018-01-18 07:55:23

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 11/44] clk: davinci: Add platform information for TI DA830 PSC

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

2018-01-18 12:13:47

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 20/44] dt-bindings: clock: Add bindings for TI DA8XX USB PHY clocks

On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new binding for TI DA8XX USB PHY clocks. These clocks are part
> of a syscon register called CFGCHIP3.

CFGCHIP2

>
> Signed-off-by: David Lechner <[email protected]>

> +Examples:
> +
> + cfgchip: syscon@1417c {
> + compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
> + reg = <0x1417c 0x14>;
> +
> + usb0_phy_clk: usb0-phy-clock {
> + compatible = "ti,da830-usb0-phy-clock";
> + #clock-cells = <0>;
> + clocks = <&usb_refclkin>, <&pll0_aux_clk>, <&psc1 1>;
> + clock-names = "usb_refclkin", "auxclk", "usb0_lpsc";
> + clock-output-names = "usb0_phy_clk";

Probably call this "usb0_phy" to match with the input name used for
usb1_phy_clk?

> + };
> +
> + usb1_phy_clk: usb1-phy-clock {
> + compatible = "ti,da830-usb1-phy-clock";
> + #clock-cells = <0>;
> + clocks = <&usb0_phy_clk>, <&usb_refclkin>;
> + clock-names = "usb0_phy", "usb_refclkin";
> + clock-output-names = "usb1_phy_clk";
> + };
> + };

Thanks,
Sekhar

2018-01-18 14:59:29

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 21/44] clk: davinci: New driver for TI DA8XX USB PHY clocks

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

2018-01-18 15:18:32

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 29/44] ARM: da8xx: add new USB PHY clock init using common clock framework

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

2018-01-18 15:27:08

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 24/44] ARM: da850: add new clock init using common clock framework

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

2018-01-18 18:44:46

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 29/44] ARM: da8xx: add new USB PHY clock init using common clock framework

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.


2018-01-18 18:50:00

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 21/44] clk: davinci: New driver for TI DA8XX USB PHY clocks

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);

2018-01-18 19:02:27

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 20/44] dt-bindings: clock: Add bindings for TI DA8XX USB PHY clocks

On 01/18/2018 06:10 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds a new binding for TI DA8XX USB PHY clocks. These clocks are part
>> of a syscon register called CFGCHIP3.
>
> CFGCHIP2
>
>>
>> Signed-off-by: David Lechner <[email protected]>
>
>> +Examples:
>> +
>> + cfgchip: syscon@1417c {
>> + compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
>> + reg = <0x1417c 0x14>;
>> +
>> + usb0_phy_clk: usb0-phy-clock {
>> + compatible = "ti,da830-usb0-phy-clock";
>> + #clock-cells = <0>;
>> + clocks = <&usb_refclkin>, <&pll0_aux_clk>, <&psc1 1>;
>> + clock-names = "usb_refclkin", "auxclk", "usb0_lpsc";
>> + clock-output-names = "usb0_phy_clk";
>
> Probably call this "usb0_phy" to match with the input name used for
> usb1_phy_clk?

I was planning on just dropping clock-output-names altogether actually
since they don't really do anything useful.

Also, I was considering sending a series to change the con_id for the
PHY clocks.

My current revision of the device tree bindings is looking like this:

usb_phy: usb-phy {
compatible = "ti,da830-usb-phy";
#phy-cells = <1>;
clocks = <&usb_phy_clk 0>, <&usb_phy_clk 1>;
clock-names = "usb20_phy", "usb11_phy";
status = "disabled";
};
usb_phy_clk: usb-phy-clocks {
compatible = "ti,da830-usb-phy-clocks";
#clock-cells = <1>;
clocks = <&psc1 1>, <&usb_refclkin>, <&pll0_auxclk>;
clock-names = "fck", "usb_refclkin", "auxclk";
};

The clock-names = "usb20_phy", "usb11_phy" comes from the existing con_ids
in the PHY driver's clk_get()s.

However, in device tree, we are usually referring to the USB devices as
usb0 and usb1 instead of usb20 and usb11, respectively. Figure 6-2 "USB
Clocking Diagram" in spruh82c.pdf (AM1808 TRM) calls these clocks "CLK48"
and "CLK48MHz from USB 2.0 PHY", so I was thinking of changing the con_ids
(and therefore also clock-names) to "usb0_clk48" and "usb1_clk48".



2018-01-19 05:08:06

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 21/44] clk: davinci: New driver for TI DA8XX USB PHY clocks

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

2018-01-19 05:10:08

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 29/44] ARM: da8xx: add new USB PHY clock init using common clock framework

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

2018-01-19 06:19:24

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 20/44] dt-bindings: clock: Add bindings for TI DA8XX USB PHY clocks

On Friday 19 January 2018 12:30 AM, David Lechner wrote:
> On 01/18/2018 06:10 AM, Sekhar Nori wrote:
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>> This adds a new binding for TI DA8XX USB PHY clocks. These clocks are
>>> part
>>> of a syscon register called CFGCHIP3.
>>
>> CFGCHIP2
>>
>>>
>>> Signed-off-by: David Lechner <[email protected]>
>>
>>> +Examples:
>>> +
>>> +    cfgchip: syscon@1417c {
>>> +        compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
>>> +        reg = <0x1417c 0x14>;
>>> +
>>> +        usb0_phy_clk: usb0-phy-clock {
>>> +            compatible = "ti,da830-usb0-phy-clock";
>>> +            #clock-cells = <0>;
>>> +            clocks = <&usb_refclkin>, <&pll0_aux_clk>, <&psc1 1>;
>>> +            clock-names = "usb_refclkin", "auxclk", "usb0_lpsc";
>>> +            clock-output-names = "usb0_phy_clk";
>>
>> Probably call this "usb0_phy" to match with the input name used for
>> usb1_phy_clk?
>
> I was planning on just dropping clock-output-names altogether actually
> since they don't really do anything useful.
>
> Also, I was considering sending a series to change the con_id for the
> PHY clocks.
>
> My current revision of the device tree bindings is looking like this:
>
>     usb_phy: usb-phy {
>         compatible = "ti,da830-usb-phy";
>         #phy-cells = <1>;
>         clocks = <&usb_phy_clk 0>, <&usb_phy_clk 1>;
>         clock-names = "usb20_phy", "usb11_phy";
>         status = "disabled";
>     };
>     usb_phy_clk: usb-phy-clocks {
>         compatible = "ti,da830-usb-phy-clocks";
>         #clock-cells = <1>;
>         clocks = <&psc1 1>, <&usb_refclkin>, <&pll0_auxclk>;
>         clock-names = "fck", "usb_refclkin", "auxclk";
>     };
>
> The clock-names = "usb20_phy", "usb11_phy" comes from the existing con_ids
> in the PHY driver's clk_get()s.
>
> However, in device tree, we are usually referring to the USB devices as
> usb0 and usb1 instead of usb20 and usb11, respectively. Figure 6-2 "USB
> Clocking Diagram" in spruh82c.pdf (AM1808 TRM) calls these clocks "CLK48"
> and "CLK48MHz from USB 2.0 PHY", so I was thinking of changing the con_ids
> (and therefore also clock-names) to "usb0_clk48" and "usb1_clk48".

This is fine with me.

Thanks,
Sekhar

2018-02-09 16:24:26

by Bartosz Golaszewski

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
> This adds platform-specific declarations for the PSC clocks on TI DA850/
> OMAP-L138/AM18XX SoCs.
>
> Signed-off-by: David Lechner <[email protected]>
> ---
> 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 <[email protected]>
> + */
> +
> +#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

2018-02-09 16:49:48

by Michael Turquette

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

Hi Bartosz, all,

On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>> This adds platform-specific declarations for the PSC clocks on TI DA850/
>> OMAP-L138/AM18XX SoCs.
>>
>> Signed-off-by: David Lechner <[email protected]>
>> ---
>> 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 <[email protected]>
>> + */
>> +
>> +#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

2018-02-12 03:09:43

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

On 02/09/2018 10:48 AM, Michael Turquette wrote:
> Hi Bartosz, all,
>
> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>>> This adds platform-specific declarations for the PSC clocks on TI DA850/
>>> OMAP-L138/AM18XX SoCs.
>>>
>>> Signed-off-by: David Lechner <[email protected]>
>>> ---
>>> 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 <[email protected]>
>>> + */
>>> +
>>> +#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


2018-04-05 13:12:28

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

Hi Bartosz,

On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:

>> 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


2018-04-05 13:45:40

by Bartosz Golaszewski

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

2018-04-05 15:09 GMT+02:00 Sekhar Nori <[email protected]>:
> Hi Bartosz,
>
> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>
>>> 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

2018-04-05 14:38:48

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

On Thursday 05 April 2018 07:14 PM, Bartosz Golaszewski wrote:
> 2018-04-05 15:09 GMT+02:00 Sekhar Nori <[email protected]>:
>> Hi Bartosz,
>>
>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>>
>>>> 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

2018-04-05 15:40:46

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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 <[email protected]>:
>>> Hi Bartosz,
>>>
>>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>>>
>>>>> 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


2018-04-05 15:52:58

by Bartosz Golaszewski

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

2018-04-05 16:36 GMT+02:00 Sekhar Nori <[email protected]>:
> On Thursday 05 April 2018 07:14 PM, Bartosz Golaszewski wrote:
>> 2018-04-05 15:09 GMT+02:00 Sekhar Nori <[email protected]>:
>>> Hi Bartosz,
>>>
>>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>>>
>>>>> 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

2018-04-06 09:39:47

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

Hi Bart,

On Thursday 05 April 2018 09:21 PM, Bartosz Golaszewski wrote:
> 2018-04-05 16:36 GMT+02:00 Sekhar Nori <[email protected]>:
>> On Thursday 05 April 2018 07:14 PM, Bartosz Golaszewski wrote:
>>> 2018-04-05 15:09 GMT+02:00 Sekhar Nori <[email protected]>:
>>>> Hi Bartosz,
>>>>
>>>> On Friday 09 February 2018 10:18 PM, Michael Turquette wrote:
>>>>> On Fri, Feb 9, 2018 at 8:22 AM, Bartosz Golaszewski <[email protected]> wrote:
>>>>>> 2018-01-08 3:17 GMT+01:00 David Lechner <[email protected]>:
>>>>
>>>>>> 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

The panic issue in your branch is not related to genpd. Its because you
are accessing platform bus before it is initialized. The attached[1]
patch on top of your branch made it boot again.

With your branch booting, I can see genpd related debugfs entries
getting created. I don't see devices being attached to the domains you
have though. I did not debug that. I suspect some matching issue.

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().

Thanks,
Sekhar

---8<---
diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
index 9d9f94eee544..7e3d114efdac 100644
--- a/drivers/clk/davinci/psc.c
+++ b/drivers/clk/davinci/psc.c
@@ -281,12 +281,18 @@ int __davinci_psc_register_clocks(const struct davinci_psc_clk_info *info,
}
}

- DO_ONCE(pm_clk_add_notifier,
- &platform_bus_type, &platform_bus_notifier);
-
return 0;
}

+static int __init davinci_pm_runtime_init(void)
+{
+ pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+
+ return 0;
+}
+core_initcall(davinci_pm_runtime_init);
+
int davinci_psc_register_clocks(const struct davinci_psc_clk_info *info,
void __iomem *base)
{

2018-04-06 16:50:06

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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.

2018-04-23 15:04:11

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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?


2018-04-24 10:45:15

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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

2018-04-24 16:12:39

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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.



2018-04-25 06:10:08

by Sekhar Nori

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

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

2018-04-25 10:11:25

by Bartosz Golaszewski

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

2018-04-25 8:07 GMT+02:00 Sekhar Nori <[email protected]>:
> 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

2018-04-25 10:27:56

by Bartosz Golaszewski

[permalink] [raw]
Subject: Re: [PATCH v5 12/44] clk: davinci: Add platform information for TI DA850 PSC

2018-04-25 12:09 GMT+02:00 Bartosz Golaszewski <[email protected]>:
> 2018-04-25 8:07 GMT+02:00 Sekhar Nori <[email protected]>:
>> 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