1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PLL clock descriptions for TI DA850/OMAP-L138/AM18XX 4 * 5 * Copyright (C) 2018 David Lechner <david@lechnology.com> 6 */ 7 8 #include <linux/bitops.h> 9 #include <linux/clk-provider.h> 10 #include <linux/clk/davinci.h> 11 #include <linux/clkdev.h> 12 #include <linux/device.h> 13 #include <linux/init.h> 14 #include <linux/io.h> 15 #include <linux/kernel.h> 16 #include <linux/mfd/da8xx-cfgchip.h> 17 #include <linux/mfd/syscon.h> 18 #include <linux/of_address.h> 19 #include <linux/of.h> 20 #include <linux/types.h> 21 22 #include "pll.h" 23 24 #define OCSEL_OCSRC_OSCIN 0x14 25 #define OCSEL_OCSRC_PLL0_SYSCLK(n) (0x16 + (n)) 26 #define OCSEL_OCSRC_PLL1_OBSCLK 0x1e 27 #define OCSEL_OCSRC_PLL1_SYSCLK(n) (0x16 + (n)) 28 29 static const struct davinci_pll_clk_info da850_pll0_info = { 30 .name = "pll0", 31 .unlock_reg = CFGCHIP(0), 32 .unlock_mask = CFGCHIP0_PLL_MASTER_LOCK, 33 .pllm_mask = GENMASK(4, 0), 34 .pllm_min = 4, 35 .pllm_max = 32, 36 .pllout_min_rate = 300000000, 37 .pllout_max_rate = 600000000, 38 .flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV | 39 PLL_HAS_EXTCLKSRC, 40 }; 41 42 /* 43 * NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio", 44 * meaning that we could change the divider as long as we keep the correct 45 * ratio between all of the clocks, but we don't support that because there is 46 * currently not a need for it. 47 */ 48 49 SYSCLK(1, pll0_sysclk1, pll0_pllen, 5, SYSCLK_FIXED_DIV); 50 SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV); 51 SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0); 52 SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV); 53 SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0); 54 SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_ARM_RATE | SYSCLK_FIXED_DIV); 55 SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0); 56 57 static const char * const da850_pll0_obsclk_parent_names[] = { 58 "oscin", 59 "pll0_sysclk1", 60 "pll0_sysclk2", 61 "pll0_sysclk3", 62 "pll0_sysclk4", 63 "pll0_sysclk5", 64 "pll0_sysclk6", 65 "pll0_sysclk7", 66 "pll1_obsclk", 67 }; 68 69 static u32 da850_pll0_obsclk_table[] = { 70 OCSEL_OCSRC_OSCIN, 71 OCSEL_OCSRC_PLL0_SYSCLK(1), 72 OCSEL_OCSRC_PLL0_SYSCLK(2), 73 OCSEL_OCSRC_PLL0_SYSCLK(3), 74 OCSEL_OCSRC_PLL0_SYSCLK(4), 75 OCSEL_OCSRC_PLL0_SYSCLK(5), 76 OCSEL_OCSRC_PLL0_SYSCLK(6), 77 OCSEL_OCSRC_PLL0_SYSCLK(7), 78 OCSEL_OCSRC_PLL1_OBSCLK, 79 }; 80 81 static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info = { 82 .name = "pll0_obsclk", 83 .parent_names = da850_pll0_obsclk_parent_names, 84 .num_parents = ARRAY_SIZE(da850_pll0_obsclk_parent_names), 85 .table = da850_pll0_obsclk_table, 86 .ocsrc_mask = GENMASK(4, 0), 87 }; 88 89 int da850_pll0_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) 90 { 91 struct clk *clk; 92 93 davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base, cfgchip); 94 95 clk = davinci_pll_sysclk_register(dev, &pll0_sysclk1, base); 96 clk_register_clkdev(clk, "pll0_sysclk1", "da850-psc0"); 97 98 clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base); 99 clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc0"); 100 clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc1"); 101 clk_register_clkdev(clk, "pll0_sysclk2", "da850-async3-clksrc"); 102 103 clk = davinci_pll_sysclk_register(dev, &pll0_sysclk3, base); 104 clk_register_clkdev(clk, "pll0_sysclk3", "da850-async1-clksrc"); 105 106 clk = davinci_pll_sysclk_register(dev, &pll0_sysclk4, base); 107 clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc0"); 108 clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc1"); 109 110 davinci_pll_sysclk_register(dev, &pll0_sysclk5, base); 111 112 clk = davinci_pll_sysclk_register(dev, &pll0_sysclk6, base); 113 clk_register_clkdev(clk, "pll0_sysclk6", "da850-psc0"); 114 115 davinci_pll_sysclk_register(dev, &pll0_sysclk7, base); 116 117 davinci_pll_auxclk_register(dev, "pll0_auxclk", base); 118 119 clk = clk_register_fixed_factor(dev, "async2", "pll0_auxclk", 120 CLK_IS_CRITICAL, 1, 1); 121 122 clk_register_clkdev(clk, NULL, "i2c_davinci.1"); 123 clk_register_clkdev(clk, "timer0", NULL); 124 clk_register_clkdev(clk, NULL, "davinci-wdt"); 125 126 davinci_pll_obsclk_register(dev, &da850_pll0_obsclk_info, base); 127 128 return 0; 129 } 130 131 static const struct davinci_pll_sysclk_info *da850_pll0_sysclk_info[] = { 132 &pll0_sysclk1, 133 &pll0_sysclk2, 134 &pll0_sysclk3, 135 &pll0_sysclk4, 136 &pll0_sysclk5, 137 &pll0_sysclk6, 138 &pll0_sysclk7, 139 NULL 140 }; 141 142 void of_da850_pll0_init(struct device_node *node) 143 { 144 void __iomem *base; 145 struct regmap *cfgchip; 146 147 base = of_iomap(node, 0); 148 if (!base) { 149 pr_err("%s: ioremap failed\n", __func__); 150 return; 151 } 152 153 cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); 154 155 of_davinci_pll_init(NULL, node, &da850_pll0_info, 156 &da850_pll0_obsclk_info, 157 da850_pll0_sysclk_info, 7, base, cfgchip); 158 } 159 160 static const struct davinci_pll_clk_info da850_pll1_info = { 161 .name = "pll1", 162 .unlock_reg = CFGCHIP(3), 163 .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, 164 .pllm_mask = GENMASK(4, 0), 165 .pllm_min = 4, 166 .pllm_max = 32, 167 .pllout_min_rate = 300000000, 168 .pllout_max_rate = 600000000, 169 .flags = PLL_HAS_POSTDIV, 170 }; 171 172 SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED); 173 SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, 0); 174 SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, 0); 175 176 static const char * const da850_pll1_obsclk_parent_names[] = { 177 "oscin", 178 "pll1_sysclk1", 179 "pll1_sysclk2", 180 "pll1_sysclk3", 181 }; 182 183 static u32 da850_pll1_obsclk_table[] = { 184 OCSEL_OCSRC_OSCIN, 185 OCSEL_OCSRC_PLL1_SYSCLK(1), 186 OCSEL_OCSRC_PLL1_SYSCLK(2), 187 OCSEL_OCSRC_PLL1_SYSCLK(3), 188 }; 189 190 static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info = { 191 .name = "pll1_obsclk", 192 .parent_names = da850_pll1_obsclk_parent_names, 193 .num_parents = ARRAY_SIZE(da850_pll1_obsclk_parent_names), 194 .table = da850_pll1_obsclk_table, 195 .ocsrc_mask = GENMASK(4, 0), 196 }; 197 198 int da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) 199 { 200 struct clk *clk; 201 202 davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base, cfgchip); 203 204 davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); 205 206 clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base); 207 clk_register_clkdev(clk, "pll1_sysclk2", "da850-async3-clksrc"); 208 209 davinci_pll_sysclk_register(dev, &pll1_sysclk3, base); 210 211 davinci_pll_obsclk_register(dev, &da850_pll1_obsclk_info, base); 212 213 return 0; 214 } 215 216 static const struct davinci_pll_sysclk_info *da850_pll1_sysclk_info[] = { 217 &pll1_sysclk1, 218 &pll1_sysclk2, 219 &pll1_sysclk3, 220 NULL 221 }; 222 223 int of_da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) 224 { 225 return of_davinci_pll_init(dev, dev->of_node, &da850_pll1_info, 226 &da850_pll1_obsclk_info, 227 da850_pll1_sysclk_info, 3, base, cfgchip); 228 } 229