Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: renesas: cpg-mssr: Add support for fixing up clock tables

The same SoC may have different clocks and/or module clock parents,
depending on SoC revision. One option is to use different sets of clock
tables for each SoC revision. However, if the differences are small, it
is much more space-efficient to have a single set of clock tables, and
fix those up at runtime instead.

Hence provide three helpers:
- Two helpers to NULLify core and module clocks that do not exist on
some revisions (NULLified clocks are skipped during the registration
phase),
- One helper to reparent module clocks that have different clock
parents.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>

+72
+50
drivers/clk/renesas/renesas-cpg-mssr.c
··· 265 265 WARN_DEBUG(id >= priv->num_core_clks); 266 266 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); 267 267 268 + if (!core->name) { 269 + /* Skip NULLified clock */ 270 + return; 271 + } 272 + 268 273 switch (core->type) { 269 274 case CLK_TYPE_IN: 270 275 clk = of_clk_get_by_name(priv->dev->of_node, core->name); ··· 339 334 WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); 340 335 WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); 341 336 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); 337 + 338 + if (!mod->name) { 339 + /* Skip NULLified clock */ 340 + return; 341 + } 342 342 343 343 parent = priv->clks[mod->parent]; 344 344 if (IS_ERR(parent)) { ··· 743 733 } 744 734 745 735 subsys_initcall(cpg_mssr_init); 736 + 737 + void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks, 738 + unsigned int num_core_clks, 739 + unsigned int first_clk, 740 + unsigned int last_clk) 741 + { 742 + unsigned int i; 743 + 744 + for (i = 0; i < num_core_clks; i++) 745 + if (core_clks[i].id >= first_clk && 746 + core_clks[i].id <= last_clk) 747 + core_clks[i].name = NULL; 748 + } 749 + 750 + void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks, 751 + unsigned int num_mod_clks, 752 + const unsigned int *clks, unsigned int n) 753 + { 754 + unsigned int i, j; 755 + 756 + for (i = 0, j = 0; i < num_mod_clks && j < n; i++) 757 + if (mod_clks[i].id == clks[j]) { 758 + mod_clks[i].name = NULL; 759 + j++; 760 + } 761 + } 762 + 763 + void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks, 764 + unsigned int num_mod_clks, 765 + const struct mssr_mod_reparent *clks, 766 + unsigned int n) 767 + { 768 + unsigned int i, j; 769 + 770 + for (i = 0, j = 0; i < num_mod_clks && j < n; i++) 771 + if (mod_clks[i].id == clks[j].clk) { 772 + mod_clks[i].parent = clks[j].parent; 773 + j++; 774 + } 775 + } 746 776 747 777 MODULE_DESCRIPTION("Renesas CPG/MSSR Driver"); 748 778 MODULE_LICENSE("GPL v2");
+22
drivers/clk/renesas/renesas-cpg-mssr.h
··· 134 134 extern const struct cpg_mssr_info r8a7745_cpg_mssr_info; 135 135 extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; 136 136 extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; 137 + 138 + 139 + /* 140 + * Helpers for fixing up clock tables depending on SoC revision 141 + */ 142 + 143 + struct mssr_mod_reparent { 144 + unsigned int clk, parent; 145 + }; 146 + 147 + 148 + extern void cpg_core_nullify_range(struct cpg_core_clk *core_clks, 149 + unsigned int num_core_clks, 150 + unsigned int first_clk, 151 + unsigned int last_clk); 152 + extern void mssr_mod_nullify(struct mssr_mod_clk *mod_clks, 153 + unsigned int num_mod_clks, 154 + const unsigned int *clks, unsigned int n); 155 + extern void mssr_mod_reparent(struct mssr_mod_clk *mod_clks, 156 + unsigned int num_mod_clks, 157 + const struct mssr_mod_reparent *clks, 158 + unsigned int n); 137 159 #endif