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

bus: ti-sysc: Add handling for clkctrl opt clocks

There can be up to eight optional device functional gate gate clocks for
each clkctrl instance in clkctrl register bits 8 to 15. Some of them are
only needed for module level reset while others may always be needed
during use. Let's add support for those and update the binding doc
accordingly.

Note that the optional clkctrl mux and divider clocks starting at bit 20
can be directly mapped to the child devices, and ti-sysc does not need to
manage those.

And as GPIOs need the optional clocks for reset, we can now add it with
SYSC_QUIRK_OPT_CLKS_IN_RESET.

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Tero Kristo <t-kristo@ti.com>
Cc: devicetree@vger.kernel.org
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>

+120 -26
+5 -1
Documentation/devicetree/bindings/bus/ti-sysc.txt
··· 79 79 mode as for example omap4 L4_CFG_CLKCTRL 80 80 81 81 - clock-names should contain at least "fck", and optionally also "ick" 82 - depending on the SoC and the interconnect target module 82 + depending on the SoC and the interconnect target module, 83 + some interconnect target modules also need additional 84 + optional clocks that can be specified as listed in TRM 85 + for the related CLKCTRL register bits 8 to 15 such as 86 + "dbclk" or "clk32k" depending on their role 83 87 84 88 - ti,hwmods optional TI interconnect module name to use legacy 85 89 hwmod platform data
+115 -25
drivers/bus/ti-sysc.c
··· 32 32 enum sysc_clocks { 33 33 SYSC_FCK, 34 34 SYSC_ICK, 35 + SYSC_OPTFCK0, 36 + SYSC_OPTFCK1, 37 + SYSC_OPTFCK2, 38 + SYSC_OPTFCK3, 39 + SYSC_OPTFCK4, 40 + SYSC_OPTFCK5, 41 + SYSC_OPTFCK6, 42 + SYSC_OPTFCK7, 35 43 SYSC_MAX_CLOCKS, 36 44 }; 37 45 38 - static const char * const clock_names[] = { "fck", "ick", }; 46 + static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", }; 39 47 40 48 #define SYSC_IDLEMODE_MASK 3 41 49 #define SYSC_CLOCKACTIVITY_MASK 3 ··· 56 48 * @module_va: virtual address of the interconnect target module 57 49 * @offsets: register offsets from module base 58 50 * @clocks: clocks used by the interconnect target module 51 + * @clock_roles: clock role names for the found clocks 52 + * @nr_clocks: number of clocks used by the interconnect target module 59 53 * @legacy_mode: configured for legacy mode if set 60 54 * @cap: interconnect target module capabilities 61 55 * @cfg: interconnect target module configuration ··· 71 61 u32 module_size; 72 62 void __iomem *module_va; 73 63 int offsets[SYSC_MAX_REGS]; 74 - struct clk *clocks[SYSC_MAX_CLOCKS]; 64 + struct clk **clocks; 65 + const char **clock_roles; 66 + int nr_clocks; 75 67 const char *legacy_mode; 76 68 const struct sysc_capabilities *cap; 77 69 struct sysc_config cfg; ··· 100 88 return readl_relaxed(ddata->module_va + offset); 101 89 } 102 90 91 + static bool sysc_opt_clks_needed(struct sysc *ddata) 92 + { 93 + return !!(ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_NEEDED); 94 + } 95 + 103 96 static u32 sysc_read_revision(struct sysc *ddata) 104 97 { 105 98 int offset = ddata->offsets[SYSC_REVISION]; ··· 115 98 return sysc_read(ddata, offset); 116 99 } 117 100 118 - static int sysc_get_one_clock(struct sysc *ddata, 119 - enum sysc_clocks index) 101 + static int sysc_get_one_clock(struct sysc *ddata, const char *name) 120 102 { 121 - const char *name; 122 - int error; 103 + int error, i, index = -ENODEV; 123 104 124 - switch (index) { 125 - case SYSC_FCK: 126 - break; 127 - case SYSC_ICK: 128 - break; 129 - default: 130 - return -EINVAL; 105 + if (!strncmp(clock_names[SYSC_FCK], name, 3)) 106 + index = SYSC_FCK; 107 + else if (!strncmp(clock_names[SYSC_ICK], name, 3)) 108 + index = SYSC_ICK; 109 + 110 + if (index < 0) { 111 + for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) { 112 + if (!clock_names[i]) { 113 + index = i; 114 + break; 115 + } 116 + } 131 117 } 132 - name = clock_names[index]; 118 + 119 + if (index < 0) { 120 + dev_err(ddata->dev, "clock %s not added\n", name); 121 + return index; 122 + } 133 123 134 124 ddata->clocks[index] = devm_clk_get(ddata->dev, name); 135 125 if (IS_ERR(ddata->clocks[index])) { ··· 162 138 163 139 static int sysc_get_clocks(struct sysc *ddata) 164 140 { 165 - int i, error; 141 + struct device_node *np = ddata->dev->of_node; 142 + struct property *prop; 143 + const char *name; 144 + int nr_fck = 0, nr_ick = 0, i, error = 0; 166 145 167 - for (i = 0; i < SYSC_MAX_CLOCKS; i++) { 168 - error = sysc_get_one_clock(ddata, i); 146 + ddata->clock_roles = devm_kzalloc(ddata->dev, 147 + sizeof(*ddata->clock_roles) * 148 + SYSC_MAX_CLOCKS, 149 + GFP_KERNEL); 150 + if (!ddata->clock_roles) 151 + return -ENOMEM; 152 + 153 + of_property_for_each_string(np, "clock-names", prop, name) { 154 + if (!strncmp(clock_names[SYSC_FCK], name, 3)) 155 + nr_fck++; 156 + if (!strncmp(clock_names[SYSC_ICK], name, 3)) 157 + nr_ick++; 158 + ddata->clock_roles[ddata->nr_clocks] = name; 159 + ddata->nr_clocks++; 160 + } 161 + 162 + if (ddata->nr_clocks < 1) 163 + return 0; 164 + 165 + if (ddata->nr_clocks > SYSC_MAX_CLOCKS) { 166 + dev_err(ddata->dev, "too many clocks for %pOF\n", np); 167 + 168 + return -EINVAL; 169 + } 170 + 171 + if (nr_fck > 1 || nr_ick > 1) { 172 + dev_err(ddata->dev, "max one fck and ick for %pOF\n", np); 173 + 174 + return -EINVAL; 175 + } 176 + 177 + ddata->clocks = devm_kzalloc(ddata->dev, 178 + sizeof(*ddata->clocks) * ddata->nr_clocks, 179 + GFP_KERNEL); 180 + if (!ddata->clocks) 181 + return -ENOMEM; 182 + 183 + for (i = 0; i < ddata->nr_clocks; i++) { 184 + error = sysc_get_one_clock(ddata, ddata->clock_roles[i]); 169 185 if (error && error != -ENOENT) 170 186 return error; 171 187 } ··· 597 533 goto idled; 598 534 } 599 535 600 - for (i = 0; i < SYSC_MAX_CLOCKS; i++) { 536 + for (i = 0; i < ddata->nr_clocks; i++) { 601 537 if (IS_ERR_OR_NULL(ddata->clocks[i])) 602 538 continue; 539 + 540 + if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata)) 541 + break; 542 + 603 543 clk_disable(ddata->clocks[i]); 604 544 } 605 545 ··· 640 572 goto awake; 641 573 } 642 574 643 - for (i = 0; i < SYSC_MAX_CLOCKS; i++) { 575 + for (i = 0; i < ddata->nr_clocks; i++) { 644 576 if (IS_ERR_OR_NULL(ddata->clocks[i])) 645 577 continue; 578 + 579 + if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata)) 580 + break; 581 + 646 582 error = clk_enable(ddata->clocks[i]); 647 583 if (error) 648 584 return error; ··· 723 651 static const struct sysc_revision_quirk sysc_revision_quirks[] = { 724 652 /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ 725 653 SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffffffff, 726 - SYSC_QUIRK_LEGACY_IDLE), 654 + SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET), 727 655 SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000020, 0xffffffff, 728 656 SYSC_QUIRK_LEGACY_IDLE), 729 657 SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000030, 0xffffffff, ··· 917 845 return error; 918 846 } 919 847 848 + static int sysc_child_add_clocks(struct sysc *ddata, 849 + struct device *child) 850 + { 851 + int i, error; 852 + 853 + for (i = 0; i < ddata->nr_clocks; i++) { 854 + error = sysc_child_add_named_clock(ddata, 855 + child, 856 + ddata->clock_roles[i]); 857 + if (error && error != -EEXIST) { 858 + dev_err(ddata->dev, "could not add child clock %s: %i\n", 859 + ddata->clock_roles[i], error); 860 + 861 + return error; 862 + } 863 + } 864 + 865 + return 0; 866 + } 867 + 920 868 static struct device_type sysc_device_type = { 921 869 }; 922 870 ··· 1084 992 1085 993 switch (event) { 1086 994 case BUS_NOTIFY_ADD_DEVICE: 1087 - error = sysc_child_add_named_clock(ddata, dev, 1088 - clock_names[SYSC_FCK]); 1089 - if (error && error != -EEXIST) 1090 - dev_warn(ddata->dev, "could not add %s fck: %i\n", 1091 - dev_name(dev), error); 995 + error = sysc_child_add_clocks(ddata, dev); 996 + if (error) 997 + return error; 1092 998 sysc_legacy_idle_quirk(ddata, dev); 1093 999 break; 1094 1000 default: