Add support for MSM's mmio clocks
Subsystems (5)
cover Add support for MSM's mmio clocks
Reposting this RFC due to conflicts with v3.11-rc1 and because I haven't gone through and generated all the data needed yet. This is just a few clocks for now to give a general idea until I get some comments from DT reviewers.
The first 4 patches are generic clock framework patches. They add support for finding clocks in DT and parsing them generically. They also add support for setting the rate and the parent at the same time based on patches from James Hogan's remuxing set_rate series [1].
After that we add MSM clock hardware support and then fill in the DT and data to actually register clocks. This is sufficient enough to get the UART going on my msm8960 device.
If DT reviewers are ok I'll go ahead and generate the rest of the data and post v2.
Stephen Boyd (14):
clk: fixed-rate: Export clk_fixed_rate_register()
clk: Add of_init_clk_data() to parse common clock bindings
clk: Add of_clk_match() for device drivers
clk: Add set_rate_and_parent() op
clk: msm: Add support for phase locked loops (PLLs)
clk: msm: Add support for root clock generators (RCGs)
clk: msm: Add support for branches/gate clocks
clk: msm: Add MSM clock driver
clk: msm: Add support for MSM8960's global clock controller (GCC)
clk: msm: Add support for MSM8960's multimedia clock controller (MMCC)
ARM: dts: msm: Add MSM8960 GCC DT nodes
ARM: dts: msm: Add MSM8960 MMCC DT nodes
clk: msm: Add MSM8974 GCC data
ARM: dts: msm: Add clock entries for MSM8960 uart device
Documentation/clk.txt | 3 + Documentation/devicetree/bindings/clock/msm.txt | 99 +++ .../devicetree/bindings/clock/qcom,gcc.txt | 56 ++ .../devicetree/bindings/clock/qcom,mmcc.txt | 38 ++ arch/arm/boot/dts/msm8960-cdp.dts | 111 +++ drivers/clk/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/clk-fixed-rate.c | 1 + drivers/clk/clk.c | 201 +++++- drivers/clk/msm/Kconfig | 29 + drivers/clk/msm/Makefile | 12 + drivers/clk/msm/clk-branch.c | 190 ++++++ drivers/clk/msm/clk-branch.h | 48 ++ drivers/clk/msm/clk-pll.c | 233 +++++++ drivers/clk/msm/clk-pll.h | 43 ++ drivers/clk/msm/clk-rcg.c | 754 +++++++++++++++++++++ drivers/clk/msm/clk-rcg.h | 114 ++++ drivers/clk/msm/clk-rcg2.c | 320 +++++++++ drivers/clk/msm/core.c | 274 ++++++++ drivers/clk/msm/gcc-8960.c | 174 +++++ drivers/clk/msm/gcc-8974.c | 107 +++ drivers/clk/msm/internal.h | 28 + drivers/clk/msm/mmcc-8960.c | 142 ++++ include/linux/clk-provider.h | 38 ++ 24 files changed, 2998 insertions(+), 20 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/msm.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt create mode 100644 drivers/clk/msm/Kconfig create mode 100644 drivers/clk/msm/Makefile create mode 100644 drivers/clk/msm/clk-branch.c create mode 100644 drivers/clk/msm/clk-branch.h create mode 100644 drivers/clk/msm/clk-pll.c create mode 100644 drivers/clk/msm/clk-pll.h create mode 100644 drivers/clk/msm/clk-rcg.c create mode 100644 drivers/clk/msm/clk-rcg.h create mode 100644 drivers/clk/msm/clk-rcg2.c create mode 100644 drivers/clk/msm/core.c create mode 100644 drivers/clk/msm/gcc-8960.c create mode 100644 drivers/clk/msm/gcc-8974.c create mode 100644 drivers/clk/msm/internal.h create mode 100644 drivers/clk/msm/mmcc-8960.c
[1] Subject: [PATCH v5 0/5] clk: implement remuxing during set_rate Message-ID: <[email protected]>
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 1/14 clk: fixed-rate: Export clk_fixed_rate_register()
Export this symbol so that modules can register fixed rate clocks.
--- drivers/clk/clk-fixed-rate.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/clk-fixed-rate.c +1 -0
@@ -80,6 +80,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,return clk; } +EXPORT_SYMBOL_GPL (clk_register_fixed_rate);#ifdef CONFIG_OF /**
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 1/14 clk: fixed-rate: Export clk_fixed_rate_register()
Quoting Stephen Boyd (2013-07-24 17:43:29)
Quoted 4 lines
Export this symbol so that modules can register fixed rate clocks.
Signed-off-by Stephen Boyd <[email protected]>
Taken into clk-next.
Thanks,
Mike
Quoted 19 lines
--- drivers/clk/clk-fixed-rate.c | 1 + 1 file changed, 1 insertion(+)drivers/clk/clk-fixed-rate.c +1
-0@@ -80,6 +80,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,return clk; } +EXPORT_SYMBOL_GPL (clk_register_fixed_rate);#ifdef CONFIG_OF /** Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 2/14 clk: Add of_init_clk_data() to parse common clock bindings
In reply to Stephen BoydConsolidate DT parsing for the common bits of a clock binding in one place to simplify clock drivers. This also has the added benefit of standardizing how the clock names used by the common clock framework are generated from the DT bindings. We always use the first clock-output-names string if it exists, otherwise we fall back to the node name.
To be slightly more efficient and make the caller's life easier, we introduce a shallow copy flag so that the clock core knows to just copy the pointers to the strings and not the string contents. Otherwise the callers of this function would have to free the strings allocated here which could be cumbersome.
--- drivers/clk/clk.c | 59 +++++++++++++++++++++++++++++++++++++++++++- include/linux/clk-provider.h | 7 ++++++ 2 files changed, 65 insertions(+), 1 deletion(-)
drivers/clk/clk.c +58 -1
@@ -1809,6 +1809,10 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) {int i, ret; + hw->clk = clk; +if (hw->init->flags &CLK_SHALLOW_COPY ) +return PTR_RET (__clk_register (dev, hw)); + clk->name =kstrdup (hw->init->name,GFP_KERNEL );if (!clk->name) {pr_err ("%s: could not allocate clk->name\n" , __func__);
@@ -1819,7 +1823,6 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) clk->hw = hw; clk->flags = hw->init->flags; clk->num_parents = hw->init->num_parents; - hw->clk = clk;/* allocate local copy in case parent_names is __initdata */ clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents),
@@ -2232,4 +2235,58 @@ void __init of_clk_init(const struct of_device_id *matches) clk_init_cb(np); } } + +/** +* of_init_clk_data() - Initialize a clk_init_data struct from a DT node +* @np: node to initialize struct from +* @init: struct to initialize +* +* Populates the clk_init_data struct by parsing the device node for +* properties matching the common clock binding. Returns 0 on success +* and a negative error code on failure. +*/ +int of_init_clk_data (struct device_node *np,struct clk_init_data *init) +{ +struct of_phandle_args s; +const char **names =NULL , **p; +const char *name; +int i; + +if (of_property_read_string (np,"clock-output-names" , &name) <0 ) + name = np->name; + init->name =kstrdup (name,GFP_KERNEL ); +if (!init->name) +return -ENOMEM ; + +for (i =0 ;of_parse_phandle_with_args (np,"clocks" ,"#clock-cells" , + i, &s) ==0 ; i++) { + p =krealloc (names,sizeof (*names) * (i +1 ),GFP_KERNEL ); +if (!p) + goto err; + names = p; + +if (of_property_read_string (s.np,"clock-output-names" , + &name) <0 ) + name = s.np->name; + names[i] =kstrdup (name,GFP_KERNEL ); +if (!names[i]) + goto err; +of_node_put (s.np); + } + + init->parent_names = names; + init->num_parents = i; + init->flags = init->num_parents ?0 :CLK_IS_ROOT ; + init->flags |=CLK_SHALLOW_COPY ; + +return 0 ; +err: +of_node_put (s.np); +while (--i >=0 ) +kfree (names[i]); +kfree (names); +kfree (init->name); +return -ENOMEM ; +} +EXPORT_SYMBOL_GPL (of_init_clk_data);#endif
include/linux/clk-provider.h +7 -0
@@ -28,6 +28,7 @@#define CLK_IS_BASIC BIT(5)/* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6)/* do not use the cached clk rate */ #define CLK_SET_RATE_NO_REPARENT BIT(7)/* don't re-parent on rate change */ +#define CLK_SHALLOW_COPY BIT(8)/* don't copy the initdata strings */ struct clk_hw ;
@@ -472,6 +473,7 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);const char *of_clk_get_parent_name (struct device_node *np,int index);void of_clk_init (const struct of_device_id *matches); +int of_init_clk_data (struct device_node *np,struct clk_init_data *init);#else /* !CONFIG_OF */
@@ -501,6 +503,11 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, }#define of_clk_init (matches) \ { while (0); } +static inline int +of_init_clk_data (struct device_node *np,struct clk_init_data *init) +{ +return 0 ; +}#endif /* CONFIG_OF */ #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 02/14] clk: Add of_init_clk_data() to parse common clock bindings
Hi Stephen,
Pretty good idea, but I have some comments inline.
Quoted 62 lines · On Wednesday 24 of July 2013 17:43:30 Stephen Boyd wrote:
Consolidate DT parsing for the common bits of a clock binding in one place to simplify clock drivers. This also has the added benefit of standardizing how the clock names used by the common clock framework are generated from the DT bindings. We always use the first clock-output-names string if it exists, otherwise we fall back to the node name.
To be slightly more efficient and make the caller's life easier, we introduce a shallow copy flag so that the clock core knows to just copy the pointers to the strings and not the string contents. Otherwise the callers of this function would have to free the strings allocated here which could be cumbersome.
Cc Rob Herring <[email protected]>Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/clk.c | 59 +++++++++++++++++++++++++++++++++++++++++++- include/linux/clk-provider.h | 7 ++++++ 2 files changed, 65 insertions(+), 1 deletion(-)drivers/clk/clk.c +7
-1@@ -1809,6 +1809,10 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) { int i, ret; + hw->clk = clk; +if (hw->init->flags &CLK_SHALLOW_COPY ) +return PTR_RET (__clk_register (dev, hw)); + clk->name =kstrdup (hw->init->name,GFP_KERNEL );if (!clk->name) {pr_err ("%s: could not allocate clk->name\n" , __func__);@@ -1819,7 +1823,6 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) clk->hw = hw; clk->flags = hw->init->flags; clk->num_parents = hw->init->num_parents; - hw->clk = clk;/* allocate local copy in case parent_names is __initdata */ clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents),@@ -2232,4 +2235,58 @@ void __init of_clk_init(const struct of_device_id *matches) clk_init_cb(np); } } + +/** +* of_init_clk_data() - Initialize a clk_init_data struct from a DT node + * @np: node to initialize struct from
+ * @init: struct to initialize
+ *
+ * Populates theclk_init_datastruct by parsing the device node for
+ * properties matching the common clock binding. Returns 0 on success
+ * and a negative error code on failure.
+ */
+intof_init_clk_data(struct device_node *np, struct clk_init_data *init)+{drivers/clk/clk.c +2
-0+struct of_phandle_args s; +const char **names =NULL , **p;
drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches)
Quoted 10 lines
drivers/clk/clk.c +10
-0+const char *name; +int i; + +if (of_property_read_string (np,"clock-output-names" , &name) <0 ) + name = np->name; + init->name =kstrdup (name,GFP_KERNEL ); +if (!init->name) +return -ENOMEM ; + + for (i = 0; of_parse_phandle_with_args(np, "clocks", "#clock-
cells",
drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches) · line 2265
Quoted 4 lines
drivers/clk/clk.c +4
-0+ i, &s) == 0; i++) { + p =krealloc (names,sizeof (*names) * (i +1 ),GFP_KERNEL ); +if (!p) + goto err;
What about using of_count_phandle_with_args() first to get the parent count?
drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches) · line 2270
Quoted 5 lines
drivers/clk/clk.c +5
-0+ names = p; + +if (of_property_read_string (s.np,"clock-output-names" , + &name) <0 ) + name = s.np->name;
You should be able to use of_clk_get_parent_name() here, instead of parsing the properties directly.
Best regards,
Tomasz
Re: [PATCH v1 02/14] clk: Add of_init_clk_data() to parse common clock bindings
Quoted 74 lines · Tomasz Figa
Quoted 62 lines · On Wednesday 24 of July 2013 17:43:30 Stephen Boyd wrote:
Consolidate DT parsing for the common bits of a clock binding in one place to simplify clock drivers. This also has the added benefit of standardizing how the clock names used by the common clock framework are generated from the DT bindings. We always use the first clock-output-names string if it exists, otherwise we fall back to the node name.
To be slightly more efficient and make the caller's life easier, we introduce a shallow copy flag so that the clock core knows to just copy the pointers to the strings and not the string contents. Otherwise the callers of this function would have to free the strings allocated here which could be cumbersome.
Cc Rob Herring <[email protected]>Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/clk.c | 59 +++++++++++++++++++++++++++++++++++++++++++- include/linux/clk-provider.h | 7 ++++++ 2 files changed, 65 insertions(+), 1 deletion(-)drivers/clk/clk.c +7
-1@@ -1809,6 +1809,10 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) { int i, ret; + hw->clk = clk; +if (hw->init->flags &CLK_SHALLOW_COPY ) +return PTR_RET (__clk_register (dev, hw)); + clk->name =kstrdup (hw->init->name,GFP_KERNEL );if (!clk->name) {pr_err ("%s: could not allocate clk->name\n" , __func__);@@ -1819,7 +1823,6 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) clk->hw = hw; clk->flags = hw->init->flags; clk->num_parents = hw->init->num_parents; - hw->clk = clk;/* allocate local copy in case parent_names is __initdata */ clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents),@@ -2232,4 +2235,58 @@ void __init of_clk_init(const struct of_device_id *matches) clk_init_cb(np); } } + +/** +* of_init_clk_data() - Initialize a clk_init_data struct from a DT node + * @np: node to initialize struct from
+ * @init: struct to initialize
+ *
+ * Populates theclk_init_datastruct by parsing the device node for
+ * properties matching the common clock binding. Returns 0 on success
+ * and a negative error code on failure.
+ */
+intof_init_clk_data(struct device_node *np, struct clk_init_data *init)+{drivers/clk/clk.c +2
-0+struct of_phandle_args s; +const char **names =NULL , **p;drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches)
Quoted 10 lines
drivers/clk/clk.c +10
-0+const char *name; +int i; + +if (of_property_read_string (np,"clock-output-names" , &name) <0 ) + name = np->name; + init->name =kstrdup (name,GFP_KERNEL ); +if (!init->name) +return -ENOMEM ; + + for (i = 0; of_parse_phandle_with_args(np, "clocks", "#clock-cells",
Quoted 7 lines
drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches) · line 2265
Quoted 4 lines
drivers/clk/clk.c +4
-0+ i, &s) == 0; i++) { + p =krealloc (names,sizeof (*names) * (i +1 ),GFP_KERNEL ); +if (!p) + goto err;What about using
of_count_phandle_with_args()first to get the parent count?
Sure that simplifies things.
Quoted 9 lines
drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches) · line 2270
Quoted 6 lines
drivers/clk/clk.c +5
-0+ names = p; + +if (of_property_read_string (s.np,"clock-output-names" , + &name) <0 ) + name = s.np->name;You should be able to use
of_clk_get_parent_name()here, instead of parsing the properties directly.
This must be new too. Will do in v2.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 02/14] clk: Add of_init_clk_data() to parse common clock bindings
Quoting Stephen Boyd (2013-07-25 09:36:56)
Quoted 80 lines · Tomasz Figa
Quoted 79 lines · On Wednesday 24 of July 2013 17:43:30 Stephen Boyd wrote:
Quoted 62 lines
Consolidate DT parsing for the common bits of a clock binding in one place to simplify clock drivers. This also has the added benefit of standardizing how the clock names used by the common clock framework are generated from the DT bindings. We always use the first clock-output-names string if it exists, otherwise we fall back to the node name.
To be slightly more efficient and make the caller's life easier, we introduce a shallow copy flag so that the clock core knows to just copy the pointers to the strings and not the string contents. Otherwise the callers of this function would have to free the strings allocated here which could be cumbersome.
Cc Rob Herring <[email protected]>Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/clk.c | 59 +++++++++++++++++++++++++++++++++++++++++++- include/linux/clk-provider.h | 7 ++++++ 2 files changed, 65 insertions(+), 1 deletion(-)drivers/clk/clk.c +7
-1@@ -1809,6 +1809,10 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) { int i, ret; + hw->clk = clk; +if (hw->init->flags &CLK_SHALLOW_COPY ) +return PTR_RET (__clk_register (dev, hw)); + clk->name =kstrdup (hw->init->name,GFP_KERNEL );if (!clk->name) {pr_err ("%s: could not allocate clk->name\n" , __func__);@@ -1819,7 +1823,6 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) clk->hw = hw; clk->flags = hw->init->flags; clk->num_parents = hw->init->num_parents; - hw->clk = clk;/* allocate local copy in case parent_names is __initdata */ clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents),@@ -2232,4 +2235,58 @@ void __init of_clk_init(const struct of_device_id *matches) clk_init_cb(np); } } + +/** +* of_init_clk_data() - Initialize a clk_init_data struct from a DT node + * @np: node to initialize struct from
+ * @init: struct to initialize
+ *
+ * Populates theclk_init_datastruct by parsing the device node for
+ * properties matching the common clock binding. Returns 0 on success
+ * and a negative error code on failure.
+ */
+intof_init_clk_data(struct device_node *np, struct clk_init_data *init)+{drivers/clk/clk.c +2
-0+struct of_phandle_args s; +const char **names =NULL , **p;drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches)
Quoted 10 lines
drivers/clk/clk.c +10
-0+const char *name; +int i; + +if (of_property_read_string (np,"clock-output-names" , &name) <0 ) + name = np->name; + init->name =kstrdup (name,GFP_KERNEL ); +if (!init->name) +return -ENOMEM ; + + for (i = 0; of_parse_phandle_with_args(np, "clocks", "#clock-cells",
Quoted 4 lines
drivers/clk/clk.c +4
-0+ i, &s) == 0; i++) { + p =krealloc (names,sizeof (*names) * (i +1 ),GFP_KERNEL ); +if (!p) + goto err;
Quoted 4 lines
Quoted 2 lines
What about using
of_count_phandle_with_args()first to get the parent count?Sure that simplifies things.
I made a simple wrapper around of_count_phandle_with_args for the basic DT bindings series:
http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/178836.html
I still need to make a couple of changes to that before I merge it. If you want to base on top of the v3 version then you can use it, otherwise just use of_count_phandle_with_args.
Regards,
Mike
Quoted 16 lines
Quoted 10 lines
drivers/clk/clk.c void __init of_clk_init(const struct of_device_id *matches) · line 2270
Quoted 7 lines
drivers/clk/clk.c +5
-0+ names = p; + +if (of_property_read_string (s.np,"clock-output-names" , + &name) <0 ) + name = s.np->name;You should be able to use
of_clk_get_parent_name()here, instead of parsing the properties directly.This must be new too. Will do in v2.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 3/14 clk: Add of_clk_match() for device drivers
In reply to Stephen BoydIn similar fashion as of_regulator_match() add an of_clk_match() function that finds an initializes clock init_data structs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.
--- drivers/clk/clk.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 16 +++++++++++ 2 files changed, 80 insertions(+)
drivers/clk/clk.c +64 -0
@@ -2289,4 +2289,68 @@ err:return -ENOMEM ; }EXPORT_SYMBOL_GPL (of_init_clk_data); + +/** +* of_clk_match() - Scan and match clock providers from the DT node of a device +* @dev: device initializing clock providers +* @matches: match table of clocks +* @num_matches: number of entries in @matches +* +* This function uses a match table specified by the clock driver to parse +* clock init data from the device tree. @dev is expected to be a device with +* a 'clocks' child node containing a set of child nodes, each providing the +* init data for one clock. The data parsed from a child node will be matched +* to a clock based on the child node's name. Note that the match table is +* modified in place. +* +* Returns the number of matches found or a negative error code on failure. +*/ +int of_clk_match (struct device *dev,struct of_clk_match *matches, +int num_matches) +{ +int count =0 ; +int err, i; +struct device_node *np, *clocks; +struct clk_init_data *init; + + clocks =of_find_node_by_name (dev->of_node,"clocks" ); +if (!clocks) +return -EINVAL ; + +for (i =0 ; i < num_matches; i++) { +struct of_clk_match *match = &matches[i]; + match->init_data =NULL ; + match->of_node =NULL ; + } + +for_each_available_child_of_node (clocks, np) { +for (i =0 ; i < num_matches; i++) { +struct of_clk_match *match = &matches[i]; +if (match->of_node) +continue ; + +if (strcmp (match->name, np->name)) +continue ; + + init =devm_kzalloc (dev,sizeof (*init),GFP_KERNEL ); +if (!init) +return -ENOMEM ; + + err =of_init_clk_data (np, init); +if (err) { +dev_err (dev, +"failed to parse DT for clock %s\n" , + np->name); +return err; + } + match->of_node = np; + match->init_data = init; + count++; +break ; + } + } + +return count; +} +EXPORT_SYMBOL_GPL (of_clk_match);#endif
include/linux/clk-provider.h +16 -0
@@ -461,6 +461,13 @@ struct clk_onecell_data {__used __section (__clk_of_table ) \ = { .compatible = compat, .data = fn }; +struct of_clk_match { +const char *name; +void *driver_data; +struct clk_init_data *init_data; +struct device_node *of_node; +}; +#ifdef CONFIG_OF int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args *args,
@@ -475,6 +482,9 @@ const char *of_clk_get_parent_name(struct device_node *np, int index);void of_clk_init (const struct of_device_id *matches);int of_init_clk_data (struct device_node *np,struct clk_init_data *init); +int of_clk_match (struct device *dev,struct of_clk_match *matches, +int num_matches); +#else /* !CONFIG_OF */ static inline int of_clk_add_provider(struct device_node *np,
@@ -508,6 +518,12 @@ of_init_clk_data(struct device_node *np, struct clk_init_data *init) {return 0 ; } +static inline int +of_clk_match (struct device *dev,struct of_clk_match *matches,int num_matches) +{ + +return 0 ; +}#endif /* CONFIG_OF */ #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 03/14] clk: Add of_clk_match() for device drivers
Hi Stephen,
Quoted 5 lines · On Wednesday 24 of July 2013 17:43:31 Stephen Boyd wrote:
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.
I think all you need here is declaring all your clock drivers using CLK_OF_DECLARE() macro. Then they will be automatically probed by of_clk_init(). See last lines of drivers/clk/clk-fixed-rate.c for an example.
Best regards,
Tomasz
Quoted 49 lines
Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/clk.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 16 +++++++++++ 2 files changed, 80 insertions(+)drivers/clk/clk.c +3
-0@@ -2289,4 +2289,68 @@ err:return -ENOMEM ; }EXPORT_SYMBOL_GPL (of_init_clk_data); + +/** +* of_clk_match() - Scan and match clock providers from the DT node of a device + * @dev: device initializing clock providers
+ * @matches: match table of clocks
+ * @num_matches: number of entries in @matches
+ *
+ * This function uses a match table specified by the clock driver to parse + * clock init data from the device tree. @dev is expected to be a device with + * a 'clocks' child node containing a set of child nodes, each providing the + * init data for one clock. The data parsed from a child node will be matched + * to a clock based on the child node's name. Note that the match table is + * modified in place.
+ *
+ * Returns the number of matches found or a negative error code on failure. + */drivers/clk/clk.c +18
-0+int of_clk_match (struct device *dev,struct of_clk_match *matches, +int num_matches) +{ +int count =0 ; +int err, i; +struct device_node *np, *clocks; +struct clk_init_data *init; + + clocks =of_find_node_by_name (dev->of_node,"clocks" ); +if (!clocks) +return -EINVAL ; + +for (i =0 ; i < num_matches; i++) { +struct of_clk_match *match = &matches[i]; + match->init_data =NULL ; + match->of_node =NULL ; + } +
drivers/clk/clk.c err:
Quoted 10 lines
drivers/clk/clk.c +10
-0+for_each_available_child_of_node (clocks, np) { +for (i =0 ; i < num_matches; i++) { +struct of_clk_match *match = &matches[i]; +if (match->of_node) +continue ; + +if (strcmp (match->name, np->name)) +continue ; + + init = devm_kzalloc(dev, sizeof(*init),
GFP_KERNEL);
drivers/clk/clk.c err:
Quoted 7 lines
drivers/clk/clk.c +7
-0+if (!init) +return -ENOMEM ; + + err =of_init_clk_data (np, init); +if (err) { + dev_err(dev, + "failed to parse DT for clock
%s\n",
Quoted 22 lines
drivers/clk/clk.c +13
-0+ np->name); + return err; + } + match->of_node = np; + match->init_data = init; + count++; +break ; + } + } + +return count; +} +EXPORT_SYMBOL_GPL (of_clk_match);#endif include/linux/clk-provider.h +0
-0@@ -461,6 +461,13 @@ struct clk_onecell_data {__used __section (__clk_of_table ) \ = { .compatible = compat, .data = fn };
include/linux/clk-provider.h struct clk_onecell_data { · line 473
Quoted 10 lines
include/linux/clk-provider.h +7
-0+struct of_clk_match { +const char *name; +void *driver_data; +struct clk_init_data *init_data; +struct device_node *of_node; +}; +#ifdef CONFIG_OF int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args
*args,
Quoted 25 lines
include/linux/clk-provider.h +0
-0@@ -475,6 +482,9 @@ const char *of_clk_get_parent_name(struct
device_node*np, int index); voidof_clk_init(const struct of_device_id *matches);
int of_init_clk_data(structdevice_node*np, structclk_init_data
*init);include/linux/clk-provider.h +8
-0+int of_clk_match (struct device *dev,struct of_clk_match *matches, +int num_matches); +#else /* !CONFIG_OF */ static inline int of_clk_add_provider(struct device_node *np,@@ -508,6 +518,12 @@ of_init_clk_data(struct device_node *np, struct clk_init_data *init) {return 0 ; } +static inline int +of_clk_match (struct device *dev,struct of_clk_match *matches,int num_matches) +{ + +return 0 ; +}#endif /* CONFIG_OF */ #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */
Re: [PATCH v1 03/14] clk: Add of_clk_match() for device drivers
Quoted 9 lines · Tomasz Figa
Hi Stephen,
Quoted 5 lines · On Wednesday 24 of July 2013 17:43:31 Stephen Boyd wrote:
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.
Quoted 5 lines
I think all you need here is declaring all your clock drivers using
CLK_OF_DECLARE()macro. Then they will be automatically probed byof_clk_init(). See last lines ofdrivers/clk/clk-fixed-rate.cfor an example.
CLK_OF_DECLARE() will not work because it doesn't give the caller a struct device. I want that struct device to use managed allocations and clk registrations.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 3/14 clk: Add of_clk_match() for device drivers
In reply to Stephen BoydQuoting Stephen Boyd (2013-07-24 17:43:31)
Quoted 7 lines
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.Signed-off-by Stephen Boyd <[email protected]>
Stephen,
In general I like this approach. Writing real device drivers for clock controllers is The Right Way and of_clk_match helps.
Am I reading this correctly that the base register addresses/offsets for the clock nodes still come from C files? For example I still see pll8_desc defining reg stuff in drivers/clk/msm/gcc-8960.c.
What do you think about fetching this data from DT? My thinking here is that the definition of that PLL structure would be in C, as would all of the control logic. But any per-clock data whatsoever should live in DTS. This means the clock data you supply in the DTS files in patches #9 and #10 would have base addresses or offsets per-clock. I think this echoes Mark R's concerns as well.
In the future if new chips have more of that type of PLL it would not require changes to your clock driver, only new DTS data for the new chip.
I could have that wrong though, there is a fair amount of indirection in this series...
Regards,
Mike
Quoted 122 lines
--- drivers/clk/clk.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 16 +++++++++++ 2 files changed, 80 insertions(+)drivers/clk/clk.c +64
-0@@ -2289,4 +2289,68 @@ err:return -ENOMEM ; }EXPORT_SYMBOL_GPL (of_init_clk_data); + +/** +* of_clk_match() - Scan and match clock providers from the DT node of a device +* @dev: device initializing clock providers +* @matches: match table of clocks +* @num_matches: number of entries in @matches +* +* This function uses a match table specified by the clock driver to parse +* clock init data from the device tree. @dev is expected to be a device with +* a 'clocks' child node containing a set of child nodes, each providing the +* init data for one clock. The data parsed from a child node will be matched +* to a clock based on the child node's name. Note that the match table is +* modified in place. +* +* Returns the number of matches found or a negative error code on failure. +*/ +int of_clk_match (struct device *dev,struct of_clk_match *matches, +int num_matches) +{ +int count =0 ; +int err, i; +struct device_node *np, *clocks; +struct clk_init_data *init; + + clocks =of_find_node_by_name (dev->of_node,"clocks" ); +if (!clocks) +return -EINVAL ; + +for (i =0 ; i < num_matches; i++) { +struct of_clk_match *match = &matches[i]; + match->init_data =NULL ; + match->of_node =NULL ; + } + +for_each_available_child_of_node (clocks, np) { +for (i =0 ; i < num_matches; i++) { +struct of_clk_match *match = &matches[i]; +if (match->of_node) +continue ; + +if (strcmp (match->name, np->name)) +continue ; + + init =devm_kzalloc (dev,sizeof (*init),GFP_KERNEL ); +if (!init) +return -ENOMEM ; + + err =of_init_clk_data (np, init); +if (err) { +dev_err (dev, +"failed to parse DT for clock %s\n" , + np->name); +return err; + } + match->of_node = np; + match->init_data = init; + count++; +break ; + } + } + +return count; +} +EXPORT_SYMBOL_GPL (of_clk_match);#endif include/linux/clk-provider.h +16
-0@@ -461,6 +461,13 @@ struct clk_onecell_data {__used __section (__clk_of_table ) \ = { .compatible = compat, .data = fn }; +struct of_clk_match { +const char *name; +void *driver_data; +struct clk_init_data *init_data; +struct device_node *of_node; +}; +#ifdef CONFIG_OF int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args *args,@@ -475,6 +482,9 @@ const char *of_clk_get_parent_name(struct device_node *np, int index);void of_clk_init (const struct of_device_id *matches);int of_init_clk_data (struct device_node *np,struct clk_init_data *init); +int of_clk_match (struct device *dev,struct of_clk_match *matches, +int num_matches); +#else /* !CONFIG_OF */ static inline int of_clk_add_provider(struct device_node *np,@@ -508,6 +518,12 @@ of_init_clk_data(struct device_node *np, struct clk_init_data *init) {return 0 ; } +static inline int +of_clk_match (struct device *dev,struct of_clk_match *matches,int num_matches) +{ + +return 0 ; +}#endif /* CONFIG_OF */ #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */ Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 03/14] clk: Add of_clk_match() for device drivers
Quoted 9 lines · Mike Turquette
Quoting Stephen Boyd (2013-07-24 17:43:31)
Quoted 7 lines
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.Signed-off-by Stephen Boyd <[email protected]>
Quoted 8 lines
Stephen,
In general I like this approach. Writing real device drivers for clock controllers is The Right Way and
of_clk_matchhelps.Am I reading this correctly that the base register addresses/offsets for the clock nodes still come from C files? For example I still see
pll8_descdefining reg stuff indrivers/clk/msm/gcc-8960.c.
I think we may be able to put the registers in DT but I don't know why we need to do that if we're already matching up nodes with C structs. It also made me want to introduce devm_of_iomap() which just seemed wrong (if you have a dev struct why can't you use devm_ioremap()).
Quoted 8 lines
What do you think about fetching this data from DT? My thinking here is that the definition of that PLL structure would be in C, as would all of the control logic. But any per-clock data whatsoever should live in DTS. This means the clock data you supply in the DTS files in patches #9 and #10 would have base addresses or offsets per-clock. I think this echoes Mark R's concerns as well.
Quoted 6 lines
In the future if new chips have more of that type of PLL it would not require changes to your clock driver, only new DTS data for the new chip.
I could have that wrong though, there is a fair amount of indirection in this series...
Let's take the PLL example and see if I follow what would be in DT and what would be in C.
Right now we have
pll8: pll8 {
#clock-cells = <0>;
compatible = "qcom,pll";
clocks = <&pxo>;
};in DT and
static struct pll_desc pll8_desc = {
.l_reg = 0x3144,
.m_reg = 0x3148,
.n_reg = 0x314c,
.config_reg = 0x3154,
.mode_reg = 0x3140,
.status_reg = 0x3158,
.status_bit = 16,
};in C. Do you want everything to be in DT? Something like:
pll8: pll8 at 3140 {
#clock-cells = <0>;
compatible = "qcom,pll";
clocks = <&pxo>;
reg = <0x3140 0x20>;
};and then assume that all those registers are offset from the base register and that the status bit is 16 (it usually is but not always)?
The problem I see is this quickly breaks down with more complicated clocks like the RCGs.
We have
gsbi5_uart_rcg: gsbi5_uart_rcg {
#clock-cells = <0>;
compatible = "qcom,p2-mn16-clock";
clocks = <&pxo>, <&vpll8>;
};in DT and
static struct freq_tbl clk_tbl_gsbi_uart[] = {
{ 1843200, PLL8, 2, 6, 625 },
{ 3686400, PLL8, 2, 12, 625 },
{ 7372800, PLL8, 2, 24, 625 },
{ 14745600, PLL8, 2, 48, 625 },
{ 16000000, PLL8, 4, 1, 6 },
{ 24000000, PLL8, 4, 1, 4 },
{ 32000000, PLL8, 4, 1, 3 },
{ 40000000, PLL8, 1, 5, 48 },
{ 46400000, PLL8, 1, 29, 240 },
{ 48000000, PLL8, 4, 1, 2 },
{ 51200000, PLL8, 1, 2, 15 },
{ 56000000, PLL8, 1, 7, 48 },
{ 58982400, PLL8, 1, 96, 625 },
{ 64000000, PLL8, 2, 1, 3 },
{ }
};
static struct rcg_desc gsbi5_uart_rcg = {
.ctl_reg = 0x2a54,
.ns_reg = 0x2a54,
.md_reg = 0x2a50,
.ctl_bit = 11,
.mnctr_en_bit = 8,
.mnctr_reset_bit = 7,
.mnctr_mode_shift = 5,
.pre_div_shift = 3,
.src_sel_shift = 0,
.n_val_shift = 16,
.m_val_shift = 16,
.parent_map = gcc_pxo_pll8_map,
.freq_tbl = clk_tbl_gsbi_uart,
};in C. It starts to get pretty unwieldy when you put this all in DT, plus you'll notice that the ns_reg and ctl_reg are the same here because we've generalized the code to work with different types of software interfaces (technically this clock has no ctl register, just an NS and MD register). Our multimedia clock controllers don't follow any standard base/offset pair and so the ctl_reg can be a different offset from the md_reg depending on which clock we're talking about. My initial try at translating this into DT pretty much just made every struct member into a property, including the duplicate register, expect for the frequency table, which could probably also be DT-ified with some work.
gsbi5_uart_rcg: gsbi5_uart_rcg at 2a54 {
#clock-cells = <0>;
compatible = "qcom,p2-mn16-clock";
clocks = <&pxo>, <&vpll8>;
reg = <0x2a54 0x4>,
<0x2a54 0x4>,
<0x2a50 0x4>;
ctl_bit = <11>;
mnctr_en_bit = <8>;
mnctr_reset_bit = <7>;
mnctr_mode_shift = <5>;
pre_div_shift = <3>;
src_sel_shift = <0>;
n_val_shift = <16>;
m_val_shift = <16>;
};This is great for making the kernel DT-data-driven, but I couldn't find any other driver that was describing register level details in DT.
The good news is that newer clock controllers follow a standard and so we can specify one or two register properties and the type of clock and we're pretty much done. The software interface hasn't been randomized like on earlier controllers and bits within registers are always the same. We still have some clocks that are just on/off switches though and so we'll have to put register level details like which bit turns that clock on in DT (which I believe is not preferred/allowed?). I don't see any way to avoid that if we want it to be entirely DT driven.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 3/14 clk: Add of_clk_match() for device drivers
Quoting Stephen Boyd (2013-08-12 22:48:39)
Quoted 15 lines · Mike Turquette
Quoted 14 lines
Quoting Stephen Boyd (2013-07-24 17:43:31)
Quoted 7 lines
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.Signed-off-by Stephen Boyd <[email protected]>Stephen,
In general I like this approach. Writing real device drivers for clock controllers is The Right Way and
of_clk_matchhelps.
Quoted 7 lines
Quoted 3 lines
Am I reading this correctly that the base register addresses/offsets for the clock nodes still come from C files? For example I still see
pll8_descdefining reg stuff indrivers/clk/msm/gcc-8960.c.I think we may be able to put the registers in DT but I don't know why we need to do that if we're already matching up nodes with C structs.
The reason to do so is to remove the per-clock data from the kernel sources entirely. Separating logic and data.
Quoted 51 lines
It also made me want to introduce
devm_of_iomap()which just seemed wrong (if you have a dev struct why can't you usedevm_ioremap()).Quoted 8 lines
What do you think about fetching this data from DT? My thinking here is that the definition of that PLL structure would be in C, as would all of the control logic. But any per-clock data whatsoever should live in DTS. This means the clock data you supply in the DTS files in patches #9 and #10 would have base addresses or offsets per-clock. I think this echoes Mark R's concerns as well.
Quoted 6 lines
In the future if new chips have more of that type of PLL it would not require changes to your clock driver, only new DTS data for the new chip.
I could have that wrong though, there is a fair amount of indirection in this series...
Let's take the PLL example and see if I follow what would be in DT and what would be in C.
Right now we have
pll8: pll8 { #clock-cells = <0>; compatible = "qcom,pll"; clocks = <&pxo>; };in DT and
static struct pll_desc pll8_desc = { .l_reg = 0x3144, .m_reg = 0x3148, .n_reg = 0x314c, .config_reg = 0x3154, .mode_reg = 0x3140, .status_reg = 0x3158, .status_bit = 16, };in C. Do you want everything to be in DT? Something like:
pll8: pll8 at 3140 { #clock-cells = <0>; compatible = "qcom,pll"; clocks = <&pxo>; reg = <0x3140 0x20>; };
Quoted 3 lines
and then assume that all those registers are offset from the base register and that the status bit is 16 (it usually is but not always)?
Ideally, yes. Adding new clocks of this type would not require changes to the kernel sources.
Quoted 78 lines
The problem I see is this quickly breaks down with more complicated clocks like the RCGs.
We have
gsbi5_uart_rcg: gsbi5_uart_rcg { #clock-cells = <0>; compatible = "qcom,p2-mn16-clock"; clocks = <&pxo>, <&vpll8>; };in DT and
static struct freq_tbl clk_tbl_gsbi_uart[] = { { 1843200, PLL8, 2, 6, 625 }, { 3686400, PLL8, 2, 12, 625 }, { 7372800, PLL8, 2, 24, 625 }, { 14745600, PLL8, 2, 48, 625 }, { 16000000, PLL8, 4, 1, 6 }, { 24000000, PLL8, 4, 1, 4 }, { 32000000, PLL8, 4, 1, 3 }, { 40000000, PLL8, 1, 5, 48 }, { 46400000, PLL8, 1, 29, 240 }, { 48000000, PLL8, 4, 1, 2 }, { 51200000, PLL8, 1, 2, 15 }, { 56000000, PLL8, 1, 7, 48 }, { 58982400, PLL8, 1, 96, 625 }, { 64000000, PLL8, 2, 1, 3 }, { } }; static struct rcg_desc gsbi5_uart_rcg = { .ctl_reg = 0x2a54, .ns_reg = 0x2a54, .md_reg = 0x2a50, .ctl_bit = 11, .mnctr_en_bit = 8, .mnctr_reset_bit = 7, .mnctr_mode_shift = 5, .pre_div_shift = 3, .src_sel_shift = 0, .n_val_shift = 16, .m_val_shift = 16, .parent_map = gcc_pxo_pll8_map, .freq_tbl = clk_tbl_gsbi_uart, };in C. It starts to get pretty unwieldy when you put this all in DT, plus you'll notice that the
ns_regandctl_regare the same here because we've generalized the code to work with different types of software interfaces (technically this clock has no ctl register, just an NS and MD register). Our multimedia clock controllers don't follow any standard base/offset pair and so thectl_regcan be a different offset from themd_regdepending on which clock we're talking about. My initial try at translating this into DT pretty much just made every struct member into a property, including the duplicate register, expect for the frequency table, which could probably also be DT-ified with some work.gsbi5_uart_rcg: gsbi5_uart_rcg at 2a54 { #clock-cells = <0>; compatible = "qcom,p2-mn16-clock"; clocks = <&pxo>, <&vpll8>; reg = <0x2a54 0x4>, <0x2a54 0x4>, <0x2a50 0x4>; ctl_bit = <11>; mnctr_en_bit = <8>; mnctr_reset_bit = <7>; mnctr_mode_shift = <5>; pre_div_shift = <3>; src_sel_shift = <0>; n_val_shift = <16>; m_val_shift = <16>; };
Quoted 3 lines
This is great for making the kernel DT-data-driven, but I couldn't find any other driver that was describing register level details in DT.
Yeah, this sucks. Building a binding from a C struct is a bad idea. How many permutations are there? Hopefully some clocks use the same bit shifts and have reliable register offsets, with the only difference being base address. If this is the case then a compatible string could be done for each permutation assuming that number is low and manageable.
Quoted 6 lines
The good news is that newer clock controllers follow a standard and so we can specify one or two register properties and the type of clock and we're pretty much done. The software interface hasn't been randomized like on earlier controllers and bits within registers are always the same.
This does not suck. Just for the sake of argument let's say that you only had to deal with this new and improved register layout and not the old (current) stuff. Do you still see a reason to match DT data up with C struct data objects in the kernel?
Quoted 5 lines
We still have some clocks
that are just on/off switches though and so we'll have to put register level details like which bit turns that clock on in DT (which I believe is not preferred/allowed?). I don't see any way to avoid that if we want it to be entirely DT driven.
This is what I'm doing for the generic clock bindings. No one has screamed over that stuff so I guess rules were meant to be broken.
Regards,
Mike
Quoted 4 lines
Signature · 3 lines
-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 03/14] clk: Add of_clk_match() for device drivers
Quoted 20 lines · Mike Turquette
Quoting Stephen Boyd (2013-08-12 22:48:39)
Quoted 19 lines · Mike Turquette
Quoted 17 lines
Quoting Stephen Boyd (2013-07-24 17:43:31)
Quoted 7 lines
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.Signed-off-by Stephen Boyd <[email protected]>Stephen,
In general I like this approach. Writing real device drivers for clock controllers is The Right Way and
of_clk_matchhelps.Am I reading this correctly that the base register addresses/offsets for the clock nodes still come from C files? For example I still see
pll8_descdefining reg stuff indrivers/clk/msm/gcc-8960.c.
Quoted 6 lines
Quoted 3 lines
I think we may be able to put the registers in DT but I don't know why we need to do that if we're already matching up nodes with C structs.
The reason to do so is to remove the per-clock data from the kernel sources entirely. Separating logic and data.
Ok.
Quoted 5 lines
Quoted 5 lines
It also made me want to introduce
devm_of_iomap()which just seemed wrong (if you have a dev struct why can't you usedevm_ioremap()).
[snip]
Quoted 10 lines
Quoted 4 lines
This is great for making the kernel DT-data-driven, but I couldn't find any other driver that was describing register level details in DT.
Yeah, this sucks. Building a binding from a C struct is a bad idea. How many permutations are there? Hopefully some clocks use the same bit shifts and have reliable register offsets, with the only difference being base address. If this is the case then a compatible string could be done for each permutation assuming that number is low and manageable.
In the multimedia controller almost every clock has a different register layout. Making a compatible string for each clock is pretty much what I've done if you consider that I match up the name of the node to a struct instead of matching a compatible string to a struct. In the global controller it's more sane, following a single register layout per compatible string. Remember though, all the single bit clocks (gates or what we call branches) have a completely random location for their on/off bit and status bit.
Quoted 8 lines
Quoted 7 lines
The good news is that newer clock controllers follow a standard and so we can specify one or two register properties and the type of clock and we're pretty much done. The software interface hasn't been randomized like on earlier controllers and bits within registers are always the same.
Quoted 4 lines
This does not suck. Just for the sake of argument let's say that you only had to deal with this new and improved register layout and not the old (current) stuff. Do you still see a reason to match DT data up with C struct data objects in the kernel?
I would still need to match up frequency tables unless I figure out a way to put that in DT too.
Quoted 10 lines
Quoted 6 lines
We still have some clocks
that are just on/off switches though and so we'll have to put register level details like which bit turns that clock on in DT (which I believe is not preferred/allowed?). I don't see any way to avoid that if we want it to be entirely DT driven.This is what I'm doing for the generic clock bindings. No one has screamed over that stuff so I guess rules were meant to be broken.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 3/14 clk: Add of_clk_match() for device drivers
Quoting Stephen Boyd (2013-08-15 18:31:19)
Quoted 47 lines · Mike Turquette
Quoted 20 lines
Quoting Stephen Boyd (2013-08-12 22:48:39)
Quoted 19 lines · Mike Turquette
Quoted 17 lines
Quoting Stephen Boyd (2013-07-24 17:43:31)
Quoted 7 lines
In similar fashion as
of_regulator_match()add anof_clk_match()function that finds an initializes clockinit_datastructs from devicetree. Drivers should use this API to find clocks that their device is providing and then iterate over their match table registering the clocks with the init data parsed.Signed-off-by Stephen Boyd <[email protected]>Stephen,
In general I like this approach. Writing real device drivers for clock controllers is The Right Way and
of_clk_matchhelps.Am I reading this correctly that the base register addresses/offsets for the clock nodes still come from C files? For example I still see
pll8_descdefining reg stuff indrivers/clk/msm/gcc-8960.c.Quoted 6 lines
Quoted 3 lines
I think we may be able to put the registers in DT but I don't know why we need to do that if we're already matching up nodes with C structs.
The reason to do so is to remove the per-clock data from the kernel sources entirely. Separating logic and data.
Ok.
Quoted 5 lines
Quoted 5 lines
It also made me want to introduce
devm_of_iomap()which just seemed wrong (if you have a dev struct why can't you usedevm_ioremap()).[snip]
Quoted 10 lines
Quoted 4 lines
This is great for making the kernel DT-data-driven, but I couldn't find any other driver that was describing register level details in DT.
Yeah, this sucks. Building a binding from a C struct is a bad idea. How many permutations are there? Hopefully some clocks use the same bit shifts and have reliable register offsets, with the only difference being base address. If this is the case then a compatible string could be done for each permutation assuming that number is low and manageable.
Quoted 5 lines
In the multimedia controller almost every clock has a different register layout. Making a compatible string for each clock is pretty much what I've done if you consider that I match up the name of the node to a struct instead of matching a compatible string to a struct.
Right, the data has to live somewhere and any solution that puts static per-clock data in the kernel solves the matching in one way or another. The "map a clock to a number" approach does the same thing, but differently (though I like this approach better than the number mapping one).
I guess we're at a point where two different guidelines are at odds. The first is not to put register-level details into DT. The second is to move data out of the kernel and stop all of the "crazy churn" that Linus ranted about in his famous email 2-3 years back.
Quoted 5 lines
In the global controller it's more sane,
following a single register layout per compatible string. Remember though, all the single bit clocks (gates or what we call branches) have a completely random location for their on/off bit and status bit.
I looked at the branch clock data in gcc-8960.c and gcc-8974.c and there are more bits to twiddle and more registers to access than I thought there would be. As a counter example I am happy with simple gate clock implementations specifying a single bit to enable/disable a clock in DT. That's really not such a big deal.
However without a somewhat common pattern to this stuff you need to keep it in C. But you said that common patterns are on the horizon for your platform; I guess you're going to reuse some of these clock types for that upcoming stuff, right? What do you think about taking that into account and adding an optional 'reg' property to the binding definition? The purpose of that would be so that the same binding here could be used for the future stuff, but all of the data could live in DT. That's where I'd like things to get to eventually.
Regards,
Mike
Quoted 32 lines
Quoted 9 lines
Quoted 8 lines
The good news is that newer clock controllers follow a standard and so we can specify one or two register properties and the type of clock and we're pretty much done. The software interface hasn't been randomized like on earlier controllers and bits within registers are always the same.
Quoted 4 lines
This does not suck. Just for the sake of argument let's say that you only had to deal with this new and improved register layout and not the old (current) stuff. Do you still see a reason to match DT data up with C struct data objects in the kernel?
I would still need to match up frequency tables unless I figure out a way to put that in DT too.
Quoted 10 lines
Quoted 6 lines
We still have some clocks
that are just on/off switches though and so we'll have to put register level details like which bit turns that clock on in DT (which I believe is not preferred/allowed?). I don't see any way to avoid that if we want it to be entirely DT driven.This is what I'm doing for the generic clock bindings. No one has screamed over that stuff so I guess rules were meant to be broken.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 03/14] clk: Add of_clk_match() for device drivers
In reply to Mike TurquetteQuoted 29 lines · Mike Turquette
Quoted 29 lines
Right now we have
pll8: pll8 { #clock-cells = <0>; compatible = "qcom,pll"; clocks = <&pxo>; };in DT and
static struct pll_desc pll8_desc = { .l_reg = 0x3144, .m_reg = 0x3148, .n_reg = 0x314c, .config_reg = 0x3154, .mode_reg = 0x3140, .status_reg = 0x3158, .status_bit = 16, };in C. Do you want everything to be in DT? Something like:
pll8: pll8 at 3140 { #clock-cells = <0>; compatible = "qcom,pll"; clocks = <&pxo>; reg = <0x3140 0x20>; };
Quoted 3 lines
Quoted 3 lines
and then assume that all those registers are offset from the base register and that the status bit is 16 (it usually is but not always)?
I think its reasonable to put the various regs associated with a clock in the .dts like the example you show, but we should be going down to bit level details. If we think of each clock as its own device its reasonable that the clock would have some set of registers associated with it.
-k
Signature · 2 lines
Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 03/14] clk: Add of_clk_match() for device drivers
Quoted 32 lines · Kumar Gala
Quoted 29 lines · Mike Turquette
Quoted 29 lines
Right now we have
pll8: pll8 { #clock-cells = <0>; compatible = "qcom,pll"; clocks = <&pxo>; };in DT and
static struct pll_desc pll8_desc = { .l_reg = 0x3144, .m_reg = 0x3148, .n_reg = 0x314c, .config_reg = 0x3154, .mode_reg = 0x3140, .status_reg = 0x3158, .status_bit = 16, };in C. Do you want everything to be in DT? Something like:
pll8: pll8 at 3140 { #clock-cells = <0>; compatible = "qcom,pll"; clocks = <&pxo>; reg = <0x3140 0x20>; };
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
and then assume that all those registers are offset from the base register and that the status bit is 16 (it usually is but not always)?
I think its reasonable to put the various regs associated with a clock in the .dts like the example you show, but we should be going down to bit level details. If we think of each clock as its own device its reasonable that the clock would have some set of registers associated with it.
oops, we should NOT be going down to bit level.
- k
Signature · 2 lines
Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 4/14 clk: Add set_rate_and_parent() op
In reply to Stephen BoydSome of Qualcomm's clocks can change their parent and rate at the same time with a single register write. Add support for this hardware to the common clock framework by adding a new set_rate_and_parent() op. When the clock framework determines that both the parent and the rate are going to change during clk_set_rate() it will call the .set_rate_and_parent() op if available and fall back to calling .set_parent() followed by .set_rate() otherwise.
--- Documentation/clk.txt | 3 ++ drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++++----------- include/linux/clk-provider.h | 15 +++++++++ 3 files changed, 77 insertions(+), 19 deletions(-)
Documentation/clk.txt +3 -0
@@ -77,6 +77,9 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + int (*set_rate_and_parent)(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, u8 index); void (*init)(struct clk_hw *hw); };
drivers/clk/clk.c +59 -19
116 lines not on this page · raw message
include/linux/clk-provider.h +15 -0
@@ -108,6 +108,18 @@ struct clk_hw;* which is likely helpful for most .set_rate implementation. * Returns 0 on success, -EERROR otherwise. * +* @set_rate_and_parent: Change the rate and the parent of this clock. The +* requested rate is specified by the second argument, which +* should typically be the return of .round_rate call. The +* third argument gives the parent rate which is likely helpful +* for most .set_rate_and_parent implementation. The fourth +* argument gives the parent index. It is optional (and +* unnecessary) for clocks with 0 or 1 parents as well as +* for clocks that can tolerate switching the rate and the parent +* separately via calls to .set_parent and .set_rate. +* Returns 0 on success, -EERROR otherwise. +* +* * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow * implementations to split any work between atomic (enable) and sleepable * (prepare) contexts. If enabling a clock requires code that might sleep,
@@ -139,6 +151,9 @@ struct clk_ops {u8 (*get_parent)(struct clk_hw *hw);int (*set_rate)(struct clk_hw *hw,unsigned long ,unsigned long ); +int (*set_rate_and_parent)(struct clk_hw *hw, +unsigned long rate, +unsigned long parent_rate,u8 index);void (*init)(struct clk_hw *hw); };
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 04/14] clk: Add set_rate_and_parent() op
Quoted 8 lines · On Wednesday 24 of July 2013 17:43:32 Stephen Boyd wrote:
Some of Qualcomm's clocks can change their parent and rate at the same time with a single register write. Add support for this hardware to the common clock framework by adding a new
set_rate_and_parent()op. When the clock framework determines that both the parent and the rate are going to change duringclk_set_rate()it will call the .set_rate_and_parent() op if available and fall back to calling .set_parent() followed by .set_rate() otherwise.
This is strange. Does you hardware support switching parent and rate separately or you always need to set both and so all the fuss here?
If the latter is the case, then maybe you can simply keep parent index and rate cached inside driver data of your clock driver and use them on any .set_rate() or .set_parent() calls?
I'm not really sure if we want such oddities to be handled inside of common clock framework. Mike, what do you think?
Best regards,
Tomasz
Quoted 14 lines
Cc James Hogan <[email protected]>Signed-off-by Stephen Boyd <[email protected]>--- Documentation/clk.txt | 3 ++ drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++++----------- include/linux/clk-provider.h | 15 +++++++++ 3 files changed, 77 insertions(+), 19 deletions(-)Documentation/clk.txt +0
-0
Documentation/clk.txt the operations defined in clk.h: · line 77
Quoted 1 line
Documentation/clk.txt +0
-0@@ -77,6 +77,9 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8
index);
Documentation/clk.txt the operations defined in clk.h: · line 79
Quoted 2 lines
Documentation/clk.txt +0
-0u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned
long);
Documentation/clk.txt the operations defined in clk.h:
Quoted 3 lines
Documentation/clk.txt +3
-0+ int (*set_rate_and_parent)(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, u8
index);
Quoted 108 lines
Documentation/clk.txt +0
-0void (*init)(struct clk_hw *hw); };drivers/clk/clk.c +43
-19@@ -1121,10 +1121,9 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent) clk->parent = new_parent; } -static int __clk_set_parent (struct clk *clk,struct clk *parent,u8 p_index) +static struct clk *__clk_set_parent_before(struct clk *clk,struct clk *parent) {unsigned long flags; -int ret =0 ;struct clk *old_parent = clk->parent;/* @@ -1155,6 +1154,34 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) clk_reparent(clk, parent);clk_enable_unlock (flags); +return old_parent; +} + +static void __clk_set_parent_after (struct clk *clk,struct clk *parent, +struct clk *old_parent) +{ +/* +* Finish the migration of prepare state and undo the changes done +* for preventing a race with clk_enable(). +*/ +if (clk->prepare_count) { +clk_disable (clk); +clk_disable (old_parent); +__clk_unprepare (old_parent); + } + +/* update debugfs with new clk tree topology */ +clk_debug_reparent (clk, parent); +} + +static int __clk_set_parent (struct clk *clk,struct clk *parent,u8 p_index) +{ +unsigned long flags; +int ret =0 ; +struct clk *old_parent; + + old_parent =__clk_set_parent_before (clk, parent); +/* change clock input source */ if (parent && clk->ops->set_parent) ret = clk->ops->set_parent (clk->hw, p_index);@@ -1172,18 +1199,8 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) return ret; } -/* -* Finish the migration of prepare state and undo the changes done -* for preventing a race with clk_enable(). -*/ -if (clk->prepare_count) { -clk_disable (clk); -clk_disable (old_parent); -__clk_unprepare (old_parent); - } +__clk_set_parent_after (clk, parent, old_parent); -/* update debugfs with new clk tree topology */ -clk_debug_reparent (clk, parent);return 0 ; }@@ -1368,17 +1385,32 @@ static void clk_change_rate(struct clk *clk)struct clk *child;unsigned long old_rate;unsigned long best_parent_rate =0 ; +bool skip_set_rate = false; +struct clk *old_parent; old_rate = clk->rate; -/* set parent */ -if (clk->new_parent && clk->new_parent != clk->parent) -__clk_set_parent (clk, clk->new_parent, clk- new_parent_index); - -if (clk->parent) +if (clk->new_parent) + best_parent_rate = clk->new_parent->rate; +else if (clk->parent) best_parent_rate = clk->parent->rate; -if (clk->ops->set_rate) +if (clk->new_parent && clk->new_parent != clk->parent) { + old_parent =__clk_set_parent_before (clk, clk- new_parent); + +if (clk->ops->set_rate_and_parent) { + skip_set_rate = true; + clk->ops->set_rate_and_parent (clk->hw, clk- new_rate, + best_parent_rate, + clk->new_parent_index); + }else if (clk->ops->set_parent) { + clk->ops->set_parent(clk->hw, clk-
new_parent_index);
drivers/clk/clk.c static void clk_change_rate(struct clk *clk)
Quoted 7 lines
drivers/clk/clk.c +6
-0+ } + +__clk_set_parent_after (clk, clk->new_parent, old_parent); + } + +if (!skip_set_rate && clk->ops->set_rate) clk->ops->set_rate(clk->hw, clk->new_rate,
best_parent_rate);
drivers/clk/clk.c int __clk_init(struct device *dev, struct clk · line 1701
Quoted 9 lines
drivers/clk/clk.c +3
-0if (clk->ops->recalc_rate)@@ -1664,6 +1696,14 @@ int __clk_init(struct device *dev, struct clk *clk) goto out; } +if (clk->ops->set_rate_and_parent && + !(clk->ops->set_parent && clk->ops->set_rate)) { + pr_warning("%s: %s must implement .set_parent &
.set_rate\n",
Quoted 17 lines
drivers/clk/clk.c +5
-0+ __func__, clk->name); + ret = -EINVAL ; + goto out; + } +/* throw a WARN if any entries in parent_names are NULL */ for (i =0 ; i < clk->num_parents; i++) WARN(!clk->parent_names[i],include/linux/clk-provider.h +1
-0@@ -108,6 +108,18 @@ struct clk_hw;* which is likely helpful for most .set_rate implementation. * Returns 0 on success, -EERROR otherwise. * +* @set_rate_and_parent: Change the rate and the parent of this clock.
Quoted 1 line
The + * requested rate is specified by the second
argument, which +
Quoted 2 lines
* should typically be the return of .round_rate call. The
+ * third argument gives the parent rate which is likely
helpful
Quoted 4 lines
+ * for most .set_rate_and_parent implementation. The fourth
+ * argument gives the parent index. It is optional (and
+ * unnecessary) for clocks with 0 or 1 parents as well as
+ * for clocks that can tolerate switching the rate and the
parent
Quoted 16 lines
+ * separately via calls to .set_parent and .set_rate.
+ * Returns 0 on success,-EERRORotherwise.
+ *
+ *
* The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
* implementations to split any work between atomic (enable) and sleepable * (prepare) contexts. If enabling a clock requires code that might sleep, @@ -139,6 +151,9 @@ structclk_ops{include/linux/clk-provider.h +3
-0u8 (*get_parent)(struct clk_hw *hw);int (*set_rate)(struct clk_hw *hw,unsigned long ,unsigned long ); +int (*set_rate_and_parent)(struct clk_hw *hw, +unsigned long rate, +unsigned long parent_rate,u8 index);void (*init)(struct clk_hw *hw); };
Re: [PATCH v1 04/14] clk: Add set_rate_and_parent() op
Quoted 10 lines · Tomasz Figa
Quoted 8 lines · On Wednesday 24 of July 2013 17:43:32 Stephen Boyd wrote:
Some of Qualcomm's clocks can change their parent and rate at the same time with a single register write. Add support for this hardware to the common clock framework by adding a new
set_rate_and_parent()op. When the clock framework determines that both the parent and the rate are going to change duringclk_set_rate()it will call the .set_rate_and_parent() op if available and fall back to calling .set_parent() followed by .set_rate() otherwise.
Quoted 2 lines
This is strange. Does you hardware support switching parent and rate separately or you always need to set both and so all the fuss here?
It supports setting the parent or setting the rate, or setting both at the same time.
Quoted 4 lines
If the latter is the case, then maybe you can simply keep parent index and rate cached inside driver data of your clock driver and use them on any .set_rate() or .set_parent() calls?
This will not work. In fact, doing that would cause us to overclock hardware for a short time between switching the parent and the rate.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 04/14] clk: Add set_rate_and_parent() op
Quoting Stephen Boyd (2013-07-25 09:45:42)
Quoted 11 lines · Tomasz Figa
Quoted 10 lines · On Wednesday 24 of July 2013 17:43:32 Stephen Boyd wrote:
Quoted 8 lines
Some of Qualcomm's clocks can change their parent and rate at the same time with a single register write. Add support for this hardware to the common clock framework by adding a new
set_rate_and_parent()op. When the clock framework determines that both the parent and the rate are going to change duringclk_set_rate()it will call the .set_rate_and_parent() op if available and fall back to calling .set_parent() followed by .set_rate() otherwise.
Quoted 5 lines
Quoted 2 lines
This is strange. Does you hardware support switching parent and rate separately or you always need to set both and so all the fuss here?
It supports setting the parent or setting the rate, or setting both at the same time.
I think that setting parent and rate at the same time is a common enough case to merit handling it in the clock core. Probably this design will become more common in time.
Regards,
Mike
Quoted 13 lines
Quoted 5 lines
If the latter is the case, then maybe you can simply keep parent index and rate cached inside driver data of your clock driver and use them on any .set_rate() or .set_parent() calls?
This will not work. In fact, doing that would cause us to overclock hardware for a short time between switching the parent and the rate.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 04/14] clk: Add set_rate_and_parent() op
In reply to Stephen BoydHi Stephen,
Quoted 11 lines · Stephen Boyd
Some of Qualcomm's clocks can change their parent and rate at the same time with a single register write. Add support for this hardware to the common clock framework by adding a new
set_rate_and_parent()op. When the clock framework determines that both the parent and the rate are going to change duringclk_set_rate()it will call the .set_rate_and_parent() op if available and fall back to calling .set_parent() followed by .set_rate() otherwise.Cc James Hogan <[email protected]>Signed-off-by Stephen Boyd <[email protected]>
Aside from the nit below, I can't see anything wrong with this patch.
Quoted 5 lines
include/linux/clk-provider.h +0
-0
include/linux/clk-provider.h struct clk_hw; · line 116
Quoted 9 lines
include/linux/clk-provider.h +6
-0@@ -108,6 +108,18 @@ struct clk_hw;* which is likely helpful for most .set_rate implementation. * Returns 0 on success, -EERROR otherwise. * +* @set_rate_and_parent: Change the rate and the parent of this clock. The +* requested rate is specified by the second argument, which +* should typically be the return of .round_rate call. The +* third argument gives the parent rate which is likely helpful +* for most .set_rate_and_parent implementation. The fourth +* argument gives the parent index. It is optional (and
nit: s/It/This callback/ or add newline or something - I completely misread it the first time, thinking you were referring to the parent index argument :)
include/linux/clk-provider.h struct clk_hw; · line 125
Quoted 9 lines
include/linux/clk-provider.h +6
-0+* unnecessary) for clocks with 0 or 1 parents as well as +* for clocks that can tolerate switching the rate and the parent +* separately via calls to .set_parent and .set_rate. +* Returns 0 on success, -EERROR otherwise. +* +* * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow * implementations to split any work between atomic (enable) and sleepable * (prepare) contexts. If enabling a clock requires code that might sleep,
Thanks
James
PATCH 5/14 clk: msm: Add support for phase locked loops (PLLs)
In reply to Stephen BoydAdd support for MSM's PLLs (phase locked loops). This is sufficient enough to be able to determine the rate the PLL is running at. We can add rate setting support later when it's needed.
--- Documentation/devicetree/bindings/clock/msm.txt | 40 ++++ drivers/clk/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/msm/Kconfig | 4 + drivers/clk/msm/Makefile | 3 + drivers/clk/msm/clk-pll.c | 233 ++++++++++++++++++++++++ drivers/clk/msm/clk-pll.h | 43 +++++ 7 files changed, 326 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/msm.txt create mode 100644 drivers/clk/msm/Kconfig create mode 100644 drivers/clk/msm/Makefile create mode 100644 drivers/clk/msm/clk-pll.c create mode 100644 drivers/clk/msm/clk-pll.h
Documentation/devicetree/bindings/clock/msm.txt new file +40 -0
@@ -0,0 +1,40 @@ +Bindings for Qualcomm's clock controllers + +These bindings use the common clock binding +Documentation/devicetree/bindings/clock/clock-bindings.txt + +PLL Binding +----------- + +Required properties: +- compatible : shall be "qcom,pll". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : from common clock binding; shall be set to the reference clock + +Example: + pll8: pll8 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + +Voteable PLL Binding +-------------------- + +Voteable PLLs are PLLs surrounded by a voting wrapper that aggregates +votes from multiple masters in the system and enables or disables the +PLL according to the current vote. + +Required properties: +- compatible: shall be "qcom,pll-vote" +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : from common clock binding; shall be set to the pll that is wrapped + in voting logic + +Example: + vpll8: vpll8 { + #clock-cells = <0>; + compatible = "qcom,pll-vote"; + clocks = <&pll8>; + }; +
drivers/clk/Kconfig +2 -0
@@ -87,6 +87,8 @@ config CLK_PPC_CORENET This adds the clock driver support for Freescale PowerPC corenet platforms using common clock framework. +source "drivers/clk/msm/Kconfig" + endmenu source "drivers/clk/mvebu/Kconfig"
drivers/clk/Makefile +1 -0
@@ -20,6 +20,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o +obj-$(CONFIG_COMMON_CLK_MSM) += msm/ obj-$(CONFIG_PLAT_ORION) += mvebu/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/
drivers/clk/msm/Kconfig new file +4 -0
@@ -0,0 +1,4 @@ +menuconfig COMMON_CLK_MSM + tristate "Support for Qualcomm's MSM designs" + depends on OF +
drivers/clk/msm/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +obj-$(CONFIG_COMMON_CLK_MSM) += clk-msm.o + +clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o
drivers/clk/msm/clk-pll.c new file +233 -0
233 lines not on this page · raw message
drivers/clk/msm/clk-pll.h new file +43 -0
43 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 05/14] clk: msm: Add support for phase locked loops (PLLs)
Hi Stephen,
Quoted 22 lines · On Wednesday 24 of July 2013 17:43:33 Stephen Boyd wrote:
Add support for MSM's PLLs (phase locked loops). This is sufficient enough to be able to determine the rate the PLL is running at. We can add rate setting support later when it's needed.
Cc devicetree at vger.kernel.orgSigned-off-by Stephen Boyd <[email protected]>--- Documentation/devicetree/bindings/clock/msm.txt | 40 ++++ drivers/clk/Kconfig | 2 + drivers/clk/Makefile | 1 + drivers/clk/msm/Kconfig | 4 + drivers/clk/msm/Makefile | 3 + drivers/clk/msm/clk-pll.c | 233 ++++++++++++++++++++++++ drivers/clk/msm/clk-pll.h | 43 +++++ 7 files changed, 326 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/msm.txt create mode 100644 drivers/clk/msm/Kconfig create mode 100644 drivers/clk/msm/Makefile create mode 100644 drivers/clk/msm/clk-pll.c create mode 100644 drivers/clk/msm/clk-pll.h
[snip]
Quoted 44 lines
drivers/clk/msm/clk-pll.h new file +37
-0@@ -0,0 +1,43 @@ +/* +* Copyright (c) 2013, The Linux Foundation. All rights reserved. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. + * +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __MSM_CLK_PLL_H__ +#define __MSM_CLK_PLL_H__ + +struct device ; +struct clk ; +struct clk_init_data ; + +struct pll_desc { +void __iomem *base; +u16 l_reg; +u16 m_reg; +u16 n_reg; +u16 config_reg; +u16 mode_reg; +u16 status_reg; +u8 status_bit; +}; + +struct pll_vote_desc { +void __iomem *base; +u16 vote_reg; +u8 vote_bit; +}; + +extern struct clk *pll_clk_register(struct device *dev, struct pll_desc*desc, + struct
clk_init_data*init);
drivers/clk/msm/clk-pll.h line 41
Quoted 2 lines
drivers/clk/msm/clk-pll.h new file +2
-0+extern struct clk *pll_vote_clk_register (struct device *dev, +struct pll_vote_desc *desc,struct clk_init_data *init);
I don't think such generic name is good here. What about prefixing them with msm_ or qcom_ string?
Best regards,
Tomasz
Re: [PATCH v1 05/14] clk: msm: Add support for phase locked loops (PLLs)
Quoted 9 lines · Tomasz Figa
drivers/clk/msm/clk-pll.h line 41
Quoted 4 lines · On Wednesday 24 of July 2013 17:43:33 Stephen Boyd wrote:
+extern struct clk *pll_clk_register(struct device *dev, struct
pll_desc
*desc, + structclk_init_data*init);drivers/clk/msm/clk-pll.h new file +2
-0+extern struct clk *pll_vote_clk_register (struct device *dev, +struct pll_vote_desc *desc,struct clk_init_data *init);I don't think such generic name is good here. What about prefixing them with
msm_orqcom_string?
Sure.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 6/14 clk: msm: Add support for root clock generators (RCGs)
In reply to Stephen Boyd--- Documentation/devicetree/bindings/clock/msm.txt | 31 + drivers/clk/msm/Makefile | 2 + drivers/clk/msm/clk-rcg.c | 754 ++++++++++++++++++++++++ drivers/clk/msm/clk-rcg.h | 114 ++++ drivers/clk/msm/clk-rcg2.c | 320 ++++++++++ 5 files changed, 1221 insertions(+) create mode 100644 drivers/clk/msm/clk-rcg.c create mode 100644 drivers/clk/msm/clk-rcg.h create mode 100644 drivers/clk/msm/clk-rcg2.c
Documentation/devicetree/bindings/clock/msm.txt +31 -0
@@ -38,3 +38,34 @@ Example: clocks = <&pll8>; }; +M/N:D Binding +------------- + +Required properties: +- compatible : shall be one of "qcom,p2-mn16-clock" or "qcom,p2-mn8-clock" +- #clock-cells : from common clock binding; shall be set to 0 +- clocks : from common clock binding; shall be set of muxed input sources + +Example: + gsbi5_uart_rcg: gsbi5_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&pll8>; + }; + +M/N:D Dynamic Binding +--------------------- + +Required properties: +- compatible : shall be one of "qcom,mn4-dyn-clock", "qcom,mn8-dyn-clock" or + "qcom,p4-dyn-clock". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : from common clock binding; shall be set of muxed input sources + +Example: + gfx2d_rcg : gfx2d_rcg { + #clock-cells = <0>; + compatible = "qcom,mn4-dyn-clock"; + clocks = <&pxo>, <&pll2>, <&pll8>; + }; +
drivers/clk/msm/Makefile +2 -0
@@ -1,3 +1,5 @@ obj-$(CONFIG_COMMON_CLK_MSM) += clk-msm.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o +clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o +clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o
drivers/clk/msm/clk-rcg.c new file +754 -0
754 lines not on this page · raw message
drivers/clk/msm/clk-rcg.h new file +114 -0
114 lines not on this page · raw message
drivers/clk/msm/clk-rcg2.c new file +320 -0
320 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 7/14 clk: msm: Add support for branches/gate clocks
In reply to Stephen Boyd--- Documentation/devicetree/bindings/clock/msm.txt | 28 ++++ drivers/clk/msm/Makefile | 1 + drivers/clk/msm/clk-branch.c | 190 ++++++++++++++++++++++++ drivers/clk/msm/clk-branch.h | 48 ++++++ 4 files changed, 267 insertions(+) create mode 100644 drivers/clk/msm/clk-branch.c create mode 100644 drivers/clk/msm/clk-branch.h
Documentation/devicetree/bindings/clock/msm.txt +28 -0
@@ -69,3 +69,31 @@ Example: clocks = <&pxo>, <&pll2>, <&pll8>; }; +CXC Binding +----------- + +Required properties: +- compatible : shall be "qcom,cxc-clock". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : from common clock binding; shall be set to the source being gated + +Example: + gsbi5_uart_clk: gsbi5_uart_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_uart_rcg>; + }; + +CXC With Hardware Gating Binding +-------------------------------- + +Required properties: +- compatible : shall be "qcom,cxc-hg-clock". +- #clock-cells : from common clock binding; shall be set to 0. +- clocks : from common clock binding; shall be set to the source being gated + + gsbi5_uart_ahb: gsbi5_uart_ahb { + #clock-cells = <0>; + compatible = "qcom,cxc-hg-clock"; + clocks = <&cfpb_clk>; + };
drivers/clk/msm/Makefile +1 -0
@@ -3,3 +3,4 @@ obj-$(CONFIG_COMMON_CLK_MSM) += clk-msm.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o +clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o
drivers/clk/msm/clk-branch.c new file +190 -0
190 lines not on this page · raw message
drivers/clk/msm/clk-branch.h new file +48 -0
48 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 8/14 clk: msm: Add MSM clock driver
In reply to Stephen BoydAdd a clock driver that registers clocks from a DT node's 'clocks' child. Each new SoC will add a file describing the software interface and frequency plan to drivers/clk/msm/ and then hook that into the msm_cc_match_table by means of a compatible string and an msm_clk_match table.
--- drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 265 +++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/msm/internal.h | 24 ++++ 3 files changed, 291 insertions(+) create mode 100644 drivers/clk/msm/core.c create mode 100644 drivers/clk/msm/internal.h
drivers/clk/msm/Makefile +2 -0
@@ -4,3 +4,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o + +clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.o
drivers/clk/msm/core.c new file +265 -0
265 lines not on this page · raw message
drivers/clk/msm/internal.h new file +24 -0
@@ -0,0 +1,24 @@ +/* +* Copyright (c) 2013, The Linux Foundation. All rights reserved. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __MSM_CLK_INTERNAL_H__ +#define __MSM_CLK_INTERNAL_H__ + +struct of_clk_match ; + +struct msm_clk_match { +struct of_clk_match *matches; +size_t size; +}; + +#endif
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 08/14] clk: msm: Add MSM clock driver
Hi Stephen,
Quoted 63 lines · On Wednesday 24 of July 2013 17:43:36 Stephen Boyd wrote:
Add a clock driver that registers clocks from a DT node's 'clocks' child. Each new SoC will add a file describing the software interface and frequency plan to
drivers/clk/msm/and then hook that into themsm_cc_match_tableby means of a compatible string and anmsm_clk_matchtable.Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 265 +++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/msm/internal.h | 24 ++++ 3 files changed, 291 insertions(+) create mode 100644 drivers/clk/msm/core.c create mode 100644 drivers/clk/msm/internal.hdrivers/clk/msm/Makefile +2
-0@@ -4,3 +4,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o + +clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.odrivers/clk/msm/core.c new file +31
-0@@ -0,0 +1,265 @@ +/* +* Copyright (c) 2013, The Linux Foundation. All rights reserved. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. + * +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/spinlock.h> + +#include "internal.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" + +struct cc_data { +void __iomem *base; +spinlock_t lock; +}; + +static struct clk *
drivers/clk/msm/core.c line 41
Quoted 10 lines
drivers/clk/msm/core.c new file +10
-0+dispatch_fixed_clk(struct of_clk_match *m, struct device *dev, + struct cc_data *cc) +{ + u32 rate; +const char *name = m->init_data->name; + +if (of_property_read_u32 (m->of_node,"clock-frequency" , &rate)) +return ERR_PTR (-EINVAL ); + + return clk_register_fixed_rate(dev, name, NULL, CLK_IS_ROOT,
rate);
Quoted 108 lines
drivers/clk/msm/core.c new file +33
-0+} + +static struct clk * +dispatch_pll_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct pll_desc *desc = m->driver_data; + + desc->base = cc->base; + +return pll_clk_register (dev, desc, m->init_data); +} + +static struct clk * +dispatch_pll_vote_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct pll_vote_desc *desc = m->driver_data; + + desc->base = cc->base; + +return pll_vote_clk_register (dev, desc, m->init_data); +} + +static struct clk * +dispatch_rcg_p2mn16_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct rcg_desc *desc = m->driver_data; + + desc->base = cc->base; + + return rcg_p2mn16_clk_register(dev, desc, &cc->lock, m-
init_data);drivers/clk/msm/core.c new file +15
-0+} + +static struct clk * +dispatch_rcg_p2mn8_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct rcg_desc *desc = m->driver_data; + + desc->base = cc->base; + +return rcg_p2mn8_clk_register (dev, desc, &cc->lock, m->init_data); +} + +static struct clk * +dispatch_rcg_mn8_dyn_clk(struct of_clk_match *match, struct device*dev, + struct
cc_data*cc)drivers/clk/msm/core.c new file +30
-0+{ +struct rcg_dyn_desc *desc = match->driver_data; + + desc->base = cc->base; + +return rcg_mn8_dyn_clk_register (dev, desc, &cc->lock, + match->init_data); +} + +static struct clk * +dispatch_rcg_p4_dyn_clk (struct of_clk_match *match,struct device *dev, +struct cc_data *cc) +{ +struct rcg_dyn_desc *desc = match->driver_data; + + desc->base = cc->base; + +return rcg_p4_dyn_clk_register (dev, desc, &cc->lock, + match->init_data); +} + +static struct clk * +dispatch_rcg_h5mn8_clk (struct of_clk_match *match,struct device *dev, +struct cc_data *cc) +{ +struct rcg2_desc *desc = match->driver_data; + + desc->base = cc->base; + + return rcg_h5mn8_clk_register(dev, desc, &cc->lock, match-
init_data);drivers/clk/msm/core.c new file +11
-0+} + +static struct clk * +dispatch_rcg_h5mn16_clk (struct of_clk_match *match,struct device *dev, +struct cc_data *cc) +{ +struct rcg2_desc *desc = match->driver_data; + + desc->base = cc->base; + + return rcg_h5mn16_clk_register(dev, desc, &cc->lock,
match->init_data); +}drivers/clk/msm/core.c new file +15
-0+ +static struct clk * +dispatch_branch_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct branch_desc *desc = m->driver_data; + + desc->base = cc->base; + +return branch_clk_register (dev, desc, &cc->lock, m->init_data); +} + +static struct clk * +dispatch_branch_hg_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc)
drivers/clk/msm/core.c line 158
Quoted 10 lines
drivers/clk/msm/core.c new file +10
-0+{ +struct branch_desc *desc = m->driver_data; + + desc->base = cc->base; + +return branch_hg_clk_register (dev, desc, &cc->lock, m->init_data); +} + +static const struct of_device_id dispatch_table[] = { + { .compatible ="fixed-clock" , .data = dispatch_fixed_clk },
This is already handled by the fixed-rate-clock driver and of_clk_init().
drivers/clk/msm/core.c
Quoted 3 lines
drivers/clk/msm/core.c new file +3
-0+ { .compatible = "qcom,pll", .data = dispatch_pll_clk }, + { .compatible = "qcom,pll-vote", .data = dispatch_pll_vote_clk }, + { .compatible = "qcom,p2-mn8-clock", .data =
dispatch_rcg_p2mn8_clk },
drivers/clk/msm/core.c
Quoted 1 line
drivers/clk/msm/core.c new file +1
-0+ { .compatible = "qcom,p2-mn16-clock", .data =
dispatch_rcg_p2mn16_clk
Quoted 4 lines
}, + { .compatible = "qcom,mn8-dyn-clock", .data =
dispatch_rcg_mn8_dyn_clk}, + { .compatible = "qcom,p4-dyn-clock",
.data =dispatch_rcg_p4_dyn_clk}, + { .compatible =
"qcom,h5-mn8-clock", .data =dispatch_rcg_h5mn8_clk}, + {
.compatible
Quoted 4 lines
= "qcom,h5-mn16-clock", .data =
dispatch_rcg_h5mn16_clk}, + {
.compatible = "qcom,cxc-clock", .data =dispatch_branch_clk}, + {
.compatible = "qcom,cxc-hg-clock", .data =dispatch_branch_hg_clk}, +};
You can avoid all the code above by using OF_CLK_DECLARE() and of_clk_init().
Quoted 75 lines
drivers/clk/msm/core.c new file +75
-0+typedef struct clk * +(*clk_dispatch_fn )(struct of_clk_match *m,struct device *dev, +struct cc_data *cc); + +static const struct of_device_id msm_cc_match_table[] = { + { } +}; +MODULE_DEVICE_TABLE (of, msm_cc_match_table); + +static int msm_cc_probe (struct platform_device *pdev) +{ +struct cc_data *cc; +void __iomem *base; +struct resource *res; +int count, i; +const struct of_device_id *id_entry; +const struct msm_clk_match *m; +struct of_clk_match *matches; +size_t size; + + id_entry =of_match_device (msm_cc_match_table, &pdev->dev); + m = id_entry->data; + matches = m->matches; + size = m->size; + + cc =devm_kzalloc (&pdev->dev,sizeof (*cc),GFP_KERNEL ); +if (!cc) +return -ENOMEM ; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (base)) +return PTR_ERR (base); + + cc->base = base; +spin_lock_init (&cc->lock); + + count =of_clk_match (&pdev->dev, matches, size); +if (count <0 ) +return count; + +for (i =0 ; i < size; i++) { +struct of_clk_match *match; +const struct of_device_id *id; +struct device_node *np; +clk_dispatch_fn fn; +struct clk *clk; +int err; + + match = &matches[i]; + np = match->of_node; +if (!np) +continue ; + + id =of_match_node (dispatch_table, match->of_node); +if (!id) +continue ; + + fn = id->data; + clk =fn (match, &pdev->dev, cc); +if (IS_ERR (clk)) +return PTR_ERR (clk); + + err =of_clk_add_provider (np, of_clk_src_simple_get, clk); +if (err) +return err; + } + +return 0 ; +} + +static struct platform_driver msm_cc_driver = { + .probe = msm_cc_probe, + .driver = { + .name ="msm-clock" ,
drivers/clk/msm/core.c line 255
Quoted 10 lines
drivers/clk/msm/core.c new file +10
-0+ .owner = THIS_MODULE, + .of_match_table = msm_cc_match_table, + }, +}; + +static int __init msm_cc_init (void ) +{ +return platform_driver_register (&msm_cc_driver); +} +core_initcall (msm_cc_init);
I might be saying something stupid, but is it okay for a removable module to have a core_initcall?
Best regards,
Tomasz
Re: [PATCH v1 08/14] clk: msm: Add MSM clock driver
Quoted 187 lines · Tomasz Figa
Quoted 63 lines · On Wednesday 24 of July 2013 17:43:36 Stephen Boyd wrote:
Add a clock driver that registers clocks from a DT node's 'clocks' child. Each new SoC will add a file describing the software interface and frequency plan to
drivers/clk/msm/and then hook that into themsm_cc_match_tableby means of a compatible string and anmsm_clk_matchtable.Signed-off-by Stephen Boyd <[email protected]>--- drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 265 +++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/msm/internal.h | 24 ++++ 3 files changed, 291 insertions(+) create mode 100644 drivers/clk/msm/core.c create mode 100644 drivers/clk/msm/internal.hdrivers/clk/msm/Makefile +2
-0@@ -4,3 +4,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o + +clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.odrivers/clk/msm/core.c new file +31
-0@@ -0,0 +1,265 @@ +/* +* Copyright (c) 2013, The Linux Foundation. All rights reserved. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. + * +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/spinlock.h> + +#include "internal.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" + +struct cc_data { +void __iomem *base; +spinlock_t lock; +}; + +static struct clk *drivers/clk/msm/core.c line 41
Quoted 10 lines
drivers/clk/msm/core.c new file +10
-0+dispatch_fixed_clk(struct of_clk_match *m, struct device *dev, + struct cc_data *cc) +{ + u32 rate; +const char *name = m->init_data->name; + +if (of_property_read_u32 (m->of_node,"clock-frequency" , &rate)) +return ERR_PTR (-EINVAL ); + + return clk_register_fixed_rate(dev, name, NULL, CLK_IS_ROOT,rate);
Quoted 112 lines
drivers/clk/msm/core.c new file +33
-0+} + +static struct clk * +dispatch_pll_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct pll_desc *desc = m->driver_data; + + desc->base = cc->base; + +return pll_clk_register (dev, desc, m->init_data); +} + +static struct clk * +dispatch_pll_vote_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct pll_vote_desc *desc = m->driver_data; + + desc->base = cc->base; + +return pll_vote_clk_register (dev, desc, m->init_data); +} + +static struct clk * +dispatch_rcg_p2mn16_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct rcg_desc *desc = m->driver_data; + + desc->base = cc->base; + + return rcg_p2mn16_clk_register(dev, desc, &cc->lock, m-
init_data);drivers/clk/msm/core.c new file +15
-0+} + +static struct clk * +dispatch_rcg_p2mn8_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct rcg_desc *desc = m->driver_data; + + desc->base = cc->base; + +return rcg_p2mn8_clk_register (dev, desc, &cc->lock, m->init_data); +} + +static struct clk * +dispatch_rcg_mn8_dyn_clk(struct of_clk_match *match, struct device*dev, + struct
cc_data*cc)drivers/clk/msm/core.c new file +30
-0+{ +struct rcg_dyn_desc *desc = match->driver_data; + + desc->base = cc->base; + +return rcg_mn8_dyn_clk_register (dev, desc, &cc->lock, + match->init_data); +} + +static struct clk * +dispatch_rcg_p4_dyn_clk (struct of_clk_match *match,struct device *dev, +struct cc_data *cc) +{ +struct rcg_dyn_desc *desc = match->driver_data; + + desc->base = cc->base; + +return rcg_p4_dyn_clk_register (dev, desc, &cc->lock, + match->init_data); +} + +static struct clk * +dispatch_rcg_h5mn8_clk (struct of_clk_match *match,struct device *dev, +struct cc_data *cc) +{ +struct rcg2_desc *desc = match->driver_data; + + desc->base = cc->base; + + return rcg_h5mn8_clk_register(dev, desc, &cc->lock, match-
init_data);drivers/clk/msm/core.c new file +11
-0+} + +static struct clk * +dispatch_rcg_h5mn16_clk (struct of_clk_match *match,struct device *dev, +struct cc_data *cc) +{ +struct rcg2_desc *desc = match->driver_data; + + desc->base = cc->base; + + return rcg_h5mn16_clk_register(dev, desc, &cc->lock,
match->init_data); +}drivers/clk/msm/core.c new file +19
-0+ +static struct clk * +dispatch_branch_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct branch_desc *desc = m->driver_data; + + desc->base = cc->base; + +return branch_clk_register (dev, desc, &cc->lock, m->init_data); +} + +static struct clk * +dispatch_branch_hg_clk (struct of_clk_match *m,struct device *dev, +struct cc_data *cc) +{ +struct branch_desc *desc = m->driver_data; + + desc->base = cc->base;
Quoted 8 lines
drivers/clk/msm/core.c line 158
Quoted 6 lines
drivers/clk/msm/core.c new file +6
-0+ +return branch_hg_clk_register (dev, desc, &cc->lock, m->init_data); +} + +static const struct of_device_id dispatch_table[] = { + { .compatible ="fixed-clock" , .data = dispatch_fixed_clk },This is already handled by the fixed-rate-clock driver and
of_clk_init().
I don't plan to use of_clk_init() because I have actual device drivers.
Quoted 11 lines
drivers/clk/msm/core.c
Quoted 4 lines
drivers/clk/msm/core.c new file +3
-0+ { .compatible = "qcom,pll", .data = dispatch_pll_clk }, + { .compatible = "qcom,pll-vote", .data = dispatch_pll_vote_clk }, + { .compatible = "qcom,p2-mn8-clock", .data =
dispatch_rcg_p2mn8_clk},drivers/clk/msm/core.c
Quoted 1 line
drivers/clk/msm/core.c new file +1
-0+ { .compatible = "qcom,p2-mn16-clock", .data =
dispatch_rcg_p2mn16_clkQuoted 4 lines
}, + { .compatible = "qcom,mn8-dyn-clock", .data =
dispatch_rcg_mn8_dyn_clk}, + { .compatible = "qcom,p4-dyn-clock",
.data =dispatch_rcg_p4_dyn_clk}, + { .compatible =
"qcom,h5-mn8-clock", .data =dispatch_rcg_h5mn8_clk}, + {
Quoted 8 lines
.compatible
Quoted 4 lines
= "qcom,h5-mn16-clock", .data =
dispatch_rcg_h5mn16_clk}, + {
.compatible = "qcom,cxc-clock", .data =dispatch_branch_clk}, + {
.compatible = "qcom,cxc-hg-clock", .data =dispatch_branch_hg_clk}, +};You can avoid all the code above by using
OF_CLK_DECLARE()andof_clk_init().
As stated earlier that won't work because I want a struct device.
Quoted 10 lines
drivers/clk/msm/core.c line 255
Quoted 6 lines
drivers/clk/msm/core.c new file +6
-0+ +static int __init msm_cc_init (void ) +{ +return platform_driver_register (&msm_cc_driver); +} +core_initcall (msm_cc_init);I might be saying something stupid, but is it okay for a removable module to have a
core_initcall?
If its compiled as a module the core_initcall becomes a module_initcall(). It's here because I need the clocks before the serial driver probes. If clocks supported deferred probing this wouldn't be necessary and we could use module_platform_driver().
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 9/14 clk: msm: Add support for MSM8960's global clock controller (GCC)
In reply to Stephen BoydFill in the data and wire up the global clock controller to the MSM clock driver. This should allow most non-multimedia device drivers to control their clocks on 8960 based platforms.
--- .../devicetree/bindings/clock/qcom,gcc.txt | 55 +++++++ drivers/clk/msm/Kconfig | 10 ++ drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/gcc-8960.c | 174 +++++++++++++++++++++ drivers/clk/msm/internal.h | 2 + 6 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt create mode 100644 drivers/clk/msm/gcc-8960.c
Documentation/devicetree/bindings/clock/qcom,gcc.txt new file +55 -0
@@ -0,0 +1,55 @@ +MSM Global Clock Controller Binding +----------------------------------- + +Required properties : +- compatible : shall contain at least "qcom,gcc" and only one of the + following: + + "qcom,gcc-8660" + "qcom,gcc-8960" + +- reg : shall contain base register location and length +- clocks : shall contain clocks supplied by the clock controller + +Example: + clock-controller at 900000 { + compatible = "qcom,gcc-8960", "qcom,gcc"; + reg = <0x900000 0x4000>; + + clocks { + pxo: pxo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + pll8: pll8 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + vpll8: vpll8 { + #clock-cells = <0>; + compatible = "qcom,pll-vote"; + clocks = <&pll8>; + }; + + gsbi5_uart_rcg: gsbi5_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi5_uart_clk: gsbi5_uart_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_uart_rcg>; + }; + + gsbi5_uart_ahb: gsbi5_uart_ahb { + #clock-cells = <0>; + compatible = "qcom,cxc-hg-clock"; + }; + }; + };
drivers/clk/msm/Kconfig +10 -0
@@ -2,3 +2,13 @@ menuconfig COMMON_CLK_MSM tristate "Support for Qualcomm's MSM designs" depends on OF +if COMMON_CLK_MSM + +config MSM_GCC_8960 + bool "MSM8960 Global Clock Controller" + help + Support for the global clock controller on msm8960 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + i2c, USB, SD/eMMC, SATA, PCIe, etc. + +endif
drivers/clk/msm/Makefile +2 -0
@@ -6,3 +6,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.o + +clk-msm-$(CONFIG_MSM_GCC_8960) += gcc-8960.o
drivers/clk/msm/core.c +3 -0
@@ -173,6 +173,9 @@ typedef struct clk * struct cc_data *cc);static const struct of_device_id msm_cc_match_table[] = { +#ifdef CONFIG_MSM_GCC_8960 + { .compatible ="qcom,gcc-8960" , .data = &msm_gcc_8960_matches }, +#endif { } };MODULE_DEVICE_TABLE (of, msm_cc_match_table);
drivers/clk/msm/gcc-8960.c new file +174 -0
174 lines not on this page · raw message
drivers/clk/msm/internal.h +2 -0
@@ -21,4 +21,6 @@ struct msm_clk_match { size_t size; }; +extern const struct msm_clk_match msm_gcc_8960_matches; +#endif
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 09/14] clk: msm: Add support for MSM8960's global clock controller (GCC)
Hi Stephen,
Quoted 68 lines · Stephen Boyd
Fill in the data and wire up the global clock controller to the MSM clock driver. This should allow most non-multimedia device drivers to control their clocks on 8960 based platforms.
Cc devicetree at vger.kernel.orgSigned-off-by Stephen Boyd <[email protected]>--- .../devicetree/bindings/clock/qcom,gcc.txt | 55 +++++++ drivers/clk/msm/Kconfig | 10 ++ drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/gcc-8960.c | 174 +++++++++++++++++++++ drivers/clk/msm/internal.h | 2 + 6 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt create mode 100644 drivers/clk/msm/gcc-8960.cDocumentation/devicetree/bindings/clock/qcom,gcc.txt new file +45
-0@@ -0,0 +1,55 @@ +MSM Global Clock Controller Binding +----------------------------------- + +Required properties : +- compatible : shall contain at least "qcom,gcc" and only one of the + following: + + "qcom,gcc-8660" + "qcom,gcc-8960" + +- reg : shall contain base register location and length +- clocks : shall contain clocks supplied by the clock controller + +Example: + clock-controller at 900000 { + compatible = "qcom,gcc-8960", "qcom,gcc"; + reg = <0x900000 0x4000>; + + clocks { + pxo: pxo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + pll8: pll8 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + vpll8: vpll8 { + #clock-cells = <0>; + compatible = "qcom,pll-vote"; + clocks = <&pll8>; + }; + + gsbi5_uart_rcg: gsbi5_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi5_uart_clk: gsbi5_uart_cxc { + #clock-cells = <0>;
Documentation/devicetree/bindings/clock/qcom,gcc.txt line 55
Quoted 10 lines
Documentation/devicetree/bindings/clock/qcom,gcc.txt new file +10
-0+ compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_uart_rcg>; + }; + + gsbi5_uart_ahb: gsbi5_uart_ahb { + #clock-cells = <0>; + compatible = "qcom,cxc-hg-clock"; + }; + }; + };
I'm slightly confused by this. How is each of the clocks described in the clocks node related to a portion of the register set?
If the set of clocks is fixed, surely the gcc node gives you enough information alone, and the whole block can be modelled as a single provider of multiple clock outputs, or it's not fixed, and some linkage needs to be defined?
The code seems to imply the former, unless only a subset of clocks may be present? In that case, the set of clocks which might be present should be described in the binding.
Thanks,
Mark.
Quoted 243 lines
drivers/clk/msm/Kconfig +10
-0@@ -2,3 +2,13 @@ menuconfig COMMON_CLK_MSM tristate "Support for Qualcomm's MSM designs" depends on OF +if COMMON_CLK_MSM + +config MSM_GCC_8960 + bool "MSM8960 Global Clock Controller" + help + Support for the global clock controller on msm8960 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + i2c, USB, SD/eMMC, SATA, PCIe, etc. + +endifdrivers/clk/msm/Makefile +2
-0@@ -6,3 +6,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.o + +clk-msm-$(CONFIG_MSM_GCC_8960) += gcc-8960.odrivers/clk/msm/core.c +3
-0@@ -173,6 +173,9 @@ typedef struct clk * struct cc_data *cc);static const struct of_device_id msm_cc_match_table[] = { +#ifdef CONFIG_MSM_GCC_8960 + { .compatible ="qcom,gcc-8960" , .data = &msm_gcc_8960_matches }, +#endif { } };MODULE_DEVICE_TABLE (of, msm_cc_match_table);drivers/clk/msm/gcc-8960.c new file +174
-0@@ -0,0 +1,174 @@ +/* +* Copyright (c) 2013, The Linux Foundation. All rights reserved. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> + +#include "internal.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" + +static struct pll_desc pll8_desc = { + .l_reg =0x3144 , + .m_reg =0x3148 , + .n_reg =0x314c , + .config_reg =0x3154 , + .mode_reg =0x3140 , + .status_reg =0x3158 , + .status_bit =16 , +}; + +static struct pll_vote_desc pll8_vote_desc = { + .vote_reg =0x34c0 , + .vote_bit =8 , +}; + +#define PXO 0 +#define PLL8 1 + +static u8 gcc_pxo_pll8_map[] = { + [PXO ] =0 , + [PLL8 ] =3 , +}; + +static struct freq_tbl clk_tbl_gsbi_uart[] = { + {1843200 ,PLL8 ,2 ,6 ,625 }, + {3686400 ,PLL8 ,2 ,12 ,625 }, + {7372800 ,PLL8 ,2 ,24 ,625 }, + {14745600 ,PLL8 ,2 ,48 ,625 }, + {16000000 ,PLL8 ,4 ,1 ,6 }, + {24000000 ,PLL8 ,4 ,1 ,4 }, + {32000000 ,PLL8 ,4 ,1 ,3 }, + {40000000 ,PLL8 ,1 ,5 ,48 }, + {46400000 ,PLL8 ,1 ,29 ,240 }, + {48000000 ,PLL8 ,4 ,1 ,2 }, + {51200000 ,PLL8 ,1 ,2 ,15 }, + {56000000 ,PLL8 ,1 ,7 ,48 }, + {58982400 ,PLL8 ,1 ,96 ,625 }, + {64000000 ,PLL8 ,2 ,1 ,3 }, + { } +}; + +static struct rcg_desc gsbi5_uart_rcg = { + .ctl_reg =0x2a54 , + .ns_reg =0x2a54 , + .md_reg =0x2a50 , + .ctl_bit =11 , + .mnctr_en_bit =8 , + .mnctr_reset_bit =7 , + .mnctr_mode_shift =5 , + .pre_div_shift =3 , + .src_sel_shift =0 , + .n_val_shift =16 , + .m_val_shift =16 , + .parent_map = gcc_pxo_pll8_map, + .freq_tbl = clk_tbl_gsbi_uart, +}; + +static struct branch_desc gsbi5_uart_cxc = { + .ctl_reg =0x2a54 , + .halt_reg =0x2fd0 , + .ctl_bit =9 , + .halt_bit =22 , + .halt_check =BRANCH_HALT , +}; + +static struct rcg_desc gsbi6_uart_rcg = { + .ctl_reg =0x2a74 , + .ns_reg =0x2a74 , + .md_reg =0x2a70 , + .ctl_bit =11 , + .mnctr_en_bit =8 , + .mnctr_reset_bit =7 , + .mnctr_mode_shift =5 , + .pre_div_shift =3 , + .src_sel_shift =0 , + .n_val_shift =16 , + .m_val_shift =16 , + .parent_map = gcc_pxo_pll8_map, + .freq_tbl = clk_tbl_gsbi_uart, +}; + +static struct branch_desc gsbi6_uart_cxc = { + .ctl_reg =0x2a74 , + .halt_reg =0x2fd0 , + .ctl_bit =9 , + .halt_bit =18 , + .halt_check =BRANCH_HALT , +}; + +static struct branch_desc gsbi5_uart_ahb = { + .ctl_reg =0x2a40 , + .halt_reg =0x2fd0 , + .hwcg_reg =0x2a40 , + .ctl_bit =4 , + .hwcg_bit =6 , + .halt_bit =23 , + .halt_check =BRANCH_HALT , +}; + +static struct freq_tbl clk_tbl_gsbi_qup[] = { + {1100000 ,PXO ,1 ,2 ,49 }, + {5400000 ,PXO ,1 ,1 ,5 }, + {10800000 ,PXO ,1 ,2 ,5 }, + {15060000 ,PLL8 ,1 ,2 ,51 }, + {24000000 ,PLL8 ,4 ,1 ,4 }, + {25600000 ,PLL8 ,1 ,1 ,15 }, + {27000000 ,PXO ,1 ,0 ,0 }, + {48000000 ,PLL8 ,4 ,1 ,2 }, + {51200000 ,PLL8 ,1 ,2 ,15 }, + { } +}; + +static struct rcg_desc gsbi5_qup_rcg = { + .ctl_reg =0x2a4c , + .ns_reg =0x2a4c , + .md_reg =0x2a48 , + .ctl_bit =11 , + .mnctr_en_bit =8 , + .mnctr_reset_bit =7 , + .mnctr_mode_shift =5 , + .pre_div_shift =3 , + .src_sel_shift =0 , + .n_val_shift =16 , + .m_val_shift =16 , + .parent_map = gcc_pxo_pll8_map, + .freq_tbl = clk_tbl_gsbi_qup, +}; + +static struct branch_desc gsbi5_qup_cxc = { + .ctl_reg =0x2a4c , + .halt_reg =0x2fd0 , + .ctl_bit =9 , + .halt_bit =20 , + .halt_check =BRANCH_HALT , +}; + +static struct of_clk_match msm_gcc_clk_match[] = { + { .name ="cxo" }, + { .name ="pxo" }, + { .name ="pll8" , .driver_data = &pll8_desc }, + { .name ="vpll8" , .driver_data = &pll8_vote_desc }, + { .name ="gsbi5_uart_rcg" , .driver_data = &gsbi5_uart_rcg }, + { .name ="gsbi5_uart_cxc" , .driver_data = &gsbi5_uart_cxc }, + { .name ="gsbi6_uart_rcg" , .driver_data = &gsbi6_uart_rcg }, + { .name ="gsbi6_uart_cxc" , .driver_data = &gsbi6_uart_cxc }, + { .name ="gsbi5_uart_ahb" , .driver_data = &gsbi5_uart_ahb }, + { .name ="gsbi5_qup_rcg" , .driver_data = &gsbi5_qup_rcg }, + { .name ="gsbi5_qup_cxc" , .driver_data = &gsbi5_qup_cxc }, +}; + +const struct msm_clk_match msm_gcc_8960_matches = { + .matches = msm_gcc_clk_match, + .size =ARRAY_SIZE (msm_gcc_clk_match) +};drivers/clk/msm/internal.h +2
-1@@ -21,4 +21,6 @@ struct msm_clk_match { size_t size; }; +extern const struct msm_clk_match msm_gcc_8960_matches; +#endif --The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH v1 09/14] clk: msm: Add support for MSM8960's global clock controller (GCC)
Quoted 76 lines · Mark Rutland
Hi Stephen,
Quoted 73 lines · Stephen Boyd
Fill in the data and wire up the global clock controller to the MSM clock driver. This should allow most non-multimedia device drivers to control their clocks on 8960 based platforms.
Cc devicetree at vger.kernel.orgSigned-off-by Stephen Boyd <[email protected]>--- .../devicetree/bindings/clock/qcom,gcc.txt | 55 +++++++ drivers/clk/msm/Kconfig | 10 ++ drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/gcc-8960.c | 174 +++++++++++++++++++++ drivers/clk/msm/internal.h | 2 + 6 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt create mode 100644 drivers/clk/msm/gcc-8960.cDocumentation/devicetree/bindings/clock/qcom,gcc.txt new file +50
-0@@ -0,0 +1,55 @@ +MSM Global Clock Controller Binding +----------------------------------- + +Required properties : +- compatible : shall contain at least "qcom,gcc" and only one of the + following: + + "qcom,gcc-8660" + "qcom,gcc-8960" + +- reg : shall contain base register location and length +- clocks : shall contain clocks supplied by the clock controller + +Example: + clock-controller at 900000 { + compatible = "qcom,gcc-8960", "qcom,gcc"; + reg = <0x900000 0x4000>; + + clocks { + pxo: pxo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + pll8: pll8 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + vpll8: vpll8 { + #clock-cells = <0>; + compatible = "qcom,pll-vote"; + clocks = <&pll8>; + }; + + gsbi5_uart_rcg: gsbi5_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi5_uart_clk: gsbi5_uart_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_uart_rcg>; + }; + + gsbi5_uart_ahb: gsbi5_uart_ahb {
Quoted 8 lines
Documentation/devicetree/bindings/clock/qcom,gcc.txt line 55
Quoted 5 lines
Documentation/devicetree/bindings/clock/qcom,gcc.txt new file +5
-0+ #clock-cells = <0>; + compatible = "qcom,cxc-hg-clock"; + }; + }; + };I'm slightly confused by this. How is each of the clocks described in the clocks node related to a portion of the register set?
The registers to control clocks and determine their state are scattered throughout the registers in the gcc (in this example from 0x900000 to 0x903fff). If you match up gsbi5_uart_rcg with its C struct counterpart you'll notice that there are multiple registers used to configure the clock. It isn't as simple as one reg property per clock even for the case where we're just toggling a bit to turn a clock on and off either. And it isn't as simple as saying the clock has a base register that we can offset from because offsets are almost always different (we've tried to correct this in future chip versions).
Quoted 9 lines
If the set of clocks is fixed, surely the gcc node gives you enough information alone, and the whole block can be modelled as a single provider of multiple clock outputs, or it's not fixed, and some linkage needs to be defined?
The code seems to imply the former, unless only a subset of clocks may be present? In that case, the set of clocks which might be present should be described in the binding.
The clock controller is hardware and the number of clock outputs is fixed. Isn't all hardware fixed until you start talking about FPGAs? The next minor revision of the clock controller may add more clocks or remove clocks from that base design, but otherwise the two are 90% the same and generally software compatible. It isn't until we start a new generation of chips that we make major changes to the design. Is that loose enough to qualify?
These bindings attempt to follow the regulator bindings. With regulators there is a node for each regulator and we describe physical characteristics of those regulators within the nodes but we don't describe the software interface (bits, masks, shifts, etc). I imagine we could extend these clock nodes to describe physical characteristics such as min/max frequency or if the bootloader has left the clocks on. Right now we're using the nodes to describe what types of clocks there are and how the clock tree is layed out.
Or perhaps you're talking about clock sharing? We share the clock controller with multiple masters (processors running other OSes) and the partitioning of the clocks is mostly predefined. We just won't use some clocks because they're reserved for other processors. They're still part of the same clock controller hardware block but we don't want to control them on Linux because we'll trample over other processors and most likely hang the system. I wonder how this would work for hexagon and krait both running linux on the same SoC. If all DT says is that there is a gcc here at this address how are we supposed to know that we shouldn't use some clock? In fact we have some clocks that are "voteable" in the sense that each master has its own register to vote for a clock to be on or off. The registers are all ORed together by hardware to determine if the clock should be on or not. I should probably rename those clocks to have a _krait or _apps at the end so that it's clear we want to instantiate the krait version of the clock and not the hexagon version. I suppose the other solution there is to say we have gcc-8960-krait and gcc-8960-hexagon so we know which voting registers to use or put an ifdef ARCH_HEXAGON/ARCH_ARM. Is that the right solution?
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 09/14] clk: msm: Add support for MSM8960's global clock controller (GCC)
Quoting Stephen Boyd (2013-08-12 22:03:34)
Quoted 125 lines · Mark Rutland
Quoted 76 lines
Hi Stephen,
Quoted 73 lines · Stephen Boyd
Fill in the data and wire up the global clock controller to the MSM clock driver. This should allow most non-multimedia device drivers to control their clocks on 8960 based platforms.
Cc devicetree at vger.kernel.orgSigned-off-by Stephen Boyd <[email protected]>--- .../devicetree/bindings/clock/qcom,gcc.txt | 55 +++++++ drivers/clk/msm/Kconfig | 10 ++ drivers/clk/msm/Makefile | 2 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/gcc-8960.c | 174 +++++++++++++++++++++ drivers/clk/msm/internal.h | 2 + 6 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt create mode 100644 drivers/clk/msm/gcc-8960.cDocumentation/devicetree/bindings/clock/qcom,gcc.txt new file +50
-0@@ -0,0 +1,55 @@ +MSM Global Clock Controller Binding +----------------------------------- + +Required properties : +- compatible : shall contain at least "qcom,gcc" and only one of the + following: + + "qcom,gcc-8660" + "qcom,gcc-8960" + +- reg : shall contain base register location and length +- clocks : shall contain clocks supplied by the clock controller + +Example: + clock-controller at 900000 { + compatible = "qcom,gcc-8960", "qcom,gcc"; + reg = <0x900000 0x4000>; + + clocks { + pxo: pxo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + pll8: pll8 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + vpll8: vpll8 { + #clock-cells = <0>; + compatible = "qcom,pll-vote"; + clocks = <&pll8>; + }; + + gsbi5_uart_rcg: gsbi5_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi5_uart_clk: gsbi5_uart_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_uart_rcg>; + }; + + gsbi5_uart_ahb: gsbi5_uart_ahb {Quoted 8 lines
Documentation/devicetree/bindings/clock/qcom,gcc.txt line 55
Quoted 5 lines
Documentation/devicetree/bindings/clock/qcom,gcc.txt new file +5
-0+ #clock-cells = <0>; + compatible = "qcom,cxc-hg-clock"; + }; + }; + };I'm slightly confused by this. How is each of the clocks described in the clocks node related to a portion of the register set?
The registers to control clocks and determine their state are scattered throughout the registers in the gcc (in this example from
0x900000to0x903fff). If you match upgsbi5_uart_rcgwith its C struct counterpart you'll notice that there are multiple registers used to configure the clock. It isn't as simple as one reg property per clock even for the case where we're just toggling a bit to turn a clock on and off either. And it isn't as simple as saying the clock has a base register that we can offset from because offsets are almost always different (we've tried to correct this in future chip versions).Quoted 9 lines
If the set of clocks is fixed, surely the gcc node gives you enough information alone, and the whole block can be modelled as a single provider of multiple clock outputs, or it's not fixed, and some linkage needs to be defined?
The code seems to imply the former, unless only a subset of clocks may be present? In that case, the set of clocks which might be present should be described in the binding.
The clock controller is hardware and the number of clock outputs is fixed. Isn't all hardware fixed until you start talking about FPGAs? The next minor revision of the clock controller may add more clocks or remove clocks from that base design, but otherwise the two are 90% the same and generally software compatible. It isn't until we start a new generation of chips that we make major changes to the design. Is that loose enough to qualify?
These bindings attempt to follow the regulator bindings. With regulators there is a node for each regulator and we describe physical characteristics of those regulators within the nodes but we don't describe the software interface (bits, masks, shifts, etc). I imagine we could extend these clock nodes to describe physical characteristics such as min/max frequency or if the bootloader has left the clocks on. Right now we're using the nodes to describe what types of clocks there are and how the clock tree is layed out.
Quoted 11 lines
Or perhaps you're talking about clock sharing? We share the clock controller with multiple masters (processors running other OSes) and the partitioning of the clocks is mostly predefined. We just won't use some clocks because they're reserved for other processors. They're still part of the same clock controller hardware block but we don't want to control them on Linux because we'll trample over other processors and most likely hang the system. I wonder how this would work for hexagon and krait both running linux on the same SoC. If all DT says is that there is a gcc here at this address how are we supposed to know that we shouldn't use some clock?
Do Krait and Hexagon have the same register map? On the ARM SoCs I am familiar with the masters have differing views of register addresses for the same peripherals and hardware blocks. So you couldn't use the same DTS in a straightforward way if this is true for your system.
Regards,
Mike
Quoted 14 lines
In fact we have some clocks that are
"voteable" in the sense that each master has its own register to vote for a clock to be on or off. The registers are all ORed together by hardware to determine if the clock should be on or not. I should probably rename those clocks to have a_kraitor_appsat the end so that it's clear we want to instantiate the krait version of the clock and not the hexagon version. I suppose the other solution there is to say we have gcc-8960-krait and gcc-8960-hexagon so we know which voting registers to use or put an ifdef ARCH_HEXAGON/ARCH_ARM. Is that the right solution?Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 09/14] clk: msm: Add support for MSM8960's global clock controller (GCC)
Quoted 31 lines · Mike Turquette
Quoting Stephen Boyd (2013-08-12 22:03:34)
Quoted 18 lines
The clock controller is hardware and the number of clock outputs is fixed. Isn't all hardware fixed until you start talking about FPGAs? The next minor revision of the clock controller may add more clocks or remove clocks from that base design, but otherwise the two are 90% the same and generally software compatible. It isn't until we start a new generation of chips that we make major changes to the design. Is that loose enough to qualify?
These bindings attempt to follow the regulator bindings. With regulators there is a node for each regulator and we describe physical characteristics of those regulators within the nodes but we don't describe the software interface (bits, masks, shifts, etc). I imagine we could extend these clock nodes to describe physical characteristics such as min/max frequency or if the bootloader has left the clocks on. Right now we're using the nodes to describe what types of clocks there are and how the clock tree is layed out.
Quoted 11 lines
Or perhaps you're talking about clock sharing? We share the clock controller with multiple masters (processors running other OSes) and the partitioning of the clocks is mostly predefined. We just won't use some clocks because they're reserved for other processors. They're still part of the same clock controller hardware block but we don't want to control them on Linux because we'll trample over other processors and most likely hang the system. I wonder how this would work for hexagon and krait both running linux on the same SoC. If all DT says is that there is a gcc here at this address how are we supposed to know that we shouldn't use some clock?
Quoted 5 lines
Do Krait and Hexagon have the same register map? On the ARM SoCs I am familiar with the masters have differing views of register addresses for the same peripherals and hardware blocks. So you couldn't use the same DTS in a straightforward way if this is true for your system.
They both have the same view of the register map.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH 10/14 clk: msm: Add support for MSM8960's multimedia clock controller (MMCC)
In reply to Stephen BoydFill in the data and wire up the multimedia clock controller to the MSM clock driver. This should allow multimedia device drivers to control their clocks on 8960 based platforms.
--- .../devicetree/bindings/clock/qcom,mmcc.txt | 38 ++++++ drivers/clk/msm/Kconfig | 8 ++ drivers/clk/msm/Makefile | 1 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/internal.h | 1 + drivers/clk/msm/mmcc-8960.c | 142 +++++++++++++++++++++ 6 files changed, 193 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt create mode 100644 drivers/clk/msm/mmcc-8960.c
Documentation/devicetree/bindings/clock/qcom,mmcc.txt new file +38 -0
@@ -0,0 +1,38 @@ +MSM Multimedia Clock Controller Binding +----------------------------------------- + +Required properties : +- compatible : shall contain at least "qcom,mmcc" and only one of the + following: + + "qcom,mmcc-8660" + "qcom,mmcc-8960" + +- reg : shall contain base register location and length +- clocks : shall contain clocks supplied by the clock controller + +Example: + clock-controller at 4000000 { + compatible = "qcom,mmcc-8960", "qcom,mmcc"; + reg = <0x4000000 0x1000>; + + clocks { + pll2: pll2 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + mdp_rcg: mdp_rcg { + #clock-cells = <0>; + compatible = "qcom,mn8-dyn-clock"; + clocks = <&pxo>, <&pll2>, <&vpll8>; + }; + + mdp_cxc: mdp_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&mdp_rcg>; + }; + }; + };
drivers/clk/msm/Kconfig +8 -0
@@ -11,4 +11,12 @@ config MSM_GCC_8960 Say Y if you want to use peripheral devices such as UART, SPI, i2c, USB, SD/eMMC, SATA, PCIe, etc. +config MSM_MMCC_8960 + bool "MSM8960 Multimedia Clock Controller" + select MSM_GCC_8960 + help + Support for the multimedia clock controller on msm8960 devices. + Say Y if you want to support multimedia devices such as display, + graphics, video encode/decode, camera, etc. + endif
drivers/clk/msm/Makefile +1 -0
@@ -8,3 +8,4 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.o clk-msm-$(CONFIG_MSM_GCC_8960) += gcc-8960.o +clk-msm-$(CONFIG_MSM_MMCC_8960) += mmcc-8960.o
drivers/clk/msm/core.c +3 -0
@@ -176,6 +176,9 @@ static const struct of_device_id msm_cc_match_table[] = { #ifdef CONFIG_MSM_GCC_8960 { .compatible = "qcom,gcc-8960", .data = &msm_gcc_8960_matches }, #endif +#ifdef CONFIG_MSM_MMCC_8960 + { .compatible = "qcom,mmcc-8960", .data = &msm_mmcc_8960_matches }, +#endif { } }; MODULE_DEVICE_TABLE(of, msm_cc_match_table);
drivers/clk/msm/internal.h +1 -0
@@ -22,5 +22,6 @@ struct msm_clk_match { };extern const struct msm_clk_match msm_gcc_8960_matches; +extern const struct msm_clk_match msm_mmcc_8960_matches;#endif
drivers/clk/msm/mmcc-8960.c new file +142 -0
142 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH v1 10/14] clk: msm: Add support for MSM8960's multimedia clock controller (MMCC)
Hi Stephen,
Quoted 51 lines · Stephen Boyd
Fill in the data and wire up the multimedia clock controller to the MSM clock driver. This should allow multimedia device drivers to control their clocks on 8960 based platforms.
Cc devicetree at vger.kernel.orgSigned-off-by Stephen Boyd <[email protected]>--- .../devicetree/bindings/clock/qcom,mmcc.txt | 38 ++++++ drivers/clk/msm/Kconfig | 8 ++ drivers/clk/msm/Makefile | 1 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/internal.h | 1 + drivers/clk/msm/mmcc-8960.c | 142 +++++++++++++++++++++ 6 files changed, 193 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt create mode 100644 drivers/clk/msm/mmcc-8960.cDocumentation/devicetree/bindings/clock/qcom,mmcc.txt new file +28
-0@@ -0,0 +1,38 @@ +MSM Multimedia Clock Controller Binding +----------------------------------------- + +Required properties : +- compatible : shall contain at least "qcom,mmcc" and only one of the + following: + + "qcom,mmcc-8660" + "qcom,mmcc-8960" + +- reg : shall contain base register location and length +- clocks : shall contain clocks supplied by the clock controller + +Example: + clock-controller at 4000000 { + compatible = "qcom,mmcc-8960", "qcom,mmcc"; + reg = <0x4000000 0x1000>; + + clocks { + pll2: pll2 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + mdp_rcg: mdp_rcg { + #clock-cells = <0>; + compatible = "qcom,mn8-dyn-clock";
Documentation/devicetree/bindings/clock/qcom,mmcc.txt line 38
Quoted 10 lines
Documentation/devicetree/bindings/clock/qcom,mmcc.txt new file +10
-0+ clocks = <&pxo>, <&pll2>, <&vpll8>; + }; + + mdp_cxc: mdp_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&mdp_rcg>; + }; + }; + };
Similar to my comments on the previous patch, this seems odd to me. There's either not enough information in the binding, or there's not enough in the documentation.
Thanks,
Mark.
Quoted 209 lines
drivers/clk/msm/Kconfig +8
-0@@ -11,4 +11,12 @@ config MSM_GCC_8960 Say Y if you want to use peripheral devices such as UART, SPI, i2c, USB, SD/eMMC, SATA, PCIe, etc. +config MSM_MMCC_8960 + bool "MSM8960 Multimedia Clock Controller" + select MSM_GCC_8960 + help + Support for the multimedia clock controller on msm8960 devices. + Say Y if you want to support multimedia devices such as display, + graphics, video encode/decode, camera, etc. + endifdrivers/clk/msm/Makefile +1
-0@@ -8,3 +8,4 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.o clk-msm-$(CONFIG_MSM_GCC_8960) += gcc-8960.o +clk-msm-$(CONFIG_MSM_MMCC_8960) += mmcc-8960.odrivers/clk/msm/core.c +3
-0@@ -176,6 +176,9 @@ static const struct of_device_id msm_cc_match_table[] = { #ifdef CONFIG_MSM_GCC_8960 { .compatible = "qcom,gcc-8960", .data = &msm_gcc_8960_matches }, #endif +#ifdef CONFIG_MSM_MMCC_8960 + { .compatible = "qcom,mmcc-8960", .data = &msm_mmcc_8960_matches }, +#endif { } }; MODULE_DEVICE_TABLE(of, msm_cc_match_table);drivers/clk/msm/internal.h +1
-0@@ -22,5 +22,6 @@ struct msm_clk_match { };extern const struct msm_clk_match msm_gcc_8960_matches; +extern const struct msm_clk_match msm_mmcc_8960_matches;#endif drivers/clk/msm/mmcc-8960.c new file +142
-0@@ -0,0 +1,142 @@ +/* +* Copyright (c) 2013, The Linux Foundation. All rights reserved. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/clk-provider.h> + +#include "internal.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" + +static struct pll_desc pll2_desc = { + .l_reg =0x320 , + .m_reg =0x324 , + .n_reg =0x328 , + .config_reg =0x32c , + .mode_reg =0x31c , + .status_reg =0x334 , + .status_bit =16 , +}; + +#define PXO 0 +#define PLL2 1 +#define PLL8 2 + +static u8 mmcc_pxo_pll2_pll8_map[] = { + [PXO ] =0 , + [PLL2 ] =1 , + [PLL8 ] =2 , +}; + +static struct freq_tbl clk_tbl_mdp[] = { + {9600000 ,PLL8 ,0 ,1 ,40 }, + {13710000 ,PLL8 ,0 ,1 ,28 }, + {27000000 ,PXO ,0 ,0 ,0 }, + {29540000 ,PLL8 ,0 ,1 ,13 }, + {34910000 ,PLL8 ,0 ,1 ,11 }, + {38400000 ,PLL8 ,0 ,1 ,10 }, + {59080000 ,PLL8 ,0 ,2 ,13 }, + {76800000 ,PLL8 ,0 ,1 ,5 }, + {85330000 ,PLL8 ,0 ,2 ,9 }, + {96000000 ,PLL8 ,0 ,1 ,4 }, + {128000000 ,PLL8 ,0 ,1 ,3 }, + {160000000 ,PLL2 ,0 ,1 ,5 }, + {177780000 ,PLL2 ,0 ,2 ,9 }, + {200000000 ,PLL2 ,0 ,1 ,4 }, + {228571000 ,PLL2 ,0 ,2 ,7 }, + {266667000 ,PLL2 ,0 ,1 ,3 }, + { } +}; + +static struct rcg_dyn_desc mdp_rcg = { + .ctl_reg =0xc0 , + .ns_reg =0xd0 , + .md0_reg =0xc4 , + .md1_reg =0xc8 , + .ctl_bit =2 , + .mnctr0_en_bit =8 , + .mnctr1_en_bit =5 , + .mnctr0_reset_bit =31 , + .mnctr1_reset_bit =30 , + .mnctr0_mode_shift =9 , + .mnctr1_mode_shift =6 , + .src0_sel_shift =3 , + .src1_sel_shift =0 , + .n0_val_shift =22 , + .n1_val_shift =14 , + .m0_val_shift =8 , + .m1_val_shift =8 , + .mux_sel_bit =11 , + .parent_map = mmcc_pxo_pll2_pll8_map, + .freq_tbl = clk_tbl_mdp, +}; + +static struct branch_desc mdp_cxc = { + .ctl_reg =0xc0 , + .halt_reg =0x1d0 , + .ctl_bit =0 , + .halt_bit =10 , + .halt_check =BRANCH_HALT , +}; + +static struct freq_tbl clk_tbl_rot[] = { + {27000000 ,PXO ,1 }, + {29540000 ,PLL8 ,13 }, + {32000000 ,PLL8 ,12 }, + {38400000 ,PLL8 ,10 }, + {48000000 ,PLL8 ,8 }, + {54860000 ,PLL8 ,7 }, + {64000000 ,PLL8 ,6 }, + {76800000 ,PLL8 ,5 }, + {96000000 ,PLL8 ,4 }, + {100000000 ,PLL2 ,8 }, + {114290000 ,PLL2 ,7 }, + {133330000 ,PLL2 ,6 }, + {160000000 ,PLL2 ,5 }, + {200000000 ,PLL2 ,4 }, + { } +}; + +static struct rcg_dyn_desc rot_rcg = { + .ctl_reg =0xe0 , + .ns_reg =0xe8 , + .ctl_bit =2 , + .pre_div0_shift =22 , + .pre_div1_shift =26 , + .src0_sel_shift =16 , + .src1_sel_shift =19 , + .mux_sel_bit =30 , + .parent_map = mmcc_pxo_pll2_pll8_map, + .freq_tbl = clk_tbl_rot, +}; + +static struct branch_desc rot_cxc = { + .ctl_reg =0xe0 , + .halt_reg =0x1d0 , + .ctl_bit =0 , + .halt_bit =15 , + .halt_check =BRANCH_HALT , +}; + +static struct of_clk_match msm_mmcc_clk_match[] = { + { .name ="pll2" , .driver_data = &pll2_desc }, + { .name ="mdp_rcg" , .driver_data = &mdp_rcg }, + { .name ="mdp_cxc" , .driver_data = &mdp_cxc }, + { .name ="rot_rcg" , .driver_data = &rot_rcg }, + { .name ="rot_cxc" , .driver_data = &rot_cxc }, +}; + +const struct msm_clk_match msm_mmcc_8960_matches = { + .matches = msm_mmcc_clk_match, + .size =ARRAY_SIZE (msm_mmcc_clk_match) +};Signature · 8 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 11/14 ARM: dts: msm: Add MSM8960 GCC DT nodes
In reply to Stephen BoydAdd the necessary DT data to probe the global clock controller on MSM8960 devices.
--- arch/arm/boot/dts/msm8960-cdp.dts | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
arch/arm/boot/dts/msm8960-cdp.dts +72 -0
@@ -37,6 +37,78 @@ reg = <0xfd510000 0x4000>; }; + clock-controller at 900000 { + compatible = "qcom,gcc-8960", "qcom,gcc"; + reg = <0x900000 0x4000>; + + clocks { + cxo: cxo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <19200000>; + }; + + pxo: pxo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + pll8: pll8 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + vpll8: vpll8 { + #clock-cells = <0>; + compatible = "qcom,pll-vote"; + clocks = <&pll8>; + }; + + gsbi5_uart_rcg: gsbi5_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi5_uart_clk: gsbi5_uart_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_uart_rcg>; + }; + + gsbi6_uart_rcg: gsbi6_uart_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn16-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi6_uart_clk: gsbi6_uart_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi6_uart_rcg>; + }; + + gsbi5_uart_ahb: gsbi5_uart_ahb { + #clock-cells = <0>; + compatible = "qcom,cxc-hg-clock"; + }; + + gsbi5_qup_rcg: gsbi5_qup_rcg { + #clock-cells = <0>; + compatible = "qcom,p2-mn8-clock"; + clocks = <&pxo>, <&vpll8>; + }; + + gsbi5_qup_clk: gsbi5_qup_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&gsbi5_qup_rcg>; + }; + }; + }; + serial at 16440000 { compatible = "qcom,msm-hsuart", "qcom,msm-uart"; reg = <0x16440000 0x1000>,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 12/14 ARM: dts: msm: Add MSM8960 MMCC DT nodes
In reply to Stephen BoydAdd the necessary DT data to probe the multimedia clock controller on MSM8960 devices.
--- arch/arm/boot/dts/msm8960-cdp.dts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
arch/arm/boot/dts/msm8960-cdp.dts +37 -0
@@ -109,6 +109,43 @@ }; }; + clock-controller at 4000000 { + compatible = "qcom,mmcc-8960", "qcom,mmcc"; + reg = <0x4000000 0x1000>; + + clocks { + pll2: pll2 { + #clock-cells = <0>; + compatible = "qcom,pll"; + clocks = <&pxo>; + }; + + mdp_rcg: mdp_rcg { + #clock-cells = <0>; + compatible = "qcom,mn8-dyn-clock"; + clocks = <&pxo>, <&pll2>, <&vpll8>; + }; + + mdp_cxc: mdp_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&mdp_rcg>; + }; + + rot_rcg: rot_rcg { + #clock-cells = <0>; + compatible = "qcom,p4-dyn-clock"; + clocks = <&pxo>, <&pll2>, <&vpll8>; + }; + + rot_cxc: rot_cxc { + #clock-cells = <0>; + compatible = "qcom,cxc-clock"; + clocks = <&rot_rcg>; + }; + }; + }; + serial at 16440000 { compatible = "qcom,msm-hsuart", "qcom,msm-uart"; reg = <0x16440000 0x1000>,
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 13/14 clk: msm: Add MSM8974 GCC data
In reply to Stephen BoydAdd the necessary data to probe an 8974 gcc device.
--- .../devicetree/bindings/clock/qcom,gcc.txt | 1 + drivers/clk/msm/Kconfig | 7 ++ drivers/clk/msm/Makefile | 1 + drivers/clk/msm/core.c | 3 + drivers/clk/msm/gcc-8974.c | 107 +++++++++++++++++++++ drivers/clk/msm/internal.h | 1 + 6 files changed, 120 insertions(+) create mode 100644 drivers/clk/msm/gcc-8974.c
Documentation/devicetree/bindings/clock/qcom,gcc.txt +1 -0
@@ -7,6 +7,7 @@ Required properties : "qcom,gcc-8660" "qcom,gcc-8960" + "qcom,gcc-8974" - reg : shall contain base register location and length - clocks : shall contain clocks supplied by the clock controller
drivers/clk/msm/Kconfig +7 -0
@@ -19,4 +19,11 @@ config MSM_MMCC_8960 Say Y if you want to support multimedia devices such as display, graphics, video encode/decode, camera, etc. +config MSM_GCC_8974 + bool "MSM8974 Global Clock Controller" + help + Support for the global clock controller on msm8974 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + i2c, USB, SD/eMMC, SATA, PCIe, etc. + endif
drivers/clk/msm/Makefile +1 -0
@@ -8,4 +8,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o clk-msm-$(CONFIG_COMMON_CLK_MSM) += core.o clk-msm-$(CONFIG_MSM_GCC_8960) += gcc-8960.o +clk-msm-$(CONFIG_MSM_GCC_8974) += gcc-8974.o clk-msm-$(CONFIG_MSM_MMCC_8960) += mmcc-8960.o
drivers/clk/msm/core.c +3 -0
@@ -176,6 +176,9 @@ static const struct of_device_id msm_cc_match_table[] = { #ifdef CONFIG_MSM_GCC_8960 { .compatible = "qcom,gcc-8960", .data = &msm_gcc_8960_matches }, #endif +#ifdef CONFIG_MSM_GCC_8974 + { .compatible = "qcom,gcc-8974", .data = &msm_gcc_8974_matches }, +#endif #ifdef CONFIG_MSM_MMCC_8960 { .compatible = "qcom,mmcc-8960", .data = &msm_mmcc_8960_matches }, #endif
drivers/clk/msm/gcc-8974.c new file +107 -0
107 lines not on this page · raw message
drivers/clk/msm/internal.h +1 -0
@@ -22,6 +22,7 @@ struct msm_clk_match { };extern const struct msm_clk_match msm_gcc_8960_matches; +extern const struct msm_clk_match msm_gcc_8974_matches;extern const struct msm_clk_match msm_mmcc_8960_matches;#endif
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 14/14 ARM: dts: msm: Add clock entries for MSM8960 uart device
In reply to Stephen Boyd--- arch/arm/boot/dts/msm8960-cdp.dts | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/boot/dts/msm8960-cdp.dts +2 -0
@@ -151,6 +151,8 @@ reg = <0x16440000 0x1000>, <0x16400000 0x1000>; interrupts = <0 154 0x0>; + clocks = <&gsbi5_uart_clk>, <&gsbi5_uart_ahb>; + clock-names = "gsbi_uart_clk", "gsbi_pclk"; }; qcom,ssbi at 500000 {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation