1 /* 2 * Copyright 2014 Chen-Yu Tsai 3 * 4 * Chen-Yu Tsai <wens@csie.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/clk-provider.h> 18 #include <linux/clkdev.h> 19 #include <linux/of.h> 20 #include <linux/of_address.h> 21 #include <linux/log2.h> 22 23 #include "clk-factors.h" 24 25 26 /** 27 * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL4 28 * PLL4 rate is calculated as follows 29 * rate = (parent_rate * n >> p) / (m + 1); 30 * parent_rate is always 24MHz 31 * 32 * p and m are named div1 and div2 in Allwinner's SDK 33 */ 34 35 static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, 36 u8 *n_ret, u8 *k, u8 *m_ret, u8 *p_ret) 37 { 38 int n; 39 int m = 1; 40 int p = 1; 41 42 /* Normalize value to a 6 MHz multiple (24 MHz / 4) */ 43 n = DIV_ROUND_UP(*freq, 6000000); 44 45 /* If n is too large switch to steps of 12 MHz */ 46 if (n > 255) { 47 m = 0; 48 n = (n + 1) / 2; 49 } 50 51 /* If n is still too large switch to steps of 24 MHz */ 52 if (n > 255) { 53 p = 0; 54 n = (n + 1) / 2; 55 } 56 57 /* n must be between 12 and 255 */ 58 if (n > 255) 59 n = 255; 60 else if (n < 12) 61 n = 12; 62 63 *freq = ((24000000 * n) >> p) / (m + 1); 64 65 /* we were called to round the frequency, we can now return */ 66 if (n_ret == NULL) 67 return; 68 69 *n_ret = n; 70 *m_ret = m; 71 *p_ret = p; 72 } 73 74 static struct clk_factors_config sun9i_a80_pll4_config = { 75 .mshift = 18, 76 .mwidth = 1, 77 .nshift = 8, 78 .nwidth = 8, 79 .pshift = 16, 80 .pwidth = 1, 81 }; 82 83 static const struct factors_data sun9i_a80_pll4_data __initconst = { 84 .enable = 31, 85 .table = &sun9i_a80_pll4_config, 86 .getter = sun9i_a80_get_pll4_factors, 87 }; 88 89 static DEFINE_SPINLOCK(sun9i_a80_pll4_lock); 90 91 static void __init sun9i_a80_pll4_setup(struct device_node *node) 92 { 93 void __iomem *reg; 94 95 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 96 if (!reg) { 97 pr_err("Could not get registers for a80-pll4-clk: %s\n", 98 node->name); 99 return; 100 } 101 102 sunxi_factors_register(node, &sun9i_a80_pll4_data, 103 &sun9i_a80_pll4_lock, reg); 104 } 105 CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); 106 107 108 /** 109 * sun9i_a80_get_gt_factors() - calculates m factor for GT 110 * GT rate is calculated as follows 111 * rate = parent_rate / (m + 1); 112 */ 113 114 static void sun9i_a80_get_gt_factors(u32 *freq, u32 parent_rate, 115 u8 *n, u8 *k, u8 *m, u8 *p) 116 { 117 u32 div; 118 119 if (parent_rate < *freq) 120 *freq = parent_rate; 121 122 div = DIV_ROUND_UP(parent_rate, *freq); 123 124 /* maximum divider is 4 */ 125 if (div > 4) 126 div = 4; 127 128 *freq = parent_rate / div; 129 130 /* we were called to round the frequency, we can now return */ 131 if (!m) 132 return; 133 134 *m = div; 135 } 136 137 static struct clk_factors_config sun9i_a80_gt_config = { 138 .mshift = 0, 139 .mwidth = 2, 140 }; 141 142 static const struct factors_data sun9i_a80_gt_data __initconst = { 143 .mux = 24, 144 .muxmask = BIT(1) | BIT(0), 145 .table = &sun9i_a80_gt_config, 146 .getter = sun9i_a80_get_gt_factors, 147 }; 148 149 static DEFINE_SPINLOCK(sun9i_a80_gt_lock); 150 151 static void __init sun9i_a80_gt_setup(struct device_node *node) 152 { 153 void __iomem *reg; 154 struct clk *gt; 155 156 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 157 if (!reg) { 158 pr_err("Could not get registers for a80-gt-clk: %s\n", 159 node->name); 160 return; 161 } 162 163 gt = sunxi_factors_register(node, &sun9i_a80_gt_data, 164 &sun9i_a80_gt_lock, reg); 165 166 /* The GT bus clock needs to be always enabled */ 167 __clk_get(gt); 168 clk_prepare_enable(gt); 169 } 170 CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup); 171 172 173 /** 174 * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 175 * AHB rate is calculated as follows 176 * rate = parent_rate >> p; 177 */ 178 179 static void sun9i_a80_get_ahb_factors(u32 *freq, u32 parent_rate, 180 u8 *n, u8 *k, u8 *m, u8 *p) 181 { 182 u32 _p; 183 184 if (parent_rate < *freq) 185 *freq = parent_rate; 186 187 _p = order_base_2(DIV_ROUND_UP(parent_rate, *freq)); 188 189 /* maximum p is 3 */ 190 if (_p > 3) 191 _p = 3; 192 193 *freq = parent_rate >> _p; 194 195 /* we were called to round the frequency, we can now return */ 196 if (!p) 197 return; 198 199 *p = _p; 200 } 201 202 static struct clk_factors_config sun9i_a80_ahb_config = { 203 .pshift = 0, 204 .pwidth = 2, 205 }; 206 207 static const struct factors_data sun9i_a80_ahb_data __initconst = { 208 .mux = 24, 209 .muxmask = BIT(1) | BIT(0), 210 .table = &sun9i_a80_ahb_config, 211 .getter = sun9i_a80_get_ahb_factors, 212 }; 213 214 static DEFINE_SPINLOCK(sun9i_a80_ahb_lock); 215 216 static void __init sun9i_a80_ahb_setup(struct device_node *node) 217 { 218 void __iomem *reg; 219 220 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 221 if (!reg) { 222 pr_err("Could not get registers for a80-ahb-clk: %s\n", 223 node->name); 224 return; 225 } 226 227 sunxi_factors_register(node, &sun9i_a80_ahb_data, 228 &sun9i_a80_ahb_lock, reg); 229 } 230 CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); 231 232 233 static const struct factors_data sun9i_a80_apb0_data __initconst = { 234 .mux = 24, 235 .muxmask = BIT(0), 236 .table = &sun9i_a80_ahb_config, 237 .getter = sun9i_a80_get_ahb_factors, 238 }; 239 240 static DEFINE_SPINLOCK(sun9i_a80_apb0_lock); 241 242 static void __init sun9i_a80_apb0_setup(struct device_node *node) 243 { 244 void __iomem *reg; 245 246 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 247 if (!reg) { 248 pr_err("Could not get registers for a80-apb0-clk: %s\n", 249 node->name); 250 return; 251 } 252 253 sunxi_factors_register(node, &sun9i_a80_apb0_data, 254 &sun9i_a80_apb0_lock, reg); 255 } 256 CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); 257 258 259 /** 260 * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 261 * APB1 rate is calculated as follows 262 * rate = (parent_rate >> p) / (m + 1); 263 */ 264 265 static void sun9i_a80_get_apb1_factors(u32 *freq, u32 parent_rate, 266 u8 *n, u8 *k, u8 *m, u8 *p) 267 { 268 u32 div; 269 u8 calcm, calcp; 270 271 if (parent_rate < *freq) 272 *freq = parent_rate; 273 274 div = DIV_ROUND_UP(parent_rate, *freq); 275 276 /* Highest possible divider is 256 (p = 3, m = 31) */ 277 if (div > 256) 278 div = 256; 279 280 calcp = order_base_2(div); 281 calcm = (parent_rate >> calcp) - 1; 282 *freq = (parent_rate >> calcp) / (calcm + 1); 283 284 /* we were called to round the frequency, we can now return */ 285 if (n == NULL) 286 return; 287 288 *m = calcm; 289 *p = calcp; 290 } 291 292 static struct clk_factors_config sun9i_a80_apb1_config = { 293 .mshift = 0, 294 .mwidth = 5, 295 .pshift = 16, 296 .pwidth = 2, 297 }; 298 299 static const struct factors_data sun9i_a80_apb1_data __initconst = { 300 .mux = 24, 301 .muxmask = BIT(0), 302 .table = &sun9i_a80_apb1_config, 303 .getter = sun9i_a80_get_apb1_factors, 304 }; 305 306 static DEFINE_SPINLOCK(sun9i_a80_apb1_lock); 307 308 static void __init sun9i_a80_apb1_setup(struct device_node *node) 309 { 310 void __iomem *reg; 311 312 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 313 if (!reg) { 314 pr_err("Could not get registers for a80-apb1-clk: %s\n", 315 node->name); 316 return; 317 } 318 319 sunxi_factors_register(node, &sun9i_a80_apb1_data, 320 &sun9i_a80_apb1_lock, reg); 321 } 322 CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup); 323