Message ID | 1455521698-7905-3-git-send-email-thomas.petazzoni@free-electrons.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Feb 15, 2016 at 08:34:57AM +0100, Thomas Petazzoni wrote: > This commit adds a new driver to handle the core clocks found in the > AP806 HW block, which is the core block of all Armada 7K and 8K > Marvell 64-bits processors. This core clock driver reads the > Sample-At-Reset register to determine the frequencies of several core > clocks: DDR, Ring and CPU clocks. > > Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> > --- > .../clock/mvebu-armada-ap806-core-clock.txt | 33 ++++++ > drivers/clk/mvebu/Kconfig | 3 + > drivers/clk/mvebu/Makefile | 2 +- > drivers/clk/mvebu/ap806-core.c | 112 +++++++++++++++++++++ > 4 files changed, 149 insertions(+), 1 deletion(-) > create mode 100644 Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt > create mode 100644 drivers/clk/mvebu/ap806-core.c > > diff --git a/Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt > new file mode 100644 > index 0000000..b2131bb > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt > @@ -0,0 +1,33 @@ > +* Clock bindings for Marvell MVEBU AP806 Core clocks > + > +The Marvell MVEBU Armada 7K/8K SoCs contain a block called AP806, > +hosting the CPU and other core components of the CPU. This Device Tree > +binding allows to describe the core clocks of the AP806, whose > +frequencies are determined by reading the Sample-At-Reset (SAR) > +register. What else is in the AP806? > + > +Clock consumers must specify the desired clock by having the clock ID > +in its "clocks" phandle cell. > + > +The following is a list of provided IDs and clock names for the core > +Armada AP806 clocks: > + > + 0 = DDR > + 1 = Ring > + 2 = CPU > + > +Required properties: > +- compatible: must be be one of the following: > + "marvell,armada-ap806-core-clock" I'd expect this to be a sub-node of a syscon block or just a single clock provider for the full block. Hard to tell reviewing this without context of what the full clock tree looks like. > +- reg: must be the register address of the Sample-At-Reset (SAR) register > +- #clock-cells: from common clock binding; shall be set to 1 > +- clock-output-names: name of the output clocks > + > +Example: > + > + coreclk: clk@0x6F8204 { Drop 0x and lowercase hex. > + compatible = "marvell,armada-ap806-core-clock"; > + reg = <0x6F8204 0x04>; lowercase hex. > + #clock-cells = <1>; > + clock-output-names = "ddr", "ring", "cpu"; > + };
Dear Rob Herring, On Sun, 21 Feb 2016 20:53:57 -0600, Rob Herring wrote: > > +The Marvell MVEBU Armada 7K/8K SoCs contain a block called AP806, > > +hosting the CPU and other core components of the CPU. This Device Tree > > +binding allows to describe the core clocks of the AP806, whose > > +frequencies are determined by reading the Sample-At-Reset (SAR) > > +register. > > What else is in the AP806? Lots of things: CPU core, caches, GIC, XOR engines, UART, I2C controller, etc. > > +Clock consumers must specify the desired clock by having the clock ID > > +in its "clocks" phandle cell. > > + > > +The following is a list of provided IDs and clock names for the core > > +Armada AP806 clocks: > > + > > + 0 = DDR > > + 1 = Ring > > + 2 = CPU > > + > > +Required properties: > > +- compatible: must be be one of the following: > > + "marvell,armada-ap806-core-clock" > > I'd expect this to be a sub-node of a syscon block or just a single > clock provider for the full block. Hard to tell reviewing this without > context of what the full clock tree looks like. I indeed wondered about adding a syscon block. However, I don't have at this point a full datasheet for the AP806, so it is hard to get a good view of what the register set looks like to create a proper syscon. And I don't have better informations about the full clock tree. Such information will come later, and we can rework the drivers and DT bindings accordingly. Those DT bindings cannot be stable, as the platform is under heavy development and we'll probably discover some issues down the road. Right now, the only information I have about the AP806 clock tree are about those core clocks and ring clocks. > > +- reg: must be the register address of the Sample-At-Reset (SAR) register > > +- #clock-cells: from common clock binding; shall be set to 1 > > +- clock-output-names: name of the output clocks > > + > > +Example: > > + > > + coreclk: clk@0x6F8204 { > > Drop 0x and lowercase hex. > > > + compatible = "marvell,armada-ap806-core-clock"; > > + reg = <0x6F8204 0x04>; > > lowercase hex. Sure, will fix. Best regards, Thomas
> Such information will come later, and we can rework the drivers and DT > bindings accordingly. Those DT bindings cannot be stable, as the > platform is under heavy development and we'll probably discover some > issues down the road. Hi Thomas Maybe add a big fat warning that the bindings are unstable, and the DT blob must be kept in sync with the kernel? Andrew
Quoting Andrew Lunn (2016-02-22 06:16:17) > > Such information will come later, and we can rework the drivers and DT > > bindings accordingly. Those DT bindings cannot be stable, as the > > platform is under heavy development and we'll probably discover some > > issues down the road. > > Hi Thomas > > Maybe add a big fat warning that the bindings are unstable, and the DT > blob must be kept in sync with the kernel? +1 and feel free to blame the lack of documentation. No one can expect bindings to be finalized when the chip topology is not fully understood. Regards, Mike > > Andrew
On Mon, Feb 22, 2016 at 12:32 PM, Michael Turquette <mturquette@baylibre.com> wrote: > Quoting Andrew Lunn (2016-02-22 06:16:17) >> > Such information will come later, and we can rework the drivers and DT >> > bindings accordingly. Those DT bindings cannot be stable, as the >> > platform is under heavy development and we'll probably discover some >> > issues down the road. >> >> Hi Thomas >> >> Maybe add a big fat warning that the bindings are unstable, and the DT >> blob must be kept in sync with the kernel? > > +1 and feel free to blame the lack of documentation. No one can expect > bindings to be finalized when the chip topology is not fully understood. I can understand not understanding the full clock tree. I have "full" documentation of a Marvell chip and don't understand the clock tree fully. But I can't believe you don't have some sense of how many clocks you have to deal with. 10? 100? 1000? What I see is 2 nodes of a single register each for clocks at roughly the same address. That tells me your binding is too fine grained. If you really don't know what is right, then err on the side of a single clock provider node and don't put the clock details in DT. Rob
Quoting Rob Herring (2016-02-22 11:42:49) > On Mon, Feb 22, 2016 at 12:32 PM, Michael Turquette > <mturquette@baylibre.com> wrote: > > Quoting Andrew Lunn (2016-02-22 06:16:17) > >> > Such information will come later, and we can rework the drivers and DT > >> > bindings accordingly. Those DT bindings cannot be stable, as the > >> > platform is under heavy development and we'll probably discover some > >> > issues down the road. > >> > >> Hi Thomas > >> > >> Maybe add a big fat warning that the bindings are unstable, and the DT > >> blob must be kept in sync with the kernel? > > > > +1 and feel free to blame the lack of documentation. No one can expect > > bindings to be finalized when the chip topology is not fully understood. > > I can understand not understanding the full clock tree. I have "full" > documentation of a Marvell chip and don't understand the clock tree > fully. But I can't believe you don't have some sense of how many > clocks you have to deal with. 10? 100? 1000? What I see is 2 nodes of > a single register each for clocks at roughly the same address. That > tells me your binding is too fine grained. If you really don't know > what is right, then err on the side of a single clock provider node > and don't put the clock details in DT. I like the "err on the side of caution" part. I'll add that to clock-bindings.txt. Regards, Mike > > Rob
Hello, On Mon, 22 Feb 2016 13:42:49 -0600, Rob Herring wrote: > >> Maybe add a big fat warning that the bindings are unstable, and the DT > >> blob must be kept in sync with the kernel? > > > > +1 and feel free to blame the lack of documentation. No one can expect > > bindings to be finalized when the chip topology is not fully understood. > > I can understand not understanding the full clock tree. I have "full" > documentation of a Marvell chip and don't understand the clock tree > fully. But I can't believe you don't have some sense of how many > clocks you have to deal with. 10? 100? 1000? What I see is 2 nodes of > a single register each for clocks at roughly the same address. That > tells me your binding is too fine grained. If you really don't know > what is right, then err on the side of a single clock provider node > and don't put the clock details in DT. I don't quite understand the reasoning behind this conclusion. We know for sure that those two registers control only those core and ring clocks. Maybe there are other registers controlling other clocks, that we don't know. But for sure, those two registers only give details about those core and ring clocks, so I don't see what would be the usefulness of merging that into a single DT node. We would lose the fact that the relationship between the ring clocks and one of the core clock is represented in the DT. Instead of having a clear <&coreclk X> or <&ringclk Y> reference, we would have a mysterious <&allclk XYZ> reference, which doesn't tell immediately whether it's a core clock or ring clock. So, while I definitely agree that a syscon is probably in order to cover all the system registers, I don't see the point of having a single node to cover all the clocks. Best regards, Thomas
Rob, Michael, Stephen, On Tue, 23 Feb 2016 10:25:50 +0100, Thomas Petazzoni wrote: > > >> Maybe add a big fat warning that the bindings are unstable, and the DT > > >> blob must be kept in sync with the kernel? > > > > > > +1 and feel free to blame the lack of documentation. No one can expect > > > bindings to be finalized when the chip topology is not fully understood. > > > > I can understand not understanding the full clock tree. I have "full" > > documentation of a Marvell chip and don't understand the clock tree > > fully. But I can't believe you don't have some sense of how many > > clocks you have to deal with. 10? 100? 1000? What I see is 2 nodes of > > a single register each for clocks at roughly the same address. That > > tells me your binding is too fine grained. If you really don't know > > what is right, then err on the side of a single clock provider node > > and don't put the clock details in DT. > > I don't quite understand the reasoning behind this conclusion. We know > for sure that those two registers control only those core and ring > clocks. Maybe there are other registers controlling other clocks, that > we don't know. But for sure, those two registers only give details > about those core and ring clocks, so I don't see what would be the > usefulness of merging that into a single DT node. > > We would lose the fact that the relationship between the ring clocks > and one of the core clock is represented in the DT. Instead of having a > clear <&coreclk X> or <&ringclk Y> reference, we would have a > mysterious <&allclk XYZ> reference, which doesn't tell immediately > whether it's a core clock or ring clock. > > So, while I definitely agree that a syscon is probably in order to > cover all the system registers, I don't see the point of having a > single node to cover all the clocks. So, I had a discussion with Marvell engineers and a closer look at the matter. It turns out that those two clock registers are in the middle of an area called DFX (Design for Testability), which contain registers to fine tune the silicon and detect manufacturing issues. This area of registers is most likely never going to be publicly documented, and the fact that those two clock-related registers were placed there was more an oversight than a real architecture choice. For this reason, there is in fact no real benefit in mapping the entire area using a syscon, and having the two DT nodes for the core clocks and ring clocks, mapping just their own registers is by far the simplest solution considering the register layout. We would prefer to keep things as proposed in terms of DT representation, with the understanding that the submission of the Linux support for this platform comes very early in the chip development cycle, and that as such, the DT bindings should be considered unstable. Thanks a lot, Thomas
diff --git a/Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt new file mode 100644 index 0000000..b2131bb --- /dev/null +++ b/Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt @@ -0,0 +1,33 @@ +* Clock bindings for Marvell MVEBU AP806 Core clocks + +The Marvell MVEBU Armada 7K/8K SoCs contain a block called AP806, +hosting the CPU and other core components of the CPU. This Device Tree +binding allows to describe the core clocks of the AP806, whose +frequencies are determined by reading the Sample-At-Reset (SAR) +register. + +Clock consumers must specify the desired clock by having the clock ID +in its "clocks" phandle cell. + +The following is a list of provided IDs and clock names for the core +Armada AP806 clocks: + + 0 = DDR + 1 = Ring + 2 = CPU + +Required properties: +- compatible: must be be one of the following: + "marvell,armada-ap806-core-clock" +- reg: must be the register address of the Sample-At-Reset (SAR) register +- #clock-cells: from common clock binding; shall be set to 1 +- clock-output-names: name of the output clocks + +Example: + + coreclk: clk@0x6F8204 { + compatible = "marvell,armada-ap806-core-clock"; + reg = <0x6F8204 0x04>; + #clock-cells = <1>; + clock-output-names = "ddr", "ring", "cpu"; + }; diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig index 2769625..fd84172 100644 --- a/drivers/clk/mvebu/Kconfig +++ b/drivers/clk/mvebu/Kconfig @@ -42,3 +42,6 @@ config KIRKWOOD_CLK config ORION_CLK bool select MVEBU_CLK_COMMON + +config ARMADA_AP806_CORE_CLK + bool diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile index 8866115..db5c28c 100644 --- a/drivers/clk/mvebu/Makefile +++ b/drivers/clk/mvebu/Makefile @@ -1,11 +1,11 @@ obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o - obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o obj-$(CONFIG_ARMADA_39X_CLK) += armada-39x.o +obj-$(CONFIG_ARMADA_AP806_CORE_CLK) += ap806-core.o obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o obj-$(CONFIG_DOVE_CLK) += dove.o dove-divider.o obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o diff --git a/drivers/clk/mvebu/ap806-core.c b/drivers/clk/mvebu/ap806-core.c new file mode 100644 index 0000000..56c81cd --- /dev/null +++ b/drivers/clk/mvebu/ap806-core.c @@ -0,0 +1,112 @@ +/* + * Marvell Armada AP806 core clocks + * + * Copyright (C) 2016 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> + +/* + * AP806 PLLs: + * 0 - DDR + * 1 - Ring + * 2 - CPU + */ + +#define AP806_PLL_NUM 3 +#define AP806_PLL_FREQ 7 + +/* SAR parameters to get the PLL data */ +struct apclk_sar { + int mask; + int offset; + const char *name; +}; + +static const struct apclk_sar +ap806_core_clk_sar[AP806_PLL_NUM] __initconst = { + { .mask = 0x7, .offset = 21 }, + { .mask = 0x7, .offset = 18 }, + { .mask = 0x7, .offset = 15 }, +}; + +static struct clk *ap806_core_clks[AP806_PLL_NUM]; + +static struct clk_onecell_data ap806_core_clk_data = { + .clks = ap806_core_clks, + .clk_num = AP806_PLL_NUM, +}; + +/* mapping between SAR value to frequency */ +static const u32 +ap806_core_clk_freq[AP806_PLL_NUM][AP806_PLL_FREQ] __initconst = { + { 2400000000, 2100000000, 1800000000, + 1600000000, 1300000000, 1300000000, + 1300000000 }, + { 2000000000, 1800000000, 1600000000, + 1400000000, 1200000000, 1200000000, + 1200000000 }, + { 2500000000, 2200000000, 2000000000, + 1700000000, 1600000000, 1200000000, + 1200000000 }, +}; + +static unsigned long __init ap806_core_clk_get_freq(u32 reg, int clk_idx) +{ + int freq_idx; + const struct apclk_sar *clk_info; + + clk_info = &ap806_core_clk_sar[clk_idx]; + + freq_idx = (reg >> clk_info->offset) & clk_info->mask; + if (WARN_ON(freq_idx > AP806_PLL_FREQ)) + return 0; + else + return ap806_core_clk_freq[clk_idx][freq_idx]; +} + +static void __init ap806_core_clk_init(struct device_node *np) +{ + void __iomem *base; + u32 reg; + int i; + + base = of_iomap(np, 0); + if (WARN_ON(!base)) + return; + + reg = readl(base); + + iounmap(base); + + for (i = 0; i < AP806_PLL_NUM; i++) { + unsigned long freq; + const char *name; + + freq = ap806_core_clk_get_freq(reg, i); + + of_property_read_string_index(np, "clock-output-names", + i, &name); + + ap806_core_clks[i] = + clk_register_fixed_rate(NULL, name, NULL, + CLK_IS_ROOT, freq); + } + + of_clk_add_provider(np, of_clk_src_onecell_get, + &ap806_core_clk_data); +} + +CLK_OF_DECLARE(ap806_core_clk, "marvell,armada-ap806-core-clock", + ap806_core_clk_init);
This commit adds a new driver to handle the core clocks found in the AP806 HW block, which is the core block of all Armada 7K and 8K Marvell 64-bits processors. This core clock driver reads the Sample-At-Reset register to determine the frequencies of several core clocks: DDR, Ring and CPU clocks. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> --- .../clock/mvebu-armada-ap806-core-clock.txt | 33 ++++++ drivers/clk/mvebu/Kconfig | 3 + drivers/clk/mvebu/Makefile | 2 +- drivers/clk/mvebu/ap806-core.c | 112 +++++++++++++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/clock/mvebu-armada-ap806-core-clock.txt create mode 100644 drivers/clk/mvebu/ap806-core.c